深入理解 MySQL MVCC 与锁机制:从底层原理到可见性算法实战

本文写给谁看:刚接触 MySQL、听过 MVCC / 事务隔离 / 幻读这些词但总觉得云里雾里的同学。 怎么读:全文按"先建立直觉 → 再看原理 → 最后实战排错"的顺序展开,每一章都可以独立看懂。遇到不懂的名词别慌,文中都会用大白话解释。 读完你能收获:① 彻底搞懂事务隔离级别;② 明白 MVCC 到底在干什么;③ 能手算"某条数据该不该被看到";④ 知道 RC 和 RR 差在哪;⑤ 理解幻读为什么会发生、怎么防;⑥ 看懂 InnoDB 的各种锁;⑦ 掌握死锁排查思路。 〇、开篇:一个让你头疼的场景 假设你开了两家银行柜台(两个事务),同时操作同一个账户: 柜员 A 正在给账户改余额(写); 柜员 B 只想查一下余额(读)。 最笨的办法是:A 改的时候把账户锁起来,B 必须干等。这就是"加锁"方案——简单,但慢得要命,因为读和写互相堵。 MySQL 的 InnoDB 引擎想了个聪明的办法:既然 B 只是想"看一眼",那我给它看一张"刚才的快照照片"不就行了?A 继续在原件上改,互不影响。 这个"拍快照、看历史版本"的机制,就叫 MVCC(Multi-Version Concurrency Control,多版本并发控制)。 🎯 一句话记住 MVCC:它让"读不加锁、读写不冲突“成为可能,是 MySQL 高并发的功臣。 整篇文章,其实就是围绕”这张快照是怎么拍的、什么时候拍的、能看到什么“这三个问题展开的。我们一步步来。 一、前置知识:先把地基打好 在讲 MVCC 之前,有三个概念你必须先认识,否则后面会看不懂。别担心,都很简单。 1.1 什么是"事务”? 事务 (Transaction) 就是"一组要么全成功、要么全失败的操作"。最经典的例子是转账:A 扣 100 元、B 加 100 元,这两步必须一起成功,不能 A 扣了钱 B 却没收到。 ...

August 16, 2026 · 8 分钟 · Bridge Li

事务并发处理

前几天和同事讨论,老夫自以为对事务有了一定的了解,但当讨论的时候发现还是有些说不明白,所以周末的时间,又看了一遍带我入门北京尚学堂马士兵老师关于事务的讲解,这次做一下笔记,以供以后忘了的时候查询方便。这里默认读者对事务的ACID都有了了解,直接说事务并发时可能出现的问题和数据库的事务隔离级别 事务并发时可能出现的问题 说这个问题记得大学课堂上有一个很经典的例子就是:银行的存取款,这里也用这个例子说明(因为不知道wp博客怎么搞表格和怎么支持MD,所以就搞几张图片吧) ①. 第一类丢失更新(Lost Update) ②. dirty read脏读(读到了另一个事务在处理中还未提交的数据) ③. non-repeatable read 不可重复读 ④. second lost update problem 第二类丢失更新(不可重复读的特殊情况) ⑤. phantom read 幻读 看到这里可能会有读者对不可重复读和幻读有所迷惑,这两者有什么区别吗?不都是受另一个事务的影响,导致前后结果不一致吗?其实仔细看区别还是很明显的:幻读是关于数据库的delete和insert导致前后的数据不一致,而其他的情况都是数据的更新导致前后的数据不一致 数据库的事务隔离机制 其中在文档java.sql.Connection中有详细的说明,除了none(没有事务)之外,还有:1:read-uncommitted 2:read-committed 4:repeatable read 8:serializable(数字代表对应值)四种。 为什么取值要使用 1 2 4 8 而不是 1 2 3 4 1=0000 2=0010 4=0100 8=1000(位移计算效率高) 需要说明的是: 只要数据库支持事务,就不可能出现第一类丢失更新 read-uncommitted(允许读取未提交的数据) 会出现dirty read, phantom-read, non-repeatable read 问题 read-commited(读取已提交的数据 项目中一般都使用这个)不会出现dirty read,因为只有另一个事务提交才会读出来结果,但仍然会出现 non-repeatable read 和 phantom-read;使用read-commited机制可用悲观锁 乐观锁来解决non-repeatable read 和 phantom-read问题 repeatable read(事务执行中其他事务无法执行修改或插入操作 较安全)但仍然会出现phantom-read serializable解决一切问题(顺序执行事务 不并发,实际中很少用) ...

April 9, 2017 · 1 分钟 · Bridge Li