MySQL 事务 和 锁、MVCC 的关系

官网保平安:https://www.mysql.com/
MySQL 思维导图:https://www.processon.com/view/link/63bc2c8ea82ed9463ba99f38

事务共有四个级别

  • 未提交读(Read Uncommitted, RU):允许脏读,其他事务只要修改了数据,即使未提交,本事务也能看到修改后的数据值。也就是可能读取到其他会话中未提交事务修改的数据。
  • 提交读(Read Committed, RC):只能读取到已经提交的数据。
  • 可重复读(Repeated Read, RR):可重复读。无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响。
  • 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。

数据库并发场景一般有三种:

  • 【读-读】:不存在任何问题,不需要并发控制。

  • 【读-写】:有线程安全问题,可能会造成事务隔离性问题,可能会有脏读,幻读,不可重复读。

    InnoDB 实现的 REPEATABLE-READ 隔离级别其实是可以解决幻读问题发生的,主要有下面两种情况:

    • 快照读:由 MVCC 机制来保证不出现幻读。
    • 当前读:使用 Next-Key Lock 进行加锁来保证不出现幻读,Next-Key Lock 是行锁(Record Lock)和间隙锁(Gap Lock)的结合,行锁只能锁住已经存在的行,为了避免插入新行,需要依赖间隙锁。
  • 【写-写】:有线程安全问题,可能会存在更新丢失问题。

    • 【写-写】问题怎么解决呢,就需要用到 锁 了。

总结:一般数据库中都会采用 MVCC+锁 的种组合来解决并发场景的问题,以此最大限度的提高数据库性能。如下:

  • MVCC + 悲观锁:
    • MVCC 解决快照读的冲突。
    • 悲观锁(也就是读锁和写锁)解决当前读和【写-写】冲突,悲观锁 InnoDB 已实现。
  • MVCC + 乐观锁:
    • MVCC 解决快照读的冲突。
    • 乐观锁(其实就是不加锁,如果内容变更,则放弃查询和更新)解决当前读和【写-写】冲突,乐观锁由用户自己实现。

MySQL 事务 和 锁、MVCC 的关系
https://flepeng.github.io/041-MySQL-41-底层原理-MySQL-事务-和-锁、MVCC-的关系/
作者
Lepeng
发布于
2020年8月8日
许可协议