SQL 事务与隔离级别入门:脏读、不可重复读、幻读一次分清
【摘要】 ACID 四特性、脏读/不可重复读/幻读三个并发问题、四个隔离级别的递进关系,以及事务长短与 FOR UPDATE 的实用建议,MySQL 默认级别的原理一次讲清。
转账扣款成功但流水没记录?两个用户同时下单库存却超卖?这些经典问题的根源都是事务与隔离级别。这篇入门笔记用转账的例子把概念一次讲清。
一、事务的 ACID
事务是一组要么全部成功、要么全部回滚的操作。ACID 分别是原子性(全部或 nothing)、一致性(转账前后总额不变)、隔离性(并发事务互不干扰)、持久性(提交后不丢)。
二、三个并发问题
- 脏读:读到了别的事务还没提交的数据,对方一回滚你就是假数据;
- 不可重复读:一个事务内两次读同一行结果不同(别人改了并提交);
- 幻读:两次同样的范围查询,返回的行数变了(别人插入了新行)。
三、四个隔离级别
READ UNCOMMITTED 读未提交:什么都不防,几乎不用
READ COMMITTED 读已提交:解决脏读(Oracle/PG 默认)
REPEATABLE READ 可重复读:再解决不可重复读(MySQL InnoDB 默认)
SERIALIZABLE 串行化:连幻读也防,代价最大
MySQL InnoDB 在可重复读级别下通过 MVCC 和间隙锁基本也解决了幻读,这也是它作为默认级别的底气。
四、实用建议
- 事务尽量短小,别在事务里做 RPC 调用或长时间计算;
- 用 SELECT ... FOR UPDATE 精确锁行,代替锁全表;
- 隔离级别够用就好,默认级别改高会牺牲并发性能。
结语:理解三个并发问题与四个隔离级别的对应关系,就能解释绝大多数"数据怎么不对了"的问题。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)