MySQL 事务隔离级别会产生的并发问题?

本文阅读 4 分钟
首页 Mysql 正文

事务定义了四种事务隔离级别,不同数据库在实现时,产生的并发问题是不同的。

不同的隔离级别有不同的现象,并有不同的锁定/并发机制,隔离级别越高,数据库的并发性就越差。
  • READ UNCOMMITTED(未提交读):事务中的修改,即使没有提交,对其他事务也都是可见的。

    会导致脏读。
  • READ COMMITTED(提交读):事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。

    会导致不可重复读。

    这个隔离级别,也可以叫做“不可重复读”。

  • REPEATABLE READ(可重复读):一个事务按相同的查询条件读取以前检索过的数据,其他事务插入了满足其查询条件的新数据。产生幻行。

    会导致幻读。
  • SERIALIZABLE(可串行化):强制事务串行执行。

MySQL InnoDB 采用 MVCC 来支持高并发,实现结果如下表所示:

关于 Oracle 和 PostgreSQL ,需要胖友自己去搜索资料。
事务隔离级别脏读不可重复读幻读
读未提交(read-uncommitted)
读已提交(read-committed)
可重复读(repeatable-read)是(x)
串行化(serializable)
  • ? 记住这个表的方式,我们会发现它是自左上向右下是一个对角线。当然,最好是去理解。
  • 具体的实验,胖友可以看看 《MySQL 的四种事务隔离级别》
  • 有些资料说可重复读解决了幻读,实际是存在的,可以通过 SELECT xxx FROM t WHERE id = ? FOR UPDATE 的方式,获得到悲观锁,禁止其它事务操作对应的数据,从而解决幻读问题。感兴趣的胖友,可以看看如下文章:

    • 必读 《MySQL 幻读的详解、实例及解决办法》 案例性更强,易懂。

      其实 RR 也是可以避免幻读的,通过对 select 操作手动加 行X锁(SELECT … FOR UPDATE 这也正是 SERIALIZABLE 隔离级别下会隐式为你做的事情),同时还需要知道,即便当前记录不存在,比如 id = 1 是不存在的,当前事务也会获得一把记录锁(因为InnoDB的行锁锁定的是索引,故记录实体存在与否没关系,存在就加 行X锁,不存在就加 next-key lock间隙X锁),其他事务则无法插入此索引的记录,故杜绝了幻读。
    • 选读 《MySQL 的 InnoDB 的幻读问题》 原理性更强,读懂会很爽。
    • 随意 《Innodb 中 RR 隔离级别能否防止幻读?》 一个简单的讨论。
本文来自投稿,不代表本站立场,如若转载,请注明出处:
如何解决分布式事务?
« 上一篇 09-17
Kubernetes组件
下一篇 » 09-25

发表评论

发表评论