美文网首页
事务并发

事务并发

作者: 妖云小离 | 来源:发表于2018-09-17 11:59 被阅读0次

事务并发产生的四个问题

更新丢失

当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题——最后的更新覆盖了由其他事务所做的更新。

clipboard.png

脏读

一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫做"脏读"。

image.png

不可重复读

一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不可重复读”。

image.png

幻读

错误的理解:
一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。
这其实并不是幻读,这是不可重复读的一种,只会在 R-U R-C 级别下出现,而在 mysql 默认的 RR 隔离级别是不会出现的。
解决不可重复读使用的是一致性读模式,通过快照的方式,使得事务内的select只会以第一次查询为基准。
事实是,在RR级别下,如果事务A的两个select操作中间不穿插更新、删除、插入操作,那么即使别的事实B有更新、删除、插入操作,并且已经提交。事物A在事务B提交后的,第二次select操作所得到的查询结果,与第一次相同。(如果以上述错误的理解为准,那RR级别不就不存在幻读了?)

image.png

正确的理解:

重现更新丢失问题(错误的理解)

第一步:

我在数据库造了一条数据,如下图:

image.png

解释一下,

字段名 备注
id 唯一标识
num 计数器

第二步:

写一个事务

image.png

在事务中,分为三个步骤:

  1. 获取这条数据
  2. 对num加一
  3. 更新这条数据

第三步:

多线程并行执行10次事务

image.png

第四步:

多次执行,查看结果

image.png

运行三次,每次结果都不同(每次运行完都把计数器置零),但都没加到10,即存在更新丢失问题。

事务的隔离级别

MySQL/InnoDB定义的4种隔离级别:

  • Read Uncommited
    读未提交:一个事务可以读取到另一个事务未提交的修改。这会带来脏读、幻读、不可重复读问题。(基本没用)

  • Read Committed (RC)
    读已提交:一个事务只能读取另一个事务已经提交的修改。其避免了脏读,但仍然存在不可重复读和幻读问题。

  • Repeatable Read (RR)
    可重复读:同一个事务中多次读取相同的数据返回的结果是一样的。其避免了脏读和不可重复读问题,但幻读依然存在。

  • Serializable
    串行化:从MVCC并发控制退化为基于锁的并发控制。不区别快照读与当前读,所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)。事务串行执行。避免了以上所有问题。
    Serializable隔离级别下,读写冲突,因此并发度急剧下降,在MySQL/InnoDB下不建议使用。

于是我尝试提高事务的隔离级别到Serializable来防止更新丢失

image.png

执行上述多线程并发加程序时,缺发生了数据库死锁问题:

image.png

究其原因,是SERIALIZABLE隔离级别读写锁竞争导致的。

在SERIALIZABLE级别下,不会使用mysql的mvcc机制,而是在每一个select请求下获得读锁,在每一个update操作下尝试获得写锁。

在我们的例子中,在level_1中,事务A获得了id = 1的读锁A。

而在同时,事务B获得id = 1的读锁B。

在事务A level_2时,事务A尝试获得id = 1的写锁,这个时候,由于id = 1处不仅有事务A的读锁,还有事务B的读锁,因此事务A的update操作获取锁被阻塞。

此时,当事务B继续执行update操作时,由于事务A又拥有id = 1的读锁A,因此进入互相等待状态,造成死锁。

解决方案:

1 将select操作改为select for update,直接加写锁。

2 在业务层将此种类事务串行化。

相关文章

  • MySQL进阶之InnoDB引擎的锁处理

    事务 InnoDB支持事务也就是ACID原子性,一致性,隔离性,持久性。 并发事务 优势: 并发事务能大大增加数...

  • 事务并发

    事务并发产生的四个问题 更新丢失 当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道...

  • MySQL多版本并发控制 - MVCC

    并发控制 实现事务隔离的机制,称之为并发控制 所谓并发控制,就是保证并发执行的事务在某一隔离级别上的正确执行的机制...

  • 数据库事务--事务隔离级别

    数据库里关于事务的并发问题,也叫做竞态条件(race condition)。它是描述并发事务中,一个事务需要读取另...

  • Hibernate之事务管理

    一、事务并发问题 数据库没有做任何并发处理的情况下有5类事务并发问题 A:第一类丢失更新:两个事务更新相同数据,如...

  • Mysql神乎乎的MVCC到底该怎么理解

    引言 MVCC即多版本并发控制主要是为了解决数据库中并发事务读写的一致性问题,那么多个事务并发执行的时候事务的隔离...

  • 事务的隔离、传播、回滚

    springboot之事务的隔离与传播 事务的隔离 多个事务是并发的访问数据库,并发是必须的但会带来几个问题: 脏...

  • 浅谈ACID的I

    隔离性: 事务的隔离性是指在并发环境中,并发的事务是相互隔离的,一个事务的执行不能被其它事务干扰。就是说,不同的事...

  • Maridb中的事务

    今天对mariadb事务并发的五类问题,进行了测试,结果得到以下的结论 事务并发5类问题(如果数据库没有做任何并发...

  • MySQL 中的锁(一)

    并发事务访问相同记录的情况大致可以划分为3种: 读-读并发事务读取相同的事务记录,读取操作本身不会对记录有任何影响...

网友评论

      本文标题:事务并发

      本文链接:https://www.haomeiwen.com/subject/ecgknftx.html