Mysql中load data infile主从复制注意点

在mysql官方文档的描述里,load data infile加载数据要比普通的insert快20倍,可以说是插入数据最快的方式了,所以在很多场合都会用它来提升入库速度。

那它在主从架构中的从库上会怎么执行呢?(主从复制官网)刚开始我假定是在master上load成功后会以batch insert方式dump进binlog,从库IO线程请求binlog,最后SQL线程以batch insert执行一遍,同样能做到主从同步。但即使是batch insert方式,按照官方文档的解释,也是会比load data infile慢的。在master端load压力足够大的情况下,主从延迟可能会无法忍受。带着这样的疑问,我准备做个测试

准备一个数据的文件(2M)为了防止load过快而无法在从库上观察到,设置循环load 30次,然后在从库端show processlist观察执行情况,结果如下截图:

load-data-infile.jpg

通过测试可以发现

load data infile在master端执行成功后会把数据文件写入到binlog里(可用mysqlbinlog分析),在从库IO线程获取binlog写到本地relay-log,SQL线程会将数据文件extract到临时目录(默认/tmp,见tmp.io.dir变量值),再执行load命令将数据文件加载进从库(在从库show processlist可以观察到此现象),最终把数据临时目录的文件删除掉。

这样保证slave与master执行相同,同时也保证了入库速度,主从延迟不会那么明显(但也不一定,见后文)

上文已经提到master执行load成功后会将数据文件写入binlog,那问题又来了,如果这个文件足够大(比如 :50G 囧),主从同步效率会如何呢,我们可以想象,至少会有两个问题:
1,主从延迟
我们将这个阶段划分成以下几个步骤便于理解:
master端: load 50G into table ,dump into binlog
slave端: get binlog & write into relay log; extract relay log and write data into tmpdir; load into table&delete file
假定在master端执行要2小时,那么从库至少要延迟2小时(why? 除了主从都执行load外,计算一下数据文件被写入传输了多少次)

2,主从数据不一致
由于同步耗时长,发生异常的可能性也跟着变大,最大而且最有可能发生的问题 临时目录空间不足,导致数据写入临时目录失败而无法load,主从一致性就被打破了。

以上两个问题对于主从复制来说是非常要命的,但是有问题总会有解决办法的
solution A: 当然要避免以上的问题可以将大文件 split成小文件load入库(如果不要求在一个事务里的话)。
solution B: 如果要求在一个事务里,那就主从都手动的执行load,显示的指定master不写binlog,取消check外键。个人觉得这是最可取也最高效的方式(即使不要求在一个事务也可用这个方法),因为可以并行load,解决了延迟大的问题,另外减少了数据写入次数,可以手动指定数据存储目录,也就降低了执行时发生异常的几率,从而保证主从数据一致性。

至于如何操作可用这条命令:

time mysql -e "set foreign_key_checks=0; set sql_log_bin=0; set unique_checks=0; load data local infile 'infile.txt' into table load_test fields terminated by '\t' lines terminated by '\n' (col1, col2);" 

注意: time命令是用于统计执行时间的

至于如何操作可用这条命令:

time mysql -e "set foreign_key_checks=0; set sql_log_bin=0; set unique_checks=0; load data local infile 'infile.txt' into table load_test fields terminated by '\t' lines terminated by '\n' (col1, col2);" 

注意: time命令是用于统计执行时间的
对于普通文件load到一半发生异常(虽然在 Mysql Load Data容错性测试 能智能的兼容各种异常数据,但不能排除有其他异常),导致后半数据不能成功写入,在这种情况下,主库是不会将加载成功的数据文件dump到binlog的,这样主从数据的一致性又被打破了,所以考虑用load的时候需要注意这一点。

参考:

官网主从复制:http://dev.mysql.com/doc/refman/5.1/zh/replication.html#replication-intro

how to safely load large file into innodb with load data infile

添加新评论