使用场景
update users set name=’XXX’ where id = 10
流程
Buffer Pool(缓冲池):如果对应‘id=10’的数据在缓冲池中,则直接使用;否则,从磁盘上加载该数据
- 为这一行数据加上独占锁
- Undo log:讲更前的旧数据写入undo log文件,用于事物回滚
- 更新缓冲池中的数据
- Redo Log Buffer:将数据的修改日志写入该缓冲区,记录的是“对哪个数据页中的的什么记录,做了什么修改”。用于mysql宕机恢复
- 此时这条redo log日志是处于prepare状态
- redo log根据配置的刷盘策略进行落盘
- server层执行器生成该操作的binlog,并写入binlog日志
server层提交事务,这时候会调用引擎的提交事务接口,将刚刚的redolog日志标记为commit,并写入redo log file
两阶段提交
两阶段含义
innodb写入的redolog日志状态为prepare状态,
- 通知server层可以提交事务了,server层写入对应的binlog日志
- 提交事务
innodb层将redolog状态更新为commit,并触发redolog buffer的刷盘策略
作用
保证某一时刻数据库的状态,和crash后用日志恢复出来的数据库状态一致
-
mysql异常重启,保证数据完整性
写入redo log处于prepare状态,写bin log之前crash
- 事务回滚;binlog没写,所以也不会同步到从库
- 写入redolog 处于prepare状态,写binlog后,还未将redo log改为commit
- 如果redo log日志有commit标志,则直接提交
- 如果redo log是prepared标志,则判断对应的binlog是否存在并完整
- 如果是,则提交
- 否,回滚事务
如何判断binlog是否完整
值为0
- 提交事物后,不会把redo_log_Buffer中的数据刷新到磁盘
- 事物提交成功,但mysql宕机会导致数据丢失
- 值为1
- 提交事物后,会把redo_log_Buffer中的数据刷新到磁盘
- 事物提交成功后宕机,不会丢失内存中的数据,因为重启后mysql会根据redo log恢复数据
值为2
InnoDB存储引擎有一个后台线程,每隔1秒,就会把redo log buffer中的内容写到文件系统缓存(page cache),然后调用fsync刷盘。
除了后台线程每秒1次的轮询操作,还有一种情况,当redo log buffer占用的空间即将达到innodb_log_buffer_size一半的时候,后台线程会主动刷盘
修改后的缓存页直接落盘和修改写入redo log文件区别
缓存页落盘
一次刷盘就是16KB比较耗时,但你一次修改可能就只改了几个字节,性价比不高
-
写redo log文件
一行redo log日志可能就只占用几十字节,就包含表空间、数据页号、文件偏移量、更新值等信息
-
redo log结构
日志类型(就是类似MLOG_1BYTE之类的),表空间ID,数据页号,数据页中的偏移量,具体修改的数据
日志类型
MLOG_1BYTE:指修改了一个字节
- MLOG_2BYTE:修改了两个字节
- 。。。
- MLOG_8BYTE:修改了8个字节
-
Redo log block
存放多行的redo log日志
- 一个redo log block是512字节
写redo log时候,会现在内存中创建一个redo log block的数据结构,写满后将其写入磁盘
结构
redo log buffer
mysql 启动后申请的一块连续的内存区域,将其划分为多个redo log block区块
- redo log buffer的内存大小通过参数innodb_log_buffer_size指定,默认大小16MB
- 写redo log其实就是写入redo log buffer中的某个redo log block
通常一个事物会包含多行redo log,这多行redo log就是一组,当这一事物多个操作都执行成功后,才会一起写入block
刷盘时机
写入redo log buffer的日志,已经占了redo log buffer总容量的一半,就会写入磁盘
- 一个事物提交,必须将其redo log所在的redo log block刷入磁盘
- 后台定时任务每隔1秒,将redo log buffer中的日志写到操作系统的page cache中,然后调用fsync落盘
-
磁盘文件
redo log磁盘文件目录:又innodb_log_group_home_dir指定,通过show variables like ‘datadir’查看
- innodb_log_files_in_group指定redo log文件数量(默认2个),innodb_log_file_size指定每个redo log的大小(默认48MB)
- 循环写
- redo log写满后,需要刷脏页落盘
组提交
