binlog_row_image使用FULL不要使用MINIMAL

背景

  binlog_row_image这个参数是MySQL5.6新增的参数,默认值是FULL,在5.7版本默认值也是FULL,但今天看到公司这边的MySQL5.7最新参数规范文档修改了这个参数的值,从FULL修改为MINIMAL,我对这个修改表示疑惑。

参数解释

前提:
binlog格式必须为row格式或者mixed格式,不可以是statement格式。
名称解释:
before image:前镜像,即数据库表中修改前的内容。
after image:后镜像,即数据库表中修改后的内容。
---
这个参数不同值的作用如下:
FULL:Log all columns in both the before image and the after image.
binlog日志记录所有前镜像和后镜像。


MINIMAL: Log only those columns in the before image that are required to identify the row to be changed; log only those columns in the after image where a value was specified by the SQL statement, or generated by auto-increment.
binlog日志的前镜像只记录唯一识别列(唯一索引列、主键列),后镜像只记录改变列。


noblob:Log all columns (same as full), except for BLOB and TEXT columns that are not required to identify rows, or that have not changed.
binlog记录所有的列,就像full格式一样。但对于BLOB或TEXT格式的列,如果他不是唯一识别列(唯一索引列、主键列),或者没有修改,那就不记录。
---

For the before image, it is necessary only that the minimum set of columns required to uniquely identify rows is logged. If the table containing the row has a primary key, then only the primary key column or columns are written to the binary log. Otherwise, if the table has a unique key all of whose columns are NOT NULL, then only the columns in the unique key need be logged. (If the table has neither a primary key nor a unique key without any NULL columns, then all columns must be used in the before image, and logged.) In the after image, it is necessary to log only the columns which have actually changed.

官方提到:如果没有唯一识别列(唯一索引列、主键列),例如只有普通key,那么MINIMAL格式的前镜像也会记录所有所有列,但后镜像依然只记录修改列。

分析

  这个参数如果设置成MINIMAL格式,可以节省不少磁盘空间,节省一定的io。但由于前镜像不记录修改列,只在后镜像记录修改列,如果数据出现误操作,必然不能通过flashback或binlog2sql等快速闪回工具恢复数据,因为不能通过binlog生成反向sql了。

  在硬盘白菜价的今天,硬盘空间不是非常大的问题,安全才是最大问题,所以我认为binlog_row_image必须设置为FULL格式了。

测试如下:

1.测试binlog_row_image=MINIMAL

1.1 测试没有主键没有唯一索引

看是否前镜像全保留

drop table test;
create table test
(
  id int(11) NOT NULL ,
  name varchar(20) DEFAULT NULL,
  key (id)
);
insert into test value (1,'aa'),(2,'bb'),(3,'cc'),(4,'dd'),(5,'ee');
update test set name='xxx';

日志如下:

### UPDATE `test57`.`test`
### WHERE
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2='aa' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### SET
###   @2='xxx' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2='bb' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### SET
###   @2='xxx' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2='cc' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### SET
###   @2='xxx' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
###   @2='dd' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### SET
###   @2='xxx' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2='ee' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### SET
###   @2='xxx' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */

binlog_row_image=MINIMAL,没有主键没有唯一索引,确实前镜像全保留,后镜像只有修改列

1.2 测试有主键

看是否前镜像只有主键列,后镜像只有修改列

create table test
(
  id int(11) NOT NULL AUTO_INCREMENT,
  name varchar(20) DEFAULT NULL,
  primary key (id)
);
insert into test value (1,'aa'),(2,'bb'),(3,'cc'),(4,'dd'),(5,'ee');
update test set name='xxx';

日志如下:

### UPDATE `test57`.`test`
### WHERE
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @2='xxx' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @2='xxx' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @2='xxx' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @2='xxx' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @2='xxx' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */

确实前镜像只有主键列,后镜像只有修改列。就这个原因,导致不能闪回数据,安全性考虑不应该使用binlog_row_image=MINIMAL。

