diff options
author | unknown <guilhem@mysql.com> | 2003-09-25 00:14:46 +0200 |
---|---|---|
committer | unknown <guilhem@mysql.com> | 2003-09-25 00:14:46 +0200 |
commit | dae13b541540953f11397d70f482b77d07699f77 (patch) | |
tree | 5d0a4646226c2ebce870b175a81f47d772220f12 | |
parent | 699f3175fe5e28b5e017dbd73a6dafa21d8a410b (diff) | |
download | mariadb-git-dae13b541540953f11397d70f482b77d07699f77.tar.gz |
Fix for BUG#1391:
"If LOAD DATA INFILE 'small_file' fails on master, slave leaves temp files"
(the bug is in the master)
mysql-test/r/rpl_loaddata.result:
result update
mysql-test/std_data/rpl_loaddata2.dat:
change to introduce a unique key violation
mysql-test/t/rpl_loaddata.test:
testcase for bug#1391.
sql/sql_load.cc:
fix for bug#1391:
for a small file, we had in the binlog only the Create_file, not the Delete_file
(the Create_file was written when the READ_INFO was destroyed).
-rw-r--r-- | mysql-test/r/rpl_loaddata.result | 13 | ||||
-rw-r--r-- | mysql-test/std_data/rpl_loaddata2.dat | 2 | ||||
-rw-r--r-- | mysql-test/t/rpl_loaddata.test | 15 | ||||
-rw-r--r-- | sql/sql_load.cc | 39 |
4 files changed, 52 insertions, 17 deletions
diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result index 0302381c119..8b910d0d183 100644 --- a/mysql-test/r/rpl_loaddata.result +++ b/mysql-test/r/rpl_loaddata.result @@ -19,7 +19,7 @@ select * from t3; day id category name 2003-02-22 2461 b a a a @ % ' " a 2003-03-22 2161 c asdf -2003-04-22 2416 a bbbbb +2003-03-22 2416 a bbbbb show master status; File Position Binlog_do_db Binlog_ignore_db slave-bin.001 964 @@ -55,3 +55,14 @@ reset slave; show slave status; Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.001 4 No No 0 0 0 4 +reset master; +create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), +unique(day)); +load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by +'\n##\n' starting by '>' ignore 1 lines; +Duplicate entry '2003-03-22' for key 1 +show master status; +File Position Binlog_do_db Binlog_ignore_db +master-bin.001 491 +drop table t2; diff --git a/mysql-test/std_data/rpl_loaddata2.dat b/mysql-test/std_data/rpl_loaddata2.dat index b883d9dcd58..04d84f1f45e 100644 --- a/mysql-test/std_data/rpl_loaddata2.dat +++ b/mysql-test/std_data/rpl_loaddata2.dat @@ -4,5 +4,5 @@ ## >2003-03-22,2161,%c%,%asdf% ## ->2003-04-22,2416,%a%,%bbbbb% +>2003-03-22,2416,%a%,%bbbbb% ## diff --git a/mysql-test/t/rpl_loaddata.test b/mysql-test/t/rpl_loaddata.test index 4c4ff6a093e..a3bb8c9aec9 100644 --- a/mysql-test/t/rpl_loaddata.test +++ b/mysql-test/t/rpl_loaddata.test @@ -112,3 +112,18 @@ stop slave; reset slave; --replace_result $MASTER_MYPORT MASTER_PORT show slave status; + +# Finally, see if logging is done ok on master for a failing LOAD DATA INFILE + +connection master; +reset master; +create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), +unique(day)); +--error 1062; +load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by +'\n##\n' starting by '>' ignore 1 lines; +# To test that there is Create_file & Delete_file, we test if the binlog is as +# long as expected (can't do SHOW BINLOG EVENTS because of varying file_id). +show master status; +drop table t2; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 0ae6ccb4c4a..ca540a8cdc0 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -282,22 +282,31 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ha_autocommit_or_rollback(thd,error); if (!opt_old_rpl_compat && mysql_bin_log.is_open()) { + /* + Make sure last block (the one which caused the error) gets logged. + This is needed because otherwise after write of + (to the binlog, not to read_info (which is a cache)) + Delete_file_log_event the bad block will remain in read_info (because + pre_read is not called at the end of the last block; remember pre_read + is called whenever a new block is read from disk). + At the end of mysql_load(), the destructor of read_info will call + end_io_cache() which will flush read_info, so we will finally have + this in the binlog: + Append_block # The last successfull block + Delete_file + Append_block # The failing block + which is nonsense. + Or could also be (for a small file) + Create_file # The failing block + which is nonsense (Delete_file is not written in this case, because: + Create_file has not been written, so Delete_file is not written, then + when read_info is destroyed end_io_cache() is called which writes + Create_file. + */ + read_info.end_io_cache(); + /* If the file was not empty, wrote_create_file is true */ if (lf_info.wrote_create_file) { - /* - Make sure last block (the one which caused the error) gets logged. - This is needed because otherwise after write of - (to the binlog, not to read_info (which is a cache)) - Delete_file_log_event the bad block will remain in read_info. - At the end of mysql_load(), the destructor of read_info will call - end_io_cache() which will flush read_info, so we will finally have - this in the binlog: - Append_block # The last successfull block - Delete_file - Append_block # The failing block - which is nonsense. - */ - read_info.end_io_cache(); Delete_file_log_event d(thd, db, log_delayed); mysql_bin_log.write(&d); } @@ -327,7 +336,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, } else { - read_info.end_io_cache(); // make sure last block gets logged + read_info.end_io_cache(); if (lf_info.wrote_create_file) { Execute_load_log_event e(thd, db, log_delayed); |