日期:2014-05-16  浏览次数:20680 次

对MySQL load data infile的一点想法

        今天无意和同事讨论MySQL load data infile的问题,这个问题是由开发那边引起的:他们竟然对一个4千万行的数据直接load data infile插入测试库,结果可想而知,出问题了。跑了一整晚都没跑完,基本上是卡死了。分析原因可能是load data infile是一个事务,而事务过程中要写redo,但一个事务这么大单个redo(几百M吧)势必又记录不了,因为此时一个事务,所以不可能将自己的同一个事务的redo覆盖掉的,所以导致卡死(个人猜测,不知道是否正确)。于是做了一个实验验证load data infile是否为一个单独的事务。

        步骤是这样的:1,开启binlog,设置binlog_format=row,执行reset master;2,load data infile xxxxx;3,查看binlog。发现如下信息:

mysql> show binlog events;
+------------------+------+-------------+-----------+-------------+---------------------------------------+
| Log_name         | Pos  | Event_type  | Server_id | End_log_pos | Info                                  |
+------------------+------+-------------+-----------+-------------+---------------------------------------+
| mysql-bin.000001 |    4 | Format_desc |         2 |         106 | Server ver: 5.1.62-log, Binlog ver: 4 | 
| mysql-bin.000001 |  106 | Query       |         2 |         174 | BEGIN                                 | 
| mysql-bin.000001 |  174 | Table_map   |         2 |         220 | table_id: 17 (test.test)              | 
| mysql-bin.000001 |  220 | Write_rows  |         2 |        1259 | table_id: 17                          | 
| mysql-bin.000001 | 1259 | Write_rows  |         2 |        2298 | table_id: 17                          | 
| mysql-bin.000001 | 2298 | Write_rows  |         2 |        3337 | table_id: 17                          | 
| mysql-bin.000001 | 3337 | Write_rows  |         2 |        4376 | table_id: 17                          | 
| mysql-bin.000001 | 4376 | Write_rows  |         2 |        5365 | table_id: 17 flags: STMT_END_F        | 
| mysql-bin.000001 | 5365 | Xid         |         2 |        5392 | COMMIT /* xid=681 */                  | 
+------------------+------+-------------+-----------+-------------+---------------------------------------+

可以看出,总共是一个事务,也通过mysqlbinlog查看了binary log,确认中间是被拆分成了多个insert形式。所以load data infile基本上是这样执行的:

begin
insert into values(),(),(),()...
insert into values(),(),(),()...
insert into values(),(),(),()...
...
...
commit 


分析到这,我就有一个想法:为什么不提供一个选项来执行一个load data infile来拆成成多个事务呢?这样最后整个语句执行成功的可能性更大吧,虽然我们可以自己通过拆分文件来做到这点,但是官方有命令来支持不是更好吗?