数据库日志整理
Database : log, redolog, undolog, commandlog
幂等性
数据库日志文件中的操作记录应该具有幂等性,同一个操作执行多次,结果是一样的。因为日志在故障恢复过程中,可能会被回放多次。
重做日志/事务日志(Redo日志)
作用
它记录了InnoDB存储引擎的事务日志,用于数据库故障的恢复,以保证数据的完整性。
在事务Commit的时候一定会写入。系统一旦写入redo日志,则可以确认数据已经提交,之后,数据库才会选择在合适的时间更新磁盘数据记录。
redo log是指在回放日志的时候把已经commit的事务重做一遍,对于没有commit的事务按照abort处理。日志回放并不会处理任何没有commit的事务,
因此,在COMMIT日志持久化之前,不能将数据的修改持久化。因为如果数据在COMMIT之前持久化,那么在系统异常退出的情况下,这种部分修改的事务就会处于一种不一致状态。
同时,由于重做事务,因此事务日志中必须记录事务修改以后的值。redo log必须满足以下规则:
R1:在修改磁盘上的任何数据库元素X以前,要保证与X的这一修改相关的所有的日志记录,包括更新记录
内容
事务T开始
事务T提交,事务commit之后,日志管理器会执行flush命令将REDO日志强写回磁盘。
事务T终止
Redo log文件是循环写入的,在覆盖写之前,总是要保证对应的脏页已经刷到了磁盘。在非常大的负载下,Redo log可能产生的速度非常快,导致频繁的刷脏操作,进而导致性能下降,通常在未做checkpoint的日志超过文件总大小的76%之后,InnoDB 认为这可能是个不安全的点,会强制的preflush脏页,导致大量用户线程stall住。如果可预期会有这样的场景,我们建议调大redo log文件的大小。可以做一次干净的shutdown,然后修改Redo log配置,重启实例。
写入时机
*> 在页面修改完成之后,在脏页刷入磁盘之前,写入REDO日志
*> 日志先行,日志一定比数据页先写回磁盘。
*> 聚簇索引、二级索引、undo页面修改,均需要记录REDO日志。
删除时机
不删除,会循环写日志,最后一个redo日志写满,则回溯到第一个。
有几种场景可能会触发redo log写文件:
1). Redo log buffer空间不足时
2). 事务提交
3). 后台线程
4). 做checkpoint
5). 实例shutdown时
6). binlog切换时
存储位置
回滚日志(Undo日志)
作用
undo log就是把所有没有COMMIT的事务回滚到事务开始之前的状态(撤销事务在系统崩溃前可能还没有完成的影响来恢复数据库状态),对于已经commit的事务不做任何处理。
undo日志必须满足如下两个规则:
U1:如果事务T改变了数据库元素X,那么形如
内容
生成时机
DML操作修改聚簇索引前,记录UNDO日志
二级索引记录的修改,不记录UNDO日志
注意:undo页面的修改,同样需要记录REDO日志。
删除时机
存储位置
Undo日志和Redo日志的区别
Undo日志:
在恢复时取消未完成事务,忽略已提交事务
先将修改后的数据写到磁盘。 写到磁盘
遵循Undo日志的U1和U2规则,恢复时需要的是数据库的旧值。
Redo日志:
忽略未完成事务,重做已经提价事务的改变。
先写到磁盘,然后数据进入缓冲区,选择合适时间在写入磁盘。
恢复时需要的是新值。
UNDO/REDO LOG(UNDO和REDO和合体)
单独使用的Undo/Redo日志的缺陷
Undo 日志要求数据在事务结束后立即写到磁盘,可能增加磁盘I/O数
Redo日志要求我们在事务提交和日志记录刷新以前将所有修改过的块保留在缓冲区中,可能增加事务需要的平均缓冲区数
如果数据库元素不是完整的块或块块集,在检测点处理过程中,Undo日志和Redo日志在如何处理缓冲区上存在矛盾。
而undo/redo log可以很好的解决这些问题。undo/redo log是指在日志回放的时候像undo log那样回滚所有没有commit的事务;
redo log一样redo所有已经commit的事务。由于同时要进行redo和undo,因此日志记录中必须同时记录修改前的值和修改后的值。
二进制日志(Binlog)
作用
记录了对数据库执行更改的所有操作,但是不包壳Select和Show这些对数据本身没有修改的操作。
如果一个操作本身并没有导致数据库变化,它也有肯能会被写入binglog。比如update的条件不存在。
数据恢复:某些数据的恢复需要二进制日志。用户可以通过二进制日志进行point-in-time的恢复。
集群复制:
主备和mysql集群都是通过复制binlog文件来进行数据实时同步的。
审计:
用户对二进制日志中的信息进行审计,判断是否对数据库进行了注入攻击。
内容
Mysql可以通过如下语句来查看到SQL执行状态。
mysql> show master status;
+------------------+-----------+--------------+--------------------------+-----------------------------------------------------------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------