什么是binlog
binlog二进制日志记录了对MySQL数据库执行更改的所有操作,并且记录了语句发生时间、执行时长、操作数据等其它额外信息,但是它不记录SELECT、SHOW等那些不修改数据的SQL语句。
binlog是server层产生的归档日志,由执行器生成,与引擎无关,不具有crash-safe能力。
binlog格式
binlog是逻辑日志,记录的是原语。
逻辑日志与物理日志的区别可以看这篇:逻辑日志与物理日志
binlog有三种格式:
- ROW:基于数据的复制,基于行的更改,会将实际数据记录在二进制日志中。
- STATEMENT:记录数据库上执行的原生SQL语句。
- MIXED:默认采用基于STATEMENT的复制,一旦发现基于STATEMENT的无法精确的复制时,就会采用基于ROW的复制。
可以通过以下命令查看binlog格式,可通过set binlog_format = STATEMENT
修改binlog格式为基于STATEMENT的复制。
mysql> show variables like '%binlog_format%';
+------------------------------------------------+----------------------+
| Variable_name | Value |
+------------------------------------------------+----------------------+
| binlog_format | ROW |
+------------------------------------------------+----------------------+
1 rows in set (0.00 sec)
可以在shell中通过mysqlbinlog
命令查看二进制日志对应的内容,如下为分别使用ROW和STATEMENT格式时产生的binlog,执行的sql语句是insert into testbinlogformat values(1, current_user())
,只截取了部分内容。
可以看到基于ROW格式会把实际数据保存在日志中,而STATEMENT格式保存的是原sql语句;
但是基于ROW格式产生的日志比基于STATEMENT格式要多。
mysqlbinlog -vv $binlogfile
// eg. binlog_format=ROW
> BEGIN
> /*!*/;
> # at 1770
> #210329 9:14:10 server id 1 end_log_pos 1844 CRC32 0xfaae1535 Table_map: `practise`.`testbinlogformat` mapped to number 98
> # at 1844
> #210329 9:14:10 server id 1 end_log_pos 1899 CRC32 0x9ef05e17 Write_rows: table id 98 flags: STMT_END_F
>
> BINLOG '
> YpphYBMBAAAASgAAADQHAAAAAGIAAAAAAAEACHByYWN0aXNlABB0ZXN0YmlubG9nZm9ybWF0AAID
> DwLIAAMBAQACA/z/ADUVrvo=
> YpphYB4BAAAANwAAAGsHAAAAAGIAAAAAAAEAAgAC/wABAAAADnJvb3RAbG9jYWxob3N0F17wng==
> '/*!*/;
> ### INSERT INTO `practise`.`testbinlogformat`
> ### SET
> ### @1=1 /* INT meta=0 nullable=1 is_null=0 */
> ### @2='root@localhost' /* VARSTRING(200) meta=200 nullable=1 is_null=0 */
> # at 1899
> #210329 9:14:10 server id 1 end_log_pos 1930 CRC32 0x52fdc115 Xid = 67
> COMMIT/*!*/;
// eg. binlog_format=STATEMENT
> BEGIN
> /*!*/;
> # at 1442
> #210329 9:12:32 server id 1 end_log_pos 1581 CRC32 0x84c6c624 Query thread_id=10 exec_time=0 error_code=0
> SET TIMESTAMP=1617009152/*!*/;
> insert into testbinlogformat values(1, current_user())
> /*!*/;
> # at 1581
> #210329 9:12:32 server id 1 end_log_pos 1612 CRC32 0x16cb1106 Xid = 50
> COMMIT/*!*/;
想进一步了解binlog日志格式的话可以阅读这篇文章:MySQL binlog格式解析