前言
日志系统是用于保证MySQL数据不丢失、高性能和事务支持所需要的,不同的日志类型用于支持不同功能。下面列举MySQL目前使用的三种日志类型:
- Bin Log
- Undo Log
- Redo Log
Bin Log
全称为二进制日志文件(Binary Log),是MySQL在Server层实现的一种日志。其作用是记录DML和DDL这类对数据有更改性质的操作,可以用来复制和恢复数据。bin log支持三种记录方式:
- ROW:记录的是修改的数据的具体行
- STATEMENT:以SQL语句形式记录
- MIXED:混合模式。优先选择STATEMENT,STATEMENT无法记录的会由ROW来记录
MySQL提供了mysqlbinlog
这个工具来操作binlog文件:mysqlbinlog --no-defaults --start-datetime='2020-01-01' --stop-datetime='2020-01-15' -v --base64-output='decode-rows' log_bin.000001 > log.txt
- no-defaults:表示不使用默认值,查看默认值可以输入
mysqlbinlog --help
- start-datetime/stop-datetime:只查看特定时间范围内的bin log日志
- -v(–verbose):显示详细信息
- –base64-output:设置输出格式,这里使用decode-rows解码
- log_bin.000001:要操作的binlog文件
-
log.txt:将结果追加到log.txt文件
下面使用这条语句打印row格式的binlog日志,该binlog记录了delete from test.t limit 1
相关信息:
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#200116 7:48:18 server id 50 end_log_pos 123 CRC32 0xfb15e2bd Start: binlog v 4, server v 5.7.28-log created 200116 7:48:18 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
# at 123
#200116 7:48:18 server id 50 end_log_pos 154 CRC32 0xfba4dd6c Previous-GTIDs
# [empty]
# at 154
#200116 7:48:24 server id 50 end_log_pos 219 CRC32 0xd547ddcb Anonymous_GTID last_committed=0 sequence_number=1 rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 219
#200116 7:48:24 server id 50 end_log_pos 291 CRC32 0x7e06ddc3 Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1579160904/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=45,@@session.collation_connection=45,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 291
#200116 7:48:24 server id 50 end_log_pos 338 CRC32 0xbdd8f7b6 Table_map: `test`.`t` mapped to number 109
# at 338
#200116 7:48:24 server id 50 end_log_pos 380 CRC32 0xc6f4c168 Delete_rows: table id 109 flags: STMT_END_F
### DELETE FROM `test`.`t`
### WHERE
### @1=5330617
### @2='c'
# at 380
#200116 7:48:24 server id 50 end_log_pos 411 CRC32 0xa610a3b7 Xid = 10
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
可以看到以三个#开头的,就是被decode翻译过的SQL语句,不过还是跟我们使用的SQL不太一样,它这里面的@1,@2都有固定意思,具体可以参考这个链接。
好,我们再来看看STATEMENT
格式的日志:
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#200116 7:59:17 server id 50 end_log_pos 123 CRC32 0x9988edaf Start: binlog v 4, server v 5.7.28-log created 200116 7:59:17 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
# at 123
#200116 7:59:17 server id 50 end_log_pos 154 CRC32 0xfc792bbb Previous-GTIDs
# [empty]
# at 154
#200116 7:59:40 server id 50 end_log_pos 219 CRC32 0x276da709 Anonymous_GTID last_committed=0 sequence_number=1 rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 219
#200116 7:59:40 server id 50 end_log_pos 298 CRC32 0xe0ecceec Query thread_id=2 exec_time=0 error_code=0
SET TIMESTAMP=1579161580/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549152/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=45,@@session.collation_connection=45,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 298
#200116 7:59:40 server id 50 end_log_pos 393 CRC32 0xb9846488 Query thread_id=2 exec_time=0 error_code=0
use `test`/*!*/;
SET TIMESTAMP=1579161580/*!*/;
delete from t limit 1
/*!*/;
# at 393
#200116 7:59:40 server id 50 end_log_pos 424 CRC32 0x2773e433 Xid = 10
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
找一下就能看到在较下方可以看到这条SQL语句。MIXED
就是STATEMENT
和ROW
混合,这里就不列举了。
Undo Log
重做日志是MySQL在server
层实现的一种日志,用于记录日志的更改前信息。目前普遍用于InnoDB的事务回滚,MVCC
的支持。Undo Log记录在数据页格式为FIL_PAGE_UNDO_LOG
,对应十六进制为0x02
。Undo Log的数据页记录的具体记录也是一行一行的,每条记录都有一个7
字节的隐藏字段DB_ROLL_PTR
,用于指向Undo页具体的数据行,形成一个版本单向链表。
以下例子只适用于InnoDB存储引擎,且隔离级别为READ-COMMITTED或REPEATABLE-READ
举个例子,假设现在有三条记录:
id | name |
---|---|
1 | 张三 |
2 | 李四 |
3 | 王五 |
事务A:update t set name = “老李” where name = “李四”;
这里事务A执行了update语句后,还没提交或回滚时,就会生成一条新纪录"老李",并将这条纪录的DB_ROLL_PTR
指向旧记录"李四"的地址。在其它事务试图读取这条数据的时候,就会顺着DB_ROLL_PTR
来找到符合当前可见的记录,判断可见性是根据Read View
和该数据的隐藏字段DB_TRX_ID
来实现。关于Undo Log的原理不在这里介绍。
Redo Log
重做日志是InnoDB存储引擎实现高性能且避免数据丢失的一种日志。InnoDB为了提高性能,会尽可能的将操作只在内存中直接操作,而不马上刷到磁盘。为了避免宕机断电等情况导致内存的数据还没刷到磁盘上,导致数据丢失情况的发生。Redo Log会记录每次对数据操作的行为,并持久化到磁盘。关于Redo Log的原理不在这里介绍。
来源:CSDN
作者:树上有只狼
链接:https://blog.csdn.net/weixin_39641204/article/details/104004945