Mysql两阶段提交

在看Mysql相关内容的时候经常听到两阶段提交,那以前都是云里雾里的,通过学习丁奇老师的这篇文章彻底明白了其流程和含义。

提到两阶段提交,必须先说一下两个日志:redo logbinlog

重要的日志模块:redo log

数据在磁盘中是按照主键顺序存储的,在对数据进行更新操作(insert、update、delete)的时候,既要写数据又可能对其他数据进行移动,如果每次都写进磁盘是很耗性能的。redo log这里就用到的WAS技术,WAL的全称是Write-Ahead Logging,它的关键点是先写日志再写磁盘,并且 写日志是顺序写 速度很快。

具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到redo log,并更新内存,这个时候更新就算是完成了。同时Innodb引擎会在适当的时候讲这个操作更新到磁盘里面。

Innodeb的redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB,那么总共可以记录4GB的操作,从头开始写,写到末尾就又会到开始循环。当然当大小不够的时候会讲数据刷新到磁盘(数据文件内)。

有了redo log Innodb就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe.

重要的日志模块:binlog

前面提到的redo log是Innodb提供的,而binlog是Server层提供的。这两个日志有如下不同

  • redo logInnodb引擎特有的;binlogMysql Server层实现的,所有引擎都可以使用

  • redo log是物理日志,记录的是"在某个数据页上做了什么操作";binlog是逻辑日志,记录的是这个语句的原始逻辑,比如"给ID=2这一行的C字段加1"

  • redo log是循环写的;binlog是追加的,不会覆盖以前的日志

  • binlog用于主从同步、恢复数据(误删除)和扩容等

两阶段提交

update test set age = age +1 where id = 1 当执行这条语句的时候,我们看看它的内部流程

  • 执行器先去引擎找id=1的这一行,id是主键引擎直接用树搜索找到这一行。如果这一行的数据页在内存中,就直接返回给执行器,否则就需要从磁盘读取然后在返回。

  • 执行器拿到引擎提供的行数据,给age字段加1,比如原来是9,现在就是10,得到新的一行数据,在调用引擎接口写入这行数据

  • 引擎将新的数据行更新到内存中,同时将这个更新操作记录到redo log,此时redo log处于prepare状态,然后告知执行器执行完成了,随时可以提交事务

  • 执行器生成这个操作的binlog,并把binlog写入磁盘

  • 执行器调用引擎接口,引擎把刚刚写的redo log改成提交commit状态,更新完成。

最后三步比较绕,将redo log的写入拆成了两个步骤preparecommit,这就是两阶段提交

原文地址:https://www.cnblogs.com/wangchy0927/p/11694374.html