MySQL事务
事务概念
4个原则 ACID
| 原则 | 概念 | |
|---|---|---|
| 原子性 | 一个事务中的操作要么全部成功,要么全部失败 | Atomicity |
| 一致性 | 总是从一个一致性的状态转换到另一个一致性的状态 | Consistent |
| 隔离性 | 一个事务的修改在提交前,其他事务是感知不到的 | Isalotion |
| 持久性 | 永久保存在数据库中 | Durable |
原子性、隔离性、持久性都是为了保障一致性而存在的,一致性也是最终的目的。
隔离级别
读未提交 READ UNCOMMITTED
读已提交 READ COMMITTED
可重复读 REPEATABLE READ
可序列化 SERIALIZABLE
没有那种隔离级别是完美的,只能根据自己的项目业务场景去评估选择最适合的隔离级别,大部分的公司一般选择Mysql默认的隔离级别:可重复读。
隔离级别从:读未提交-读提交-可重复读-串行化,级别越来越高,隔离也就越来越严实,到最后的串行化,当出现读写锁冲突的时候,后面的事务只能等前面的事务完成后才能继续访问。
- 读未提交:读取到别的事务还没有提交的数据,从而产生了脏读。
- 读提交:读取别的事务已经提交的数据,从而产生不可重复读。
- 可重复读:事务开启过程中看到的数据和事务刚开始看到的数据是一样的,从而产生幻读,在Mysql的中通过MVCC多版本控制的一致性视图解决了不可重复读问题以及通过间隙锁解决了幻读问题。
- 串行化:对于同一行记录,若是读写锁发生冲突,后面访问的事务只能等前面的事务执行完才能继续访问。
举个例子,假如有一个user表,里面有两个字段id和age,里面有一条测试数据:(1,24),现在要执行age+1,同时有两个事务执行:
| 事务1 | 事务2 |
|---|---|
| 启动事务,接着查询age(a1) | |
| 启动事务 | |
| 查询age(a2) | |
| 执行age=age+1 | |
| 查询age(a3) | |
| 提交事务 | |
| 查询age(a4) | |
| 提交事务 | |
| 查询age(a5) |
经过上面的执行,在四种隔离级别下a1,a2,a3,a4,a5的值分别是多少?我们来认真的分析一波:
- 读未提交:a1和a2因为读的是初始值所以为24,隔离级别为读未提交,事务2执行了age=age+1,不管事务2是否提交,那么a3、a4和a5的值都是25。
- 读提交:a1和a2因为读的是初始值所以为24,隔离级别为读提交所以a3还是24,a4和a5因为事务2已经提交所以得到的值是25。
- 可重复读:a1和a2因为读的是初始值所以为24,可重复读的隔离级别下,a3和a4读取的值和事务开始的结果一样,所以还是24,a5前一步因为已经提交事务,所以a5的值是25。
- 串行化:a1和a2因为读的是初始值所以为24,串行化隔离级别下,当事务2修改数据的时候,获取了写锁,事务1读取age的值会被锁住,所以在事务1的角度下a3和a4读取的值为24,a5的值为25。
当你能够分析得出这个例子下,在不同隔离级别下分析的出a1-a5的值,说明你对事务的隔离级别已经有比较深入的理解了。
并发事务的问题
更新丢失
脏读
不可重复读
幻读
实现分布式事务
1、流水任务,最终一致性,前提是接口要支持幂等性
2、事务消息
3、二阶段提交
4、三阶段提交
5、TCC
6、Seata 框架
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Michael's Blog!
评论




