mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 22:12:30 +01:00
bcb3170c97
With statement- or mixed-mode logging, "LOAD DATA INFILE" queries are written to the binlog using special types of log events. When mysqlbinlog reads such events, it re-creates the file in a temporary directory with a generated filename and outputs a "LOAD DATA INFILE" query where the filename is replaced by the generated file. The temporary file is not deleted by mysqlbinlog after termination. To fix the problem, in mixed mode we go to row-based. In SBR, we document it to remind user the tmpfile is left in a temporary directory. mysql-test/extra/rpl_tests/rpl_loaddata.test: Updated for Bug#34283 mysql-test/suite/binlog/r/binlog_mixed_load_data.result: Test result for BUG#34283. mysql-test/suite/binlog/t/binlog_killed_simulate.test: Updated for Bug#34283 mysql-test/suite/binlog/t/binlog_mixed_load_data.test: Added the test file to verify that 'load data infile...' statement will go to row-based in mixed mode. mysql-test/suite/binlog/t/binlog_stm_blackhole.test: Updated for Bug#34283 mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result: Updated for Bug#34283 mysql-test/suite/rpl/t/rpl_loaddata_fatal.test: Updated for Bug#34283 mysql-test/suite/rpl/t/rpl_loaddata_map.test: Updated for Bug#34283 mysql-test/suite/rpl/t/rpl_slave_load_remove_tmpfile.test: Updated for Bug#34283 mysql-test/suite/rpl/t/rpl_stm_log.test: Updated for Bug#34283 sql/sql_load.cc: Added code to go to row-based in mixed mode for 'load data infile ...' statement
267 lines
8.3 KiB
Text
267 lines
8.3 KiB
Text
# Requires statement logging
|
|
-- source include/have_binlog_format_statement.inc
|
|
|
|
# See if replication of a "LOAD DATA in an autoincrement column"
|
|
# Honours autoincrement values
|
|
# i.e. if the master and slave have the same sequence
|
|
#
|
|
# check replication of load data for temporary tables with additional
|
|
# parameters
|
|
#
|
|
# check if duplicate entries trigger an error (they should unless IGNORE or
|
|
# REPLACE was used on the master) (bug 571).
|
|
#
|
|
# check if START SLAVE, RESET SLAVE, CHANGE MASTER reset Last_slave_error and
|
|
# Last_slave_errno in SHOW SLAVE STATUS (1st and 3rd commands did not: bug 986)
|
|
|
|
-- source include/master-slave.inc
|
|
source include/have_innodb.inc;
|
|
|
|
connection slave;
|
|
reset master;
|
|
connection master;
|
|
|
|
# MTR is not case-sensitive.
|
|
let $lower_stmt_head= load data;
|
|
let $UPPER_STMT_HEAD= LOAD DATA;
|
|
if (`SELECT '$lock_option' <> ''`)
|
|
{
|
|
#if $lock_option is null, an extra blank is added into the statement,
|
|
#this will change the result of rpl_loaddata test case. so $lock_option
|
|
#is set only when it is not null.
|
|
let $lower_stmt_head= load data $lock_option;
|
|
let $UPPER_STMT_HEAD= LOAD DATA $lock_option;
|
|
}
|
|
|
|
select last_insert_id();
|
|
create table t1(a int not null auto_increment, b int, primary key(a) );
|
|
eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1;
|
|
# verify that LAST_INSERT_ID() is set by LOAD DATA INFILE
|
|
select last_insert_id();
|
|
|
|
create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60));
|
|
eval $lower_stmt_head 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;
|
|
|
|
create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60));
|
|
insert into t3 select * from t2;
|
|
|
|
save_master_pos;
|
|
connection slave;
|
|
sync_with_master;
|
|
|
|
select * from t1;
|
|
select * from t3;
|
|
|
|
connection master;
|
|
|
|
drop table t1;
|
|
drop table t2;
|
|
drop table t3;
|
|
create table t1(a int, b int, unique(b));
|
|
|
|
save_master_pos;
|
|
connection slave;
|
|
sync_with_master;
|
|
|
|
# See if slave stops when there's a duplicate entry for key error in LOAD DATA
|
|
|
|
insert into t1 values(1,10);
|
|
|
|
connection master;
|
|
eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1;
|
|
|
|
save_master_pos;
|
|
connection slave;
|
|
# The SQL slave thread should be stopped now.
|
|
--source include/wait_for_slave_sql_to_stop.inc
|
|
|
|
# Skip the bad event and see if error is cleared in SHOW SLAVE STATUS by START
|
|
# SLAVE, even though we are not executing any event (as sql_slave_skip_counter
|
|
# takes us directly to the end of the relay log).
|
|
|
|
set global sql_slave_skip_counter=1;
|
|
start slave;
|
|
sync_with_master;
|
|
let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
|
|
echo Last_SQL_Errno=$last_error;
|
|
let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
|
|
echo Last_SQL_Error;
|
|
echo $last_error;
|
|
|
|
# Trigger error again to test CHANGE MASTER
|
|
|
|
connection master;
|
|
set sql_log_bin=0;
|
|
delete from t1;
|
|
set sql_log_bin=1;
|
|
eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1;
|
|
save_master_pos;
|
|
connection slave;
|
|
# The SQL slave thread should be stopped now.
|
|
# Exec_Master_Log_Pos should point to the start of Execute event
|
|
# for last load data.
|
|
--source include/wait_for_slave_sql_to_stop.inc
|
|
|
|
# CHANGE MASTER and see if error is cleared in SHOW SLAVE STATUS.
|
|
stop slave;
|
|
change master to master_user='test';
|
|
change master to master_user='root';
|
|
let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
|
|
echo Last_SQL_Errno=$last_error;
|
|
let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
|
|
echo Last_SQL_Error;
|
|
echo $last_error;
|
|
|
|
# Trigger error again to test RESET SLAVE
|
|
|
|
set global sql_slave_skip_counter=1;
|
|
start slave;
|
|
sync_with_master;
|
|
connection master;
|
|
set sql_log_bin=0;
|
|
delete from t1;
|
|
set sql_log_bin=1;
|
|
eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1;
|
|
save_master_pos;
|
|
connection slave;
|
|
# The SQL slave thread should be stopped now.
|
|
--source include/wait_for_slave_sql_to_stop.inc
|
|
|
|
# RESET SLAVE and see if error is cleared in SHOW SLAVE STATUS.
|
|
stop slave;
|
|
reset slave;
|
|
let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1);
|
|
echo Last_SQL_Errno=$last_error;
|
|
let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1);
|
|
echo Last_SQL_Error;
|
|
echo $last_error;
|
|
|
|
# Finally, see if logging is done ok on master for a failing LOAD DATA INFILE
|
|
|
|
connection master;
|
|
reset master;
|
|
eval create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60),
|
|
unique(day)) engine=$engine_type; # no transactions
|
|
--error ER_DUP_ENTRY
|
|
eval $lower_stmt_head 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;
|
|
select * from t2;
|
|
save_master_pos;
|
|
connection slave;
|
|
start slave;
|
|
sync_with_master;
|
|
select * from t2;
|
|
|
|
# verify that if no error on slave, this is an error
|
|
|
|
alter table t2 drop key day;
|
|
connection master;
|
|
delete from t2;
|
|
--error ER_DUP_ENTRY
|
|
eval $lower_stmt_head 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;
|
|
connection slave;
|
|
--source include/wait_for_slave_sql_to_stop.inc
|
|
drop table t1, t2;
|
|
connection master;
|
|
drop table t1, t2;
|
|
|
|
# BUG#17233 LOAD DATA INFILE: failure causes mysqld dbug_assert, binlog not flushed
|
|
CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB;
|
|
|
|
--error ER_DUP_ENTRY
|
|
eval $UPPER_STMT_HEAD INFILE "../../std_data/words.dat" INTO TABLE t1;
|
|
|
|
DROP TABLE IF EXISTS t1;
|
|
|
|
# BUG#48297: Schema name is ignored when LOAD DATA is written into binlog,
|
|
# replication aborts
|
|
-- source include/master-slave-reset.inc
|
|
|
|
-- let $db1= b48297_db1
|
|
-- let $db2= b42897_db2
|
|
|
|
-- connection master
|
|
|
|
-- disable_warnings
|
|
-- eval drop database if exists $db1
|
|
-- eval drop database if exists $db2
|
|
-- enable_warnings
|
|
|
|
-- eval create database $db1
|
|
-- eval create database $db2
|
|
|
|
-- eval use $db1
|
|
-- eval CREATE TABLE t1 (c1 VARCHAR(256)) engine=$engine_type;
|
|
|
|
-- eval use $db2
|
|
|
|
-- echo ### assertion: works with cross-referenced database
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1
|
|
|
|
-- eval use $db1
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- echo ### assertion: works with fully qualified name on current database
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1
|
|
|
|
-- echo ### assertion: works without fully qualified name on current database
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1
|
|
|
|
-- echo ### create connection without default database
|
|
-- echo ### connect (conn2,localhost,root,,*NO-ONE*);
|
|
connect (conn2,localhost,root,,*NO-ONE*);
|
|
-- connection conn2
|
|
-- echo ### assertion: works without stating the default database
|
|
-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1
|
|
|
|
# We cannot disconnect right away because when inserting
|
|
# concurrently in a MyISAM table, the server is sending an OK
|
|
# to the client before updating the table state (where the
|
|
# number of records is kept). See: BUG#37521 and BUG#29334.
|
|
# So we need to wait, otherwise we would be having sporadic
|
|
# failures as reported here: BUG#50451.
|
|
|
|
# 12 = 3 rows per each LOAD DATA executed x 4
|
|
-- let $count= 12
|
|
-- let $table= $db1.t1
|
|
--source include/wait_until_rows_count.inc
|
|
|
|
-- echo ### disconnect and switch back to master connection
|
|
-- disconnect conn2
|
|
-- connection master
|
|
|
|
-- sync_slave_with_master
|
|
-- eval use $db1
|
|
|
|
let $diff_table_1=master:$db1.t1;
|
|
let $diff_table_2=slave:$db1.t1;
|
|
source include/diff_tables.inc;
|
|
|
|
-- connection master
|
|
|
|
-- eval DROP DATABASE $db1
|
|
-- eval DROP DATABASE $db2
|
|
|
|
-- sync_slave_with_master
|
|
|
|
# BUG#49479: LOAD DATA INFILE is binlogged without escaping field names
|
|
-- source include/master-slave-reset.inc
|
|
-- connection master
|
|
use test;
|
|
CREATE TABLE t1 (`key` TEXT, `text` TEXT);
|
|
|
|
LOAD DATA INFILE '../../std_data/loaddata2.dat' REPLACE INTO TABLE `t1` FIELDS TERMINATED BY ',';
|
|
SELECT * FROM t1;
|
|
|
|
-- sync_slave_with_master
|
|
-- connection master
|
|
DROP TABLE t1;
|
|
-- sync_slave_with_master
|
|
|
|
# End of 4.1 tests
|