事务概述
事务四大特性:
A原子性、C一致性、I隔离性、D持久性
原子性:事务作为一个整体被执行,包含在事务中的操作要么全部提交,要么全部回滚。
innodb引擎两种事务日志:
- redo log:保证事务持久性
- undo log:保证事务原子性和隔离性
innodb回滚靠的是undo log
一致性:事务应该确保数据库的状态从一个一致性状态转变为另一个一致性状态
1.约束的一致性:创建表结构的时候,实体、引用、自定义完整性;
2.数据一致性:是一个综合的规定、它是由原子性、持久性、隔离性共同保证的。
隔离性:一个事务执行不能被其他事务干扰。一个事务内的操作及使用的数据对其他并发事务的隔离。
不考虑隔离性会引发一些问题:
脏读:读到未提交的数据
不可重复读:事务内多次读取同一行记录结果不一致
幻读:事务内多次按相同条件查询,结果不一致,可能多几行或少几行
持久性:一个事务一旦提交,则对数据库中数据的改变应该是永久的,后续的操作不应该对其有任何影响、不会丢失。
持久性依赖于两个日志文件:
redo log和binlog。
redolog两阶段提交
redo log提交分为两步(两阶段提交),如下图所示
两阶段提交的具体过程包括:prepare阶段写redolog,binlog落盘,coomit阶段更新redolog(打标记)。
为什么要有两阶段提交?
主要是为了解决binlog和redolog一致性的问题。
使用两阶段提交的方式,无论数据库在哪个环节发生崩溃,都可以正确地恢复,因为redolog和binlog都会有一个唯一的XID来标记更新的事务,从而二者可以对齐。在崩溃恢复时,会顺序扫描redo log:
1)如果碰到既有prepare又有commit的redolog则直接提交(即阶段2),
2)如果redolog处于prepare状态,就会拿着xid去binlog中找对应的事务,判断事务所对应的binlog是否完整(即上图第4步binlog落盘是否完整),如果完整则事务提交,如果不完整则事务回滚。
网络上其他对崩溃恢复的描述:
- 情况一,在prepare阶段完成之后崩溃,由于binlog没有记录,因此直接回滚。
- 情况二,在binlog落盘后崩溃(上图第4步),检查事务是否完整无误,若是,直接提交即可,否则直接回滚。
- 情况三,在commit阶段完成后崩溃,同情况二。
整体看一个数据修改的事务流程:
ACID总结
1.事务的持久化是为了应对系统崩溃造成的数据丢失的情况
2.只有保证事务的一致性,才能保证执行结果的正确性
3.在非并发状态下,事务和事务之间天然保证隔离性,只需要保证事务的原子性,就可以保证事务的一致性
4.在并发状态下,要严格保证事务的原子性和隔离性