BinLog
属于逻辑日志,记录的是对数据库的数据进行操作(如update、insert)的原始逻辑,属于server层
作用:
- 数据备份
- 主从节点数据同步、
binlog以顺序追加写的方式在日志文件写入新的日志
记录格式:
-
statement:记录操作数据库的原始的SQL 如:
UPDATE user SET name='new' WHERE id=1
-
row:记录每行数据数据变化前后的值 如:
id=1的name从'old'→'new'
-
mixed:动态切换row和statement,默认下使用statement
优缺点:
statement:
优点:
-
只记录SQL,日志体积小
-
可读性强,排查日志时更方便
缺点:
- 当SQL有用到函数如NOW()这种带上下文的信息时,会出现数据不一致的情况
row:
优点:
- 不依赖上下文,能够保障数据的一致性
- 使用索引快速定位数据行,并发大时性能更佳
缺点:
-
记录了每行数据的变更,导致占用内存高,传输带宽需求及磁盘IO需求更高,会带来更高的主从同步延时。
例:在批量操作 如
update user set sex =1 where sex=0
时,一条SQL将产生大量的日志记录 -
可读性差,需要配合工具解析
mixed:
优点:
- 平衡了row和mixed的日志大小和数据一致性
缺点:
- 有可能出现数据不一致
写入机制
- 事务执行期间,将日志写入binglog cache(在内存上,不涉及磁盘IO,写入速度快)
- 事务提交时,再将binlog cache通过追加写方式(减少磁盘随机IO消耗)写入binlog文件(即落盘)
binlog cache:每个客户端线程都会被分配一个独立的binlog cache(默认大小32KB)
fsync:
- 0:依赖OS自动控制落盘时机
- 1:每次事务提交后强制刷盘,数据安全但影响吞吐性能
- N: N个事务提交后进行落盘
RedoLog
记录数据页的物理变化,如某行的num+1,则记录:在对应行所存在的xx物理页内的num数据进行了+1
在存储引擎层工作,由InnoDB独占
应用场景:
- 在mysql崩溃后实现数据恢复
- 实现ACID中D(事务提交后数据变动是永久的)的特性
写入机制:
MySQL读取数据是以页为单位的,在查询记录时,会将记录存在的页拷贝至buffer pool(在内存上)中进行读取
- 当更新表数据时,会先去buffer pool中查找数据是否存在,不在则取
- 在则将该页上的数据进行修改,同时写入redolog buffer中,将日志状态置为prepared(两阶段提交)
- 事务提交后将日志状态改为commit
redolog buffer的数据将按刷盘策略写入到redolog
刷盘策略:
Innodb默认开后台每秒进行一次redolog刷盘,初次之外还可通过配置策略实现额外刷盘时机
- 0:事务提交时不主动刷盘,依赖后台线程每秒将RedoLog Buffer中的数据写入Page Cache并调用
fsync
刷入磁盘 - 1(默认策略):每次事务提交时强制将Redo Log Buffer写入Page Cache,并调用
fsync
刷入磁盘 - 2:事务提交时将Redo Log Buffer写入Page Cache,但不调用
fsync
,由操作系统决定何时刷盘(通常每秒一次)
其他刷盘时机:
- redolog buffer占用过半
- MySQ正常退出
数据丢失:
- 策略0 时,宕机时最多丢失1s的数据
- 策略1 时,宕机也不会丢失数据
- 策略2 时,由于写入了OS的缓存,当MySQL宕机,OS没宕机时,则不会产生数据丢失。OS宕机则最多丢失1s数据
为什么不将每次修改后的数据页直接刷盘,而是写到Redolog里:
- 数据页大小为16KB,而我们修改的数据往往只有几B,每次都刷浪费系统IO资源
- 每个数据页的位置是随机的,写入会触发磁盘随机IO,性能差
- redoLog一行记录大部分最多只占几十B,且是顺序写,刷盘数据更快,也能让数据库的并发写性能更高
两阶段提交
将redolog分为prepared和commited状态
配合binlog提交保障数据一致性
Redolog和binlog逻辑不一致会怎么样
当对一行数据的某个字段值为0的加一,这时候redolog写入完毕,但是binlog异常,且mysql出现宕机
redolog将这条数据进行了加一,而binlog没有。
mysql服务重启后因为原库使用的是redolog进行恢复数据,而从库则是按binlog进行的同步,从而出现主从数据不一致的情况。
通过两阶段提交:
当mysql使用redolog进行数据恢复时,发现事务的redolog还在prepare阶段,且没有数据没有对应的binlog,则回滚这个事务
当redolog在commit阶段出错,也不会影响,因为能在binlog找到相应的事务,并将prepare改为commit并进行刷盘,数据恢复
UndoLog
属于逻辑日志,记录的是每次数据修改前的值
作用:
-
保障事务的原子性:当事务执行失败或回滚时,通过undolog记录的旧值撤销操作,恢复到事务执行前的状态,如
insert回滚:记录id值,回滚时delete id=x
delete回滚:记录行,回滚时insert
update回滚:记录修改前字段值,回滚则update对应字段回旧值
-
实现MVCC的视图:通过undolog版本链,实现多个事务能够拥有独立的读视图,保障了ACID的I特性,事务通过ReadView和版本链实现了RR,RC的事务隔离
-
减少锁的使用:通过维护多个版本实现快照读来实现了视图隔离,减少锁的使用,提高性能
流程:
- 在执行数据变更操作前,将数据旧值写入undo buffer
- 生成一个新的undolog节点,将roll_pointer指向已存在的最新undolog节点
- 事务提交后,undolog标记为可清理,由后台线程回收
- 事务回滚则根据版本链进行逆向操作