事务的基本要素(ACID)
- 原子性(Atomicity):事务不可分割,中间状态不可中断。是使用 undo log 来实现的,如果事务执行过程中出错或者用户执行了rollback,系统通过 undo log 日志返回事务开始的状态。
- 隔离性(Isolation):一个事务不应该受到其他事务的干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。通过锁以及 MVCC,使事务相互隔离开。
- 持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。使用 redo log 来实现,只要 redo log 日志持久化了,当系统崩溃,即可通过redo log 把数据恢复。
- 一致性(Consistency):事务执行数据前后一致。比如A向B转账,不可能A扣了钱,B却没收到。一致性则是通过持久性+原子性+隔离性来保证;
事务隔离级别
原因:并发事务导致的脏读,不可重复读,幻读。
- 脏读:当前事务可以读到另一个事务未提交的数据。
- 不可重复读:当前事务中,同一条sql,多次查询前后结果内容不一致(侧重于修改)。
- 虚读/幻读:当前事务中,同一条sql,多次查询,前后结果记录数不一致,有可能多了,也有可能少了。 (侧重于新增/删除)。
脏读和不可重复读的区别:脏读读到的是未提交的数据,而不可重复读读到的是已经提交的数据。
不可重复读和虚读/幻读的区别:不可重复读侧重于修改,虚读/幻读侧重的是新增/删除。
解决方法:通过事务隔离级别去解决,以下四个隔离级别需要对应的数据库引擎自己支持,而不是spring本身去支持,spring只是整合使用而言。
Read committed (读已提交) | 当前事务可以读到另一个事务提交后的数据。 | 可以避免脏读,但不可重复读和幻读问题仍然可能出现。 |
Read uncommitted (读未提交) | 当前事务可以读到另一个事务未提交的数据。 | 脏读,不可重复读,幻读都可能会出现。 |
REPEATABLE_READ(可重复读)默认级别 | 确保事务可以多次从一个字段中读取相同的值。在这个事务持续期间,禁止其他事务对这个字段进行更新。 | 可以避免脏读和不可重复读,但是幻读的问题依然存在。 |
Serializable(串行化) | 确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入,更新,删除。 | 所有的并发问题都能避免,但是性能比较低。 |
mysql支持四种隔离级别,默认采用repeat