MySql Binlog statement row mixed 三种模式初探

一句话介绍

以下主要演示了MySql Binlog的row格式和statement内容和相关的知识点,

  • ROW记录包括了是EVENT TYPE,且是基于每行的,即你执行了一个DML操作,binlog中记录的并不是具体的这个sql,而是针对该语句的每一行或者多行记录各自生成记录,这样能有效避免主从下针对同一条sql而产生不同的结果(参考文中force indx的例子),这种方式无疑是最安全的,但是效率和空间上消耗是最大的。
  • STATAMENT 是基于sql执行语句的(显示记录),相对于row占用的存储空间要少。用于数据同步的话还是要谨慎,需要保证主从机器之间的一致性(variables参数,Binlog日志格式参数,表引擎,数据,索引等等),如果不能保证,用于恢复数据的情景还是要慎用(可以参考下面update where limit语句的例子)
  • MIXED格式是自动判断并自动切换行和语句的策略,既然是自动,就不能保证完全符合每个业务场景,除非Server层面能做到绝对安全。。

环境及参数说明

环境参数

mysql> select version();
+-----------------------------+
| version()                   |
+-----------------------------+
| 5.7.30-0ubuntu0.16.04.1-log |
+-----------------------------+
mysql> show variables like "%binlog%";
+--------------------------------------------+----------------------+
| Variable_name                              | Value                |
+--------------------------------------------+----------------------+
| binlog_cache_size                          | 32768                |
| binlog_checksum                            | CRC32                |
| binlog_direct_non_transactional_updates    | OFF                  |
| binlog_error_action                        | ABORT_SERVER         |
| binlog_format                              | ROW                  |
| binlog_group_commit_sync_delay             | 0                    |
| binlog_group_commit_sync_no_delay_count    | 0                    |
| binlog_gtid_simple_recovery                | ON                   |
| binlog_max_flush_queue_time                | 0                    |
| binlog_order_commits                       | ON                   |
| binlog_row_image                           | FULL                 |
| binlog_rows_query_log_events               | OFF                  |
| binlog_stmt_cache_size                     | 32768                |
| binlog_transaction_dependency_history_size | 25000                |
| binlog_transaction_dependency_tracking     | COMMIT_ORDER         |
| innodb_api_enable_binlog                   | OFF                  |
| innodb_locks_unsafe_for_binlog             | OFF                  |
| log_statements_unsafe_for_binlog           | ON                   |
| max_binlog_cache_size                      | 18446744073709547520 |
| max_binlog_size                            | 104857600            |
| max_binlog_stmt_cache_size                 | 18446744073709547520 |
| sync_binlog                                | 1                    |
+--------------------------------------------+----------------------+
mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000003 |     18117 |
| mysql-bin.000004 |       523 |
| mysql-bin.000005 |       523 |
| mysql-bin.000006 |       177 |
| mysql-bin.000007 |      4232 |
+------------------+-----------+

说明

在具体之前我们先看和本文操作不强相关但是已经存在的binlog,d当前最新的文件名为mysql-bin.000007 。主要目的是做一个上下文的分界线(id标识)

root@base2018:/var/log/mysql# ls -lt|grep mysql-bin
-rw-r----- 1 mysql mysql  4232 Jul  2 10:32 mysql-bin.000007
-rw-r----- 1 mysql mysql   160 Jul  2 10:24 mysql-bin.index
-rw-r----- 1 mysql mysql   177 Jul  2 10:23 mysql-bin.000006
-rw-r----- 1 mysql mysql   523 Jun 25 06:25 mysql-bin.000005
-rw-r----- 1 mysql mysql   523 Jun 24 06:25 mysql-bin.000004
-rw-r----- 1 mysql mysql 18117 Jun 23 06:25 mysql-bin.000003

show binlog events in 'mysql-bin.000007'\G

.## 省略..
*************************** 32. row ***************************
   Log_name: mysql-bin.000007
        Pos: 2318
 Event_type: Write_rows
  Server_id: 1
End_log_pos: 2366
       Info: table_id: 120 flags: STMT_END_F
*************************** 33. row ***************************
   Log_name: mysql-bin.000007
        Pos: 2366
 Event_type: Xid
  Server_id: 1
End_log_pos: 2397
       Info: COMMIT /* xid=62 */
33 rows in set (0.00 sec)

我们可以看一下最后一条 第row id为的详细信息,因为其开始Pos2366,记住这个33,^_^

