有时在使用一些函数,比如uuid()时,可能会发现主从有数据不一致的情况,这很大程度与日志模式有关,一起来探究下。STATEMENT模式
主库执行
mysql> create table test(id int(11),`uuid_num` varchar(50));
mysql> set session binlog_format='STATEMENT';
mysql> insert into test values(1,uuid());
mysql> select * from test;
从库执行
mysql> select * from test;
现在导致主从数据不一致了
原因:
Binlog在 statement模式下每一条会修改数据的sql都会记录到master的binlog中,slave在复制时sql进程会解析成和原来master端执行过的相同的sql再次执行。因此uuid()函数是分别在主从库执行的结构,导致主从数据不一致。
那么ROW模式和MIXED模式下结果又会怎样呢?继续试验
ROW模式
主库执行
mysql> set session binlog_format='ROW';
mysql> insert into test values(2,uuid());
mysql> select * from test;
从库执行
mysql> select * from test;
是一样的,说明row模式不会出现时UUID函数导致数据不一致的情况。
原因:
ROW模式下,日志中会记录成每一行数据被修改的形式,然后再slave端再对相同的数据进行修改。
MIXED模式
主库执行
mysql> set session binlog_format='MIXED';
mysql> insert into test values(3,uuid());
mysql> select * from test;
从库执行
mysql> select * from test;
也是一样的
原因:
在MIXED模式下,一般采用statement格式进行二进制日志文件的记录,但是在一些情况下会使用row格式,可能的情况有:表的存储引擎为NDB,此时对表的DML操作都会以ROW格式记录
使用了UUID(),USER(),CURRENT_USER(),FOUND_ROWS(),ROW_count()等不确定函数时
使用了insert delay语句
使用了用户定义函数(UDF)
使用了临时表
因此,在使用statement模式下,很有可能是有部分函数会导致主从的结果不一致。所以,多数情况不建议使用statement模式。