Mysql对于事务并发处理带来的问题,脏读、不可重复读、幻读的理解

本文主要是介绍Mysql对于事务并发处理带来的问题,脏读、不可重复读、幻读的理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、缘由

  众所周知MySQL从5.5.8开始,Innodb就是默认的存储引擎,Innodb最大的特点是:支持事务、支持行级锁。既然支持事务,那么就会有处理并发事务带来的问题:更新丢失、脏读、不可重复读、幻读;相应的为了解决这四个问题,就产生了事务隔离级别:未提交读(Read uncommitted),已提交读(Read committed),可重复读(Repeatable read),可序列化(Serializable)。

  之前在看事务隔离级别的时候,基本是一知半解。再次碰到,还是浆糊,所以这里打算彻底搞明白、清楚,也好后续的学习。

 

二、解决办法:

1、概念说明:   

  更新丢失:最后的更新覆盖了其他事务之前的更新,而事务之间并不知道,发生更新丢失。更新丢失,可以完全避免,应用对访问的数据加锁即可。

  脏读:(针对未提交的数据)一个事务在更新一条记录,未提交前,第二个事务读到了第一个事务更新后的记录,那么第二个事务就读到了脏数据,会产生对第一个未提交数据的依赖。一旦第一个事务回滚,那么第二个事务读到的数据,将是错误的脏数据。

  不可重复读:(读取数据本身的对比)一个事务在读取某些数据后的一段时间后,再次读取这个数据,发现其读取出来的数据内容已经发生了改变,就是不可重复读。

  幻读:(读取结果集条数的对比)一个事务按相同的查询条件查询之前检索过的数据,确发现检索出来的结果集条数变多或者减少(由其他事务插入、删除的),类似产生幻觉。

 

2、不可重复读和幻读的区别:

不可重复读

重点是修改:同样的条件下,你读取过的数据,再次读取发现值不一样了。

例子:(只是为了说明区别,没有事务隔离级别约束)

事务1:Jack读取自己的工资为1000,事务并没有结束:

select salary from employee empId ="Jack"; 

 

事务2:财务人员修改了Jack的工资为2000,并提交事务(事务1不知道):

update employee set salary = 2000;

commit;

在事务1中,再次读取Jack的工资时,工资变为2000

select salary from employee empId ="Jack";

在一个事务中前后两次读取的结果值并不一致,导致了不可重读读

 

幻读

重点在于新增或者删除(数据条数的变化):同样条件下,第一次和第二次读出来的记录条数不一样。

例子:

目前工资为1000的员工有10人。

事务1:读取所有工资为1000的员工,事务进行中

select count(*) from employee where salary = 1000;

共读取到10条记录。

事务2:同时插入一条新的员工记录,工资也为1000

insert into employee(empId, salary) values('Tom', 1000);

commit;

事务1:再次读取所有工资为1000的员工

select count(*) from employee where salary = 1000;

共读取到了11条记录,这样就像产生了幻读。

 

三、事务隔离级别:

  并发处理带来的问题中,更新丢失可以完全避免,由应用对数据加锁即可。脏读、不可重读度、幻读,其实都是数据库的一致性问题,必须由一定的事务隔离机制来解决。其中一种方法是:不用加锁,通过一定的机制生成一个数据请求时间点的一致性快照,并用这个快照来提供一个界别的一致性读取。从用户的角度看,好像是数据库提偶拱了统一数据的多个版本。这种技术叫做:数据库多版本并发控制,MVCC 多版本数据库。

  事务隔离的本质是使事务在一定程度上串行化执行,显然和并发机制是矛盾的。数据库的事务隔离越严格,并发负作用越小,代价越高(影响并发访问了呗)。

  为了解决隔离和并大的矛盾,IOS SQL92规定了4个隔离级别。(隔离==串行

 

MySQL 默认的级别是:Repeatable read 可重复读。

这篇关于Mysql对于事务并发处理带来的问题,脏读、不可重复读、幻读的理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/579448

相关文章

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

SpringKafka消息发布之KafkaTemplate与事务支持功能

《SpringKafka消息发布之KafkaTemplate与事务支持功能》通过本文介绍的基本用法、序列化选项、事务支持、错误处理和性能优化技术,开发者可以构建高效可靠的Kafka消息发布系统,事务支... 目录引言一、KafkaTemplate基础二、消息序列化三、事务支持机制四、错误处理与重试五、性能优

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.

Spring事务中@Transactional注解不生效的原因分析与解决

《Spring事务中@Transactional注解不生效的原因分析与解决》在Spring框架中,@Transactional注解是管理数据库事务的核心方式,本文将深入分析事务自调用的底层原理,解释为... 目录1. 引言2. 事务自调用问题重现2.1 示例代码2.2 问题现象3. 为什么事务自调用会失效3