谈谈mysql的日志,主要围绕物理日志redo log
和逻辑日志binlog
,就像mysql
的Serve
层和引擎层,Serve
层主要负责功能层面的事情,而引擎层则负责存储相关的具体事宜.
那什么是redo log
?什么是binlog
?
例:比如你在超市买东西结账,营业员在扫你购买的物品,这个时候会生成一个简单的购物清单,但是并不会直接进行超市的出库,等你结完账之后才会进行超市的物品出库,而
redo log
可以理解成正常结账的购物清单,而binlog
则是在进行超市物品出库的记录
-
redo log
是固定大小的,假设配置四个文件,每个文件的大小为1个G,那么可以记录4G的数据,从头写到尾,记录一个位置,当文件写入到当前位置,便开始擦除之前的记录,并在擦除前将记录更新至数据库。有了redo log
,InnoDB
就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe
-
binlog
是mysql
的Server
层的日志
两者的区别:
redo log
是mysql
引擎InnoDB
所特有的,而binlog
是mysql
的Service
层提供的,所有引擎都课余使用redo log
是物理日志;binlog
是逻辑日志redo log
是循环写的,空间固定会用完;binlog
是追加写入的,达到一定大小会切换到下一个
代码语言:javascript复制一条update语句是如何在mysql中执行的?
获取需要修改的行 --> 写入内存 --> 返回行数据 --> 写入新的数据 --> 新数据写入内存 --> 写入redo log --> 处于prepare阶段 --> 写入binlog --> 提交事物commit
mysql将redo log
的写入拆成了两个步骤:prepare和commit
,这就是"两阶段提交"。
两阶段提交的必要性:由于
redo log
和inlog
是两个独立的逻辑,如果不用两阶段提交,也就是不关心两者数据记录的同步情况,会出现什么情况?
- 先写
redo log
后写binlog
- 如果
redo log
写完,binlog
还没有写完,MySQL进程异常重启,由于redo log
已经写完了,所以可以进行crash
,但是由于binlog
还没有写完就已经回滚了,所以在binlog
日志中是没有记录的,那么如果 这个时候需要进行数据的回滚操作,就会缺少当前这条数据
- 如果
- 先写binlog后写redo log
- 如果
binlog
写完,redo log
还没有写完,那么此时MySQL进程异常重启,此时进行crash
,但是因为redo log
还没有写入,如果之后使用binlog
进行回滚,此时就与数据库不一致了
- 如果
两阶段提交就是让这两个状态保持逻辑上的一致。