2 测试 binlog_row_image=noblob

2.1 测试没有主键没有唯一索引

由于没有主键没有唯一索引,所以前镜像是全保留,因为TEXT/blob是修改列,所以后镜像的TEXT/blob列也被保留了。整体和FULL格式一致。

mysql> set global binlog_row_image='noblob';
Query OK, 0 rows affected (0.00 sec)


drop table test;
create table test
(
  id int(11) NOT NULL ,
  id2 int(11) NOT NULL,
  name text DEFAULT NULL,
  key (id)
);
insert into test value (1,1,'aa'),(2,2,'bb'),(3,3,'cc'),(4,4,'dd'),(5,5,'ee');
update test set name='xxx';

日志如下:

### UPDATE `test57`.`test`
### WHERE
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=1 /* INT meta=0 nullable=0 is_null=0 */
###   @3='aa' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### SET
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=1 /* INT meta=0 nullable=0 is_null=0 */
###   @3='xxx' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */
###   @3='bb' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### SET
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */
###   @3='xxx' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2=3 /* INT meta=0 nullable=0 is_null=0 */
###   @3='cc' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### SET
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2=3 /* INT meta=0 nullable=0 is_null=0 */
###   @3='xxx' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
###   @2=4 /* INT meta=0 nullable=0 is_null=0 */
###   @3='dd' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### SET
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
###   @2=4 /* INT meta=0 nullable=0 is_null=0 */
###   @3='xxx' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=5 /* INT meta=0 nullable=0 is_null=0 */
###   @3='ee' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### SET
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=5 /* INT meta=0 nullable=0 is_null=0 */
###   @3='xxx' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
2.2测试有主键

有主键,修改列依然是TEXT/blob列,由于有主键了,所以前镜像不会强迫包含所有列,但前镜像的的TEXT列被忽略、不包含,后镜像的TEXT列由于是修改列,所以包含。

mysql> set global binlog_row_image='noblob';
Query OK, 0 rows affected (0.00 sec)


drop table test;
create table test
(
  id int(11) NOT NULL ,
  id2 int(11) NOT NULL,
  name text DEFAULT NULL,
  primary key (id)
);
insert into test value (1,1,'aa'),(2,2,'bb'),(3,3,'cc'),(4,4,'dd'),(5,5,'ee');
update test set name='xxx';

日志如下:

### UPDATE `test57`.`test`
### WHERE
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=1 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=1 /* INT meta=0 nullable=0 is_null=0 */
###   @3='xxx' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */
###   @3='xxx' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2=3 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2=3 /* INT meta=0 nullable=0 is_null=0 */
###   @3='xxx' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
###   @2=4 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
###   @2=4 /* INT meta=0 nullable=0 is_null=0 */
###   @3='xxx' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=5 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=5 /* INT meta=0 nullable=0 is_null=0 */
###   @3='xxx' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */

实验证明binlog_row_image=noblob这个格式,依然存在缺失前镜像的问题,导致某些场景无法闪回,所以也不推荐设置。

2.3测试有主键,修改列也不是TEXT列
drop table test;
create table test
(
  id int(11) NOT NULL ,
  id2 int(11) NOT NULL,
  name text DEFAULT NULL,
  primary key (id)
);
insert into test value (1,1,'aa'),(2,2,'bb'),(3,3,'cc'),(4,4,'dd'),(5,5,'ee');
update test set id2=2;

日志如下:

### UPDATE `test57`.`test`
### WHERE
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=1 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2=3 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
###   @2=4 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */
### UPDATE `test57`.`test`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=5 /* INT meta=0 nullable=0 is_null=0 */
### SET
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */

前镜像和后镜像包含除TEXT/BLOB列之外的所有列

结论

我们公司生产安全大于一切,不应该设置binlog_row_image=MINIMAL参数,应该继续使用默认值binlog_row_image=FULL

猜你喜欢

转载自www.cnblogs.com/fander/p/9298660.html