事务是程序执行过程中的一个执行单元,特点是该执行单元要么全部成功,要么全部失败。
事务包含正常操作和失败补偿操作,而失败补偿操作就包含回滚,因此事务实现的大多数实现都是补偿实现。 mysql中采用补偿操作手段为回滚,即不成功就返回初始状态。一些第三方框架采用补偿,尽量多试几次失败操作,如果仍不成功,则回滚的方案。
1、事务的四大特性 (ACID)
- 原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
- 一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
- 隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
- 持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
2、并发事务的隔离级别
隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read)
读未提交(Read uncommitted 可能 可能 可能
读已提交(Read committed) 不可能 可能 可能
可重复读(Repeatable read) 不可能 不可能 可能
串行化(Serializable ) 不可能 不可能 不可能
- 读未提交(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
- 读已提交(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (存在不可重复读问题)
- 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,(存在幻读)
- 串行化(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
注:
1、不可重复读侧重于更新操作。例如:事务a反复读取一条数据,事务b在事务a读取过程中,修改了这条数据。结果导致事务a读取的这条数据发生了变化,导致前后读取的数据不止一致问题,即不可重复度问题。
2、幻读侧重于增删操作。例如:事务a读取一个列表,长度为10;当事务a反复读取时,这个列表长度也应该为10;但是,事务b在期间,插入或删除了一条数据,导致事务a读取列表时前后长度不一致,数据幽灵般的增加或消失了,因此形成幻读。