阅读 194

MySQL事务隔离

事务的基本属性(ACID):

  • 原子性(Atomicity):事务是一个原子单位,要么全部执行,要么全部不执行
  • 一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏。
  • 隔离性(Isolation):并发的事务是相互隔离的。
  • 持久性(Durability):事务完成后,该事务所对数据库所做的更改持久的保存在数据库之中,并不会被回滚。

事务的并发问题:

脏读:读取了未提交的数据。例如事务1修改某个字段的值,但未commit到数据库,然后事务2读取了该值,后来事务1撤销了对该字段的更新或者是更改该字段的值才commit到数据库。这样事务2读到的就是脏数据。

不可重复读:在数据库访问中,一个事务范围内的两次相同的查询却返回了不同的数据。例如事务1读取了某一数据,事务2读取并修改了该数据,事务1为了对读取值进行验证而重新读取,却得到了不同的结果。

幻读:事务1对表中的数据进行修改,修改涉及了表中全部的数据行。同时,事务2想这个表插入了一行新数据。操作事务1的用户就会发现表中还有没有修改的数据行,仿佛出现了幻觉一样。

MySQL事务隔离级别


MySQL默认的事务隔离级别为repeatable read(可重复读)。

读未提交

事务的最低隔离级别,在这种隔离级别下,一个事务可以读取另一个事务未提交的数据。

例子:事务1设置隔离级别为读未提交,查询user表数据。


事务2设置隔离级别为读未提交,修改user表id为1的score。


事务1能够查询到事务2修改的数据。


事务2对表进行了回滚,撤销修改。


事务1不知道事务2进行了回滚,此时事务1读到的数据为脏数据。然后事务1对表数据进行了修改。在事务1看来 score 应该为 60+50=110,但是修改后操作为60,数据不一致。


读已提交

在一个事务修改数据过程中,如果该事务还没提交,其他事务不能读取该数据。

例子:事务2对表中的数据进行修改,并提交。


事务1对表的两次查询数据不一致,即产生了不可重复读的问题。


在事务2修改表中数据但又未提交事务时,mysql对该字段增加了x锁,事务1不可修改数据。直到事务2提交事务后,事务1才能对该字段进行修改。


可重复读

在同一个事务内的查询都是事务开始时刻一致的。

例子:事务1设置隔离级别为repeatable read,并查询数据。


事务2设置隔离级别,更改数据并提交。


事务1再次查询表数据,表数据不变。解决了不可重复读问题,但不能解决幻读


串行化

事务每次读操作都需要获得表级共享锁,读写相互都会阻塞。

例子:事务1查询表数据


事务2对表数据可读,但不可读写。因此不会出现幻读的情况。


总结:

  1. 隔离级别为读可提交时,写数据会锁住相应的行。
  2. 隔离级别为可重复读时,如果检索条件有索引(包括主键索引)的时候,默认加锁方式是next-key 锁;如果检索条件没有索引,更新数据时会锁住整张表。一个间隙被事务加了锁,其他事务是不能在这个间隙插入记录的,这样可以防止幻读。
  3. 隔离级别为串行化时,读写数据都会锁住整张表。

参考资料:

MySQL的四种事务隔离级别

MySQL 四种事务隔离级的说明


关注下面的标签,发现更多相似文章
评论