开始造作

建表插入测试数据

CREATE TABLE `binlog_demo` (
  `id` int(11) NOT NULL,
  `a` int(11) DEFAULT NULL,
  `t_modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `a` (`a`),
  KEY `t_modified`(`t_modified`)
) ENGINE=InnoDB;

insert into binlog_demo values(1,1,'2020-07-01');
insert into binlog_demo values(2,2,'2020-07-02');
insert into binlog_demo values(3,3,'2020-07-02');
insert into binlog_demo values(4,4,'2020-07-04');
insert into binlog_demo values(5,5,'2020-07-05');

执行一条sql(row格式)

mysql> delete from binlog_demo /*comment*/  where a>=4 and t_modified<='2020-07-10' limit 1;
Query OK, 1 row affected (0.01 sec)

接上面的第33条之后看

*************************** 34. row ***************************
   Log_name: mysql-bin.000007
        Pos: 2397
 Event_type: Anonymous_Gtid
  Server_id: 1
End_log_pos: 2462
       Info: SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
*************************** 35. row ***************************
   Log_name: mysql-bin.000007
        Pos: 2462
 Event_type: Query
  Server_id: 1
End_log_pos: 2542
       Info: BEGIN
*************************** 36. row ***************************
   Log_name: mysql-bin.000007
        Pos: 2542
 Event_type: Table_map
  Server_id: 1
End_log_pos: 2599
       Info: table_id: 120 (test.binlog_demo)
*************************** 37. row ***************************
   Log_name: mysql-bin.000007
        Pos: 2599
 Event_type: Delete_rows
  Server_id: 1
End_log_pos: 2647
       Info: table_id: 120 flags: STMT_END_F
*************************** 38. row ***************************
   Log_name: mysql-bin.000007
        Pos: 2647
 Event_type: Xid
  Server_id: 1
End_log_pos: 2678
       Info: COMMIT /* xid=86 */

去掉\G后展开对应下面的5行,注意2397是上一个binlogEnd_log_pos,也就是那个33的end pos。

| mysql-bin.000007 | 2397 | Anonymous_Gtid |         1 |        2462 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                                                                                                                                                                                                                      |
| mysql-bin.000007 | 2462 | Query          |         1 |        2542 | BEGIN                                                                                                                                                                                                                                                     |
| mysql-bin.000007 | 2542 | Table_map      |         1 |        2599 | table_id: 120 (test.binlog_demo)                                                                                                                                                                                                                          |
| mysql-bin.000007 | 2599 | Delete_rows    |         1 |        2647 | table_id: 120 flags: STMT_END_F                                                                                                                                                                                                                           |
| mysql-bin.000007 | 2647 | Xid            |         1 |        2678 | COMMIT /* xid=86 */                                                                                                                                                                                                                                       |
+------------------+------+----------------+-----------+-------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
38 rows in set (0.00 sec)

我们从2462
mysqlbinlog -vv mysql-bin.000007 --start-position=2462

/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#200702 10:24:14 server id 1  end_log_pos 123 CRC32 0xa97adc3a     Start: binlog v 4, server v 5.7.30-0ubuntu0.16.04.1-log created 200702 10:24:14 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
TkX9Xg8BAAAAdwAAAHsAAAABAAQANS43LjMwLTB1YnVudHUwLjE2LjA0LjEtbG9nAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABORf1eEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQA
ATrceqk=
'/*!*/;
# at 2462
#200702 11:26:00 server id 1  end_log_pos 2542 CRC32 0x2e66d2a1     Query    thread_id=14    exec_time=0    error_code=0
SET TIMESTAMP=1593660360/*!*/;
SET @@session.pseudo_thread_id=14/*!*/;
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 utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.time_zone='SYSTEM'/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 2542
#200702 11:26:00 server id 1  end_log_pos 2599 CRC32 0x8d66ca1a     Table_map: `test`.`binlog_demo` mapped to number 120
# at 2599
#200702 11:26:00 server id 1  end_log_pos 2647 CRC32 0x59777bf5     Delete_rows: table id 120 flags: STMT_END_F

BINLOG '
yFP9XhMBAAAAOQAAACcKAAAAAHgAAAAAAAEABHRlc3QAC2JpbmxvZ19kZW1vAAMDAxEBAAIaymaN
yFP9XiABAAAAMAAAAFcKAAAAAHgAAAAAAAEAAgAD//gEAAAABAAAAF7/VgD1e3dZ
'/*!*/;
### DELETE FROM `test`.`binlog_demo`
### WHERE
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
###   @2=4 /* INT meta=0 nullable=1 is_null=0 */
###   @3=1593792000 /* TIMESTAMP(0) meta=0 nullable=0 is_null=0 */
# at 2647
#200702 11:26:00 server id 1  end_log_pos 2678 CRC32 0xba0bb150     Xid = 86
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*/;

以上内容中字段值简单介绍

  • server_id可以保证服务标识和做互主的时候避免循环导入binlog
  • CRC32 ,即show variables like "%binlog%"里设置binlog_checksum的校验方式
  • Table_map 也是一个事件,但只支持row格式的(statement本身就是一条sql)就是一个表与id的映射,操作多个就会对应多个
  • Delete_rows 是ROWS_EVENT之一,常见的还有UPDATE_ROWS_EVENT, WRITE_ROWS_EVENT ,其他事件.
  • where 就是sql语句里的where条件的具体值
  • Xid和commit就代表最终ok

切换到statement

mysql>  SET SESSION binlog_format = 'STATEMENT';
Query OK, 0 rows affected (0.00 sec)

insert into binlog_demo values(6,66,'2020-07-06');

接上面的39行

*************************** 40. row ***************************
   Log_name: mysql-bin.000007
        Pos: 2743
 Event_type: Query
  Server_id: 1
End_log_pos: 2830
       Info: BEGIN
*************************** 41. row ***************************
   Log_name: mysql-bin.000007
        Pos: 2830
 Event_type: Query
  Server_id: 1
End_log_pos: 2961
       Info: use `test`; insert into binlog_demo values(6,66,'2020-07-06')
*************************** 42. row ***************************
   Log_name: mysql-bin.000007
        Pos: 2961
 Event_type: Xid
  Server_id: 1
End_log_pos: 2992
       Info: COMMIT /* xid=114 */
42 rows in set (0.00 sec)
PS: End_log_posshow master status里的数据 pos大小是保持一致的

从2743行开始看 mysqlbinlog -vv mysql-bin.000007 --start-position=2743

PS: mysqlbinlog一些常用参数:
 --base64-output=decode-rows –v 
 --start-position --stop-position
 --start-time= --stop-time
 --read-from-remote-server
root@base2018:/var/log/mysql# mysqlbinlog -vv mysql-bin.000007 --start-position=2743
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#200702 10:24:14 server id 1  end_log_pos 123 CRC32 0xa97adc3a     Start: binlog v 4, server v 5.7.30-0ubuntu0.16.04.1-log created 200702 10:24:14 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
TkX9Xg8BAAAAdwAAAHsAAAABAAQANS43LjMwLTB1YnVudHUwLjE2LjA0LjEtbG9nAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABORf1eEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQA
ATrceqk=
'/*!*/;
# at 2743
#200702 11:58:33 server id 1  end_log_pos 2830 CRC32 0xa47b4e54     Query    thread_id=10    exec_time=0    error_code=0
SET TIMESTAMP=1593662313/*!*/;
SET @@session.pseudo_thread_id=10/*!*/;
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 utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.time_zone='SYSTEM'/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 2830
#200702 11:58:33 server id 1  end_log_pos 2961 CRC32 0x48d934c7     Query    thread_id=10    exec_time=0    error_code=0
use `test`/*!*/;
SET TIMESTAMP=1593662313/*!*/;
insert into binlog_demo values(6,66,'2020-07-06')
/*!*/;
# at 2961
#200702 11:58:33 server id 1  end_log_pos 2992 CRC32 0x39d367e0     Xid = 114
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*/;

row 和statement不同

row格式的BEGINCOMMIT之间的内容不同,statement只是存了insert语句(包括了我们没有 显示执行的use test;),并且带有一个 SET TIMESTAMP(这个时间可以理解为当前操作上下文的时间,避免在主从同步时发生时间不一致的问题比如一个CURRENT_TIME,NOW(),我理解就类似于linuxntp)

delete语句肯能导致数据不一致(statement模式)

上面是一个插入语句,比较简单,我们看一下特殊的删除情况 。再呈现一下上下文关系。

表中一共6条数据,且两个索引

mysql> select * from binlog_demo;
+----+----+---------------------+
| id | a  | t_modified          |
+----+----+---------------------+
|  1 |  1 | 2020-07-01 00:00:00 |
|  2 |  2 | 2020-07-02 00:00:00 |
|  3 |  3 | 2020-07-02 00:00:00 |
|  5 |  5 | 2020-07-05 00:00:00 |
|  6 | 66 | 2020-06-01 00:00:00 |
+----+----+---------------------+
5 rows in set
show index from binlog_demo;
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table       | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| binlog_demo |          0 | PRIMARY    |            1 | id          | A         |           5 | NULL     | NULL   |      | BTREE      |         |               |
| binlog_demo |          1 | a          |            1 | a           | A         |           5 | NULL     | NULL   | YES  | BTREE      |         |               |
| binlog_demo |          1 | t_modified |            1 | t_modified  | A         |           4 | NULL     | NULL   |      | BTREE      |         |               |
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

默认走的索引是a

mysql> select * from binlog_demo   where a>=4 and t_modified<='2020-07-10' limit 1;
+----+---+---------------------+
| id | a | t_modified          |
+----+---+---------------------+
|  5 | 5 | 2020-07-05 00:00:00 |
+----+---+---------------------+
1 row in set

mysql> explain select * from binlog_demo   where a>=4 and t_modified<='2020-07-10' limit 1;
+----+-------------+-------------+------------+-------+---------------+-----+---------+------+------+----------+------------------------------------+
| id | select_type | table       | partitions | type  | possible_keys | key | key_len | ref  | rows | filtered | Extra                              |
+----+-------------+-------------+------------+-------+---------------+-----+---------+------+------+----------+------------------------------------+
|  1 | SIMPLE      | binlog_demo | NULL       | range | a,t_modified  | a   | 5       | NULL |    2 |      100 | Using index condition; Using where |
+----+-------------+-------------+------------+-------+---------------+-----+---------+------+------+----------+------------------------------------+

强行指定使用索引t_modified

mysql> select * from binlog_demo use index(t_modified)  where a>=4 and t_modified<='2020-07-10' limit 1;
+----+----+---------------------+
| id | a  | t_modified          |
+----+----+---------------------+
|  6 | 66 | 2020-06-01 00:00:00 |
+----+----+---------------------+
1 row in set

mysql> explain select * from binlog_demo use index(t_modified)  where a>=4 and t_modified<='2020-07-10' limit 1;
+----+-------------+-------------+------------+-------+---------------+------------+---------+------+------+----------+------------------------------------+
| id | select_type | table       | partitions | type  | possible_keys | key        | key_len | ref  | rows | filtered | Extra                              |
+----+-------------+-------------+------------+-------+---------------+------------+---------+------+------+----------+------------------------------------+
|  1 | SIMPLE      | binlog_demo | NULL       | range | t_modified    | t_modified | 4       | NULL |    5 |    33.33 | Using index condition; Using where |
+----+-------------+-------------+------------+-------+---------------+------------+---------+------+------+----------+------------------------------------+
1 row in set

可以看出用默认索引查到的数据id为5,force index后查到的id为6.
那我们执行
delete from binlog_demo where a>=4 and t_modified<='2020-07-10' limit 1;的话,可以想到从库上执行的时候不一定也是按照同样的索引选择策略,这样可能导致不一致。所以row格式的就可以避免这个问题,row会将操作每行的信息都记录下来。这样能保证完全一致。
row 格式的

root@base2018:/var/log/mysql# mysqlbinlog -vv mysql-bin.000007 --start-position=2992;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#200702 10:24:14 server id 1  end_log_pos 123 CRC32 0xa97adc3a     Start: binlog v 4, server v 5.7.30-0ubuntu0.16.04.1-log created 200702 10:24:14 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
TkX9Xg8BAAAAdwAAAHsAAAABAAQANS43LjMwLTB1YnVudHUwLjE2LjA0LjEtbG9nAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABORf1eEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQA
ATrceqk=
'/*!*/;
# at 2992
#200702 12:19:31 server id 1  end_log_pos 3057 CRC32 0x10b875ba     Anonymous_GTID    last_committed=10    sequence_number=11    rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 3057
#200702 12:19:31 server id 1  end_log_pos 3144 CRC32 0x8f84f3a7     Query    thread_id=15    exec_time=0    error_code=0
SET TIMESTAMP=1593663571/*!*/;
SET @@session.pseudo_thread_id=15/*!*/;
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 utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.time_zone='SYSTEM'/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 3144
#200702 12:19:31 server id 1  end_log_pos 3302 CRC32 0x450cca73     Query    thread_id=15    exec_time=0    error_code=0
use `test`/*!*/;
SET TIMESTAMP=1593663571/*!*/;
UPDATE `binlog_demo` SET `t_modified`='2020-06-01 00:00:00' WHERE (`id`='6')
/*!*/;
# at 3302
#200702 12:19:31 server id 1  end_log_pos 3333 CRC32 0x73ca56b1     Xid = 132
COMMIT/*!*/;
# at 3333
#200702 12:27:03 server id 1  end_log_pos 3398 CRC32 0xad1d9f72     Anonymous_GTID    last_committed=11    sequence_number=12    rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 3398
#200702 12:27:03 server id 1  end_log_pos 3478 CRC32 0xccf08199     Query    thread_id=14    exec_time=0    error_code=0
SET TIMESTAMP=1593664023/*!*/;
BEGIN
/*!*/;
# at 3478
#200702 12:27:03 server id 1  end_log_pos 3535 CRC32 0x9946e0d7     Table_map: `test`.`binlog_demo` mapped to number 120
# at 3535
#200702 12:27:03 server id 1  end_log_pos 3583 CRC32 0x86c26c2a     Delete_rows: table id 120 flags: STMT_END_F

BINLOG '
F2L9XhMBAAAAOQAAAM8NAAAAAHgAAAAAAAEABHRlc3QAC2JpbmxvZ19kZW1vAAMDAxEBAALX4EaZ
F2L9XiABAAAAMAAAAP8NAAAAAHgAAAAAAAEAAgAD//gFAAAABQAAAF8Ap4AqbMKG
'/*!*/;
### DELETE FROM `test`.`binlog_demo`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=5 /* INT meta=0 nullable=1 is_null=0 */
###   @3=1593878400 /* TIMESTAMP(0) meta=0 nullable=0 is_null=0 */
# at 3583
#200702 12:27:03 server id 1  end_log_pos 3614 CRC32 0xe2c7ad74     Xid = 140
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*/;

statement下delete 的warning

Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.

mysql> SET SESSION binlog_format = 'STATEMENT';
Query OK, 0 rows affected (0.00 sec)

mysql> delete from binlog_demo  where a>=2 and t_modified<='2020-07-10' limit 1;
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> show warnings\G
*************************** 1. row ***************************
  Level: Note
   Code: 1592
Message: Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
1 row in set (0.00 sec)

ROW格式下没有warning

mysql> SET SESSION binlog_format = 'ROW';
Query OK, 0 rows affected (0.00 sec)

mysql> delete from binlog_demo  where a>=2 and t_modified<='2020-07-10' limit 1;
Query OK, 1 row affected (0.05 sec)

*************************** 52. row ***************************
   Log_name: mysql-bin.000007
        Pos: 3614
 Event_type: Anonymous_Gtid
  Server_id: 1
End_log_pos: 3679
       Info: SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
*************************** 53. row ***************************
   Log_name: mysql-bin.000007
        Pos: 3679
 Event_type: Query
  Server_id: 1
End_log_pos: 3766
       Info: BEGIN
*************************** 54. row ***************************
   Log_name: mysql-bin.000007
        Pos: 3766
 Event_type: Query
  Server_id: 1
End_log_pos: 3920
       Info: use `test`; delete from binlog_demo  where a>=2 and t_modified<='2020-07-10' limit 1
*************************** 55. row ***************************
   Log_name: mysql-bin.000007
        Pos: 3920
 Event_type: Xid
  Server_id: 1
End_log_pos: 3951
       Info: COMMIT /* xid=159 */
*************************** 56. row ***************************
   Log_name: mysql-bin.000007
        Pos: 3951
 Event_type: Anonymous_Gtid
  Server_id: 1
End_log_pos: 4016
       Info: SET @@SESSION.GTID_NEXT= 'ANONYMOUS'
*************************** 57. row ***************************
   Log_name: mysql-bin.000007
        Pos: 4016
 Event_type: Query
  Server_id: 1
End_log_pos: 4096
       Info: BEGIN
*************************** 58. row ***************************
   Log_name: mysql-bin.000007
        Pos: 4096
 Event_type: Table_map
  Server_id: 1
End_log_pos: 4153
       Info: table_id: 120 (test.binlog_demo)
*************************** 59. row ***************************
   Log_name: mysql-bin.000007
        Pos: 4153
 Event_type: Delete_rows
  Server_id: 1
End_log_pos: 4201
       Info: table_id: 120 flags: STMT_END_F
*************************** 60. row ***************************
   Log_name: mysql-bin.000007
        Pos: 4201
 Event_type: Xid
  Server_id: 1
End_log_pos: 4232
       Info: COMMIT /* xid=165 */
60 rows in set (0.00 sec)



root@base2018:/var/log/mysql# mysqlbinlog -vv mysql-bin.000007 --start-position=3614
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#200702 10:24:14 server id 1  end_log_pos 123 CRC32 0xa97adc3a     Start: binlog v 4, server v 5.7.30-0ubuntu0.16.04.1-log created 200702 10:24:14 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
TkX9Xg8BAAAAdwAAAHsAAAABAAQANS43LjMwLTB1YnVudHUwLjE2LjA0LjEtbG9nAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAABORf1eEzgNAAgAEgAEBAQEEgAAXwAEGggAAAAICAgCAAAACgoKKioAEjQA
ATrceqk=
'/*!*/;
# at 3614
#200702 12:38:24 server id 1  end_log_pos 3679 CRC32 0x0937d47a     Anonymous_GTID    last_committed=12    sequence_number=13    rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 3679
#200702 12:38:24 server id 1  end_log_pos 3766 CRC32 0x92b2ee24     Query    thread_id=14    exec_time=0    error_code=0
SET TIMESTAMP=1593664704/*!*/;
SET @@session.pseudo_thread_id=14/*!*/;
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 utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.time_zone='SYSTEM'/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 3766
#200702 12:38:24 server id 1  end_log_pos 3920 CRC32 0x22d50c86     Query    thread_id=14    exec_time=0    error_code=0
use `test`/*!*/;
SET TIMESTAMP=1593664704/*!*/;
delete from binlog_demo  where a>=2 and t_modified<='2020-07-10' limit 1
/*!*/;
# at 3920
#200702 12:38:24 server id 1  end_log_pos 3951 CRC32 0x35efdb16     Xid = 159
COMMIT/*!*/;
# at 3951
#200702 12:42:08 server id 1  end_log_pos 4016 CRC32 0xd357905c     Anonymous_GTID    last_committed=13    sequence_number=14    rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 4016
#200702 12:42:08 server id 1  end_log_pos 4096 CRC32 0xfbb008a4     Query    thread_id=14    exec_time=0    error_code=0
SET TIMESTAMP=1593664928/*!*/;
BEGIN
/*!*/;
# at 4096
#200702 12:42:08 server id 1  end_log_pos 4153 CRC32 0xc7c76464     Table_map: `test`.`binlog_demo` mapped to number 120
# at 4153
#200702 12:42:08 server id 1  end_log_pos 4201 CRC32 0xa7203e07     Delete_rows: table id 120 flags: STMT_END_F

BINLOG '
oGX9XhMBAAAAOQAAADkQAAAAAHgAAAAAAAEABHRlc3QAC2JpbmxvZ19kZW1vAAMDAxEBAAJkZMfH
oGX9XiABAAAAMAAAAGkQAAAAAHgAAAAAAAEAAgAD//gDAAAAAwAAAF78swAHPiCn
'/*!*/;
### DELETE FROM `test`.`binlog_demo`
### WHERE
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2=3 /* INT meta=0 nullable=1 is_null=0 */
###   @3=1593619200 /* TIMESTAMP(0) meta=0 nullable=0 is_null=0 */
# at 4201
#200702 12:42:08 server id 1  end_log_pos 4232 CRC32 0x21a1766f     Xid = 165
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*/;

写在最后

  1. 关于Binlog:
    Binlog是MySql Server层的实现,虽然也有所谓的commit,但是这个commit与具体实现引擎无关(与innodb的 事务日志redo/undo不冲突)。主要是做主从,备份/恢复用的。
  2. 关于mixed,顾名思义。两者结合是最好的,是可以自动判断是否会影响主备不一致。
  3. row 模式会针对每行都会记录,delete一行就会有一行记录, 其中binlog_row_image 决定了记录的多少

    • full 记录所有的列
    • minimal 记录变化的列
    • noblob 记录除去blob和text之外的列
      这样就直接导致row格式的binlog就会很大。

你可能感兴趣的:(binlog,mysql主从,mysql)