先分析update语句执行过程:
例如:update TableAu set num=num+1 where id=1
update过程:
-
取出id=1这行数据
这行数据在内存中,直接返回数据行/不在,将数据从磁盘读入内存,返回数据行 -
对这行数据的num+1,写入新行,更新内存
-
写redo log,处于prepare
-
写bin log,提交事务,commit
上述涉及的redo log 与bin log
- redo log:
WAL 先写日志,再写磁盘
redo log是InnodB特有的
是物理日志,记录在每个数据页做什么操作
是循环写的,空间固定会用完,所以会覆盖 - bin log
Server 层的log
逻辑日志,记录语句的原始逻辑。statement模式:SQL语句/row模式:记录行更新前、后的内容
追加写,空间用完切换下一个,不会覆盖
两阶段提交
- 第一阶段,事务处于prepare,持有prepare_commit_mutex,写入redo log,undo 设置为prepared
- 第二阶段,事务写入 bin log,将redo log对应的事务打上commit,释放prepare_commit_mutex。这里的commit才是事务真正的commit。
两阶段提交可以保证两个日志在逻辑上的一致性
崩溃时的恢复:
- 如果redo log里的事务是完整的prepare+commit,则进行提交
- 如果redo log里的事务是不完整的,获取redo 的prepare事务列表和最后的一个bin log的Xid列表进行结合
if binlog事务完整,则进行提交
if bin log事务不完整,则进行回滚
binlog 与redo log通过checksum与xid进行完整性判断
redo log 与 bin log通过事务Xid进行关联