Fix for BUG#11151 "LOAD DATA INFILE commits transaction in 5.0".

In 5.0 we made LOAD DATA INFILE autocommit in all engines, while
only NDB wanted that. Users and trainers complained that it affected
InnoDB and was a change compared to 4.1 where only NDB autocommitted.
To revert to the behaviour of 4.1, we move the autocommit logic out of mysql_load() into
ha_ndbcluster::external_lock().
The result is that LOAD DATA INFILE commits all uncommitted changes
of NDB if this is an NDB table, its own changes if this is an NDB
table, but does not affect other engines.
Note: even though there is no "commit the full transaction at end"
anymore, LOAD DATA INFILE stays disabled in routines (re-entrency
problems per a comment of Pem).
Note: ha_ndbcluster::has_transactions() does not give reliable results
because it says "yes" even if transactions are disabled in this engine...
parent 4d0430c8
# Test if the engine does autocommit in LOAD DATA INFILE, or not
# (NDB wants to do, others don't).
eval SET SESSION STORAGE_ENGINE = $engine_type;
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (a text, b text);
start transaction;
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
commit;
select count(*) from t1;
truncate table t1;
start transaction;
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
rollback;
select count(*) from t1;
drop table t1;
SET SESSION STORAGE_ENGINE = InnoDB;
drop table if exists t1;
create table t1 (a text, b text);
start transaction;
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
Warnings:
Warning 1261 Row 3 doesn't contain data for all columns
commit;
select count(*) from t1;
count(*)
4
truncate table t1;
start transaction;
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
Warnings:
Warning 1261 Row 3 doesn't contain data for all columns
rollback;
select count(*) from t1;
count(*)
0
drop table t1;
SET SESSION STORAGE_ENGINE = ndbcluster;
drop table if exists t1;
create table t1 (a text, b text);
start transaction;
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
Warnings:
Warning 1261 Row 3 doesn't contain data for all columns
commit;
select count(*) from t1;
count(*)
4
truncate table t1;
start transaction;
load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
Warnings:
Warning 1261 Row 3 doesn't contain data for all columns
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
select count(*) from t1;
count(*)
4
drop table t1;
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
create table t1 (a int, unique(a)) engine=ndbcluster;
create table t2 (a int, unique(a)) engine=innodb;
begin;
insert into t1 values(1);
insert into t2 values(1);
rollback;
select count(*) from t1;
count(*)
0
select count(*) from t2;
count(*)
0
select count(*) from t1;
count(*)
0
select count(*) from t2;
count(*)
0
begin;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t2;
Warnings:
Warning 1262 Row 1 was truncated; it contained more data than there were input columns
Warning 1262 Row 2 was truncated; it contained more data than there were input columns
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
Warnings:
Warning 1262 Row 1 was truncated; it contained more data than there were input columns
Warning 1262 Row 2 was truncated; it contained more data than there were input columns
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
select count(*) from t1;
count(*)
2
select count(*) from t2;
count(*)
0
select count(*) from t1;
count(*)
2
select count(*) from t2;
count(*)
0
delete from t1;
delete from t2;
begin;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t2;
Warnings:
Warning 1262 Row 1 was truncated; it contained more data than there were input columns
Warning 1262 Row 2 was truncated; it contained more data than there were input columns
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
Warnings:
Warning 1262 Row 1 was truncated; it contained more data than there were input columns
Warning 1262 Row 2 was truncated; it contained more data than there were input columns
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
select count(*) from t1;
count(*)
2
select count(*) from t2;
count(*)
0
select count(*) from t1;
count(*)
2
select count(*) from t2;
count(*)
0
delete from t1;
delete from t2;
begin;
insert into t2 values(3),(4);
insert into t1 values(3),(4);
load data infile '../std_data_ln/rpl_loaddata.dat' into table t2;
Warnings:
Warning 1262 Row 1 was truncated; it contained more data than there were input columns
Warning 1262 Row 2 was truncated; it contained more data than there were input columns
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
Warnings:
Warning 1262 Row 1 was truncated; it contained more data than there were input columns
Warning 1262 Row 2 was truncated; it contained more data than there were input columns
rollback;
Warnings:
Warning 1196 Some non-transactional changed tables couldn't be rolled back
select count(*) from t1;
count(*)
4
select count(*) from t2;
count(*)
0
select count(*) from t1;
count(*)
4
select count(*) from t2;
count(*)
0
drop table t1,t2;
--source include/have_innodb.inc
let $engine_type= InnoDB;
--source include/loaddata_autocom.inc
--source include/have_ndb.inc
let $engine_type=ndbcluster;
--source include/loaddata_autocom.inc
# Test of a transaction mixing the two engines
-- source include/have_ndb.inc
-- source include/have_innodb.inc
-- source include/master-slave.inc
create table t1 (a int, unique(a)) engine=ndbcluster;
create table t2 (a int, unique(a)) engine=innodb;
begin;
insert into t1 values(1);
insert into t2 values(1);
rollback;
select count(*) from t1;
select count(*) from t2;
sync_slave_with_master;
select count(*) from t1;
select count(*) from t2;
connection master;
begin;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t2;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
rollback;
select count(*) from t1;
select count(*) from t2;
sync_slave_with_master;
select count(*) from t1;
select count(*) from t2;
connection master;
delete from t1;
delete from t2;
begin;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t2;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
rollback;
select count(*) from t1;
select count(*) from t2;
sync_slave_with_master;
select count(*) from t1;
select count(*) from t2;
connection master;
delete from t1;
delete from t2;
begin;
insert into t2 values(3),(4);
insert into t1 values(3),(4);
load data infile '../std_data_ln/rpl_loaddata.dat' into table t2;
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
rollback;
select count(*) from t1;
select count(*) from t2;
sync_slave_with_master;
select count(*) from t1;
select count(*) from t2;
connection master;
drop table t1,t2;
sync_slave_with_master;
......@@ -3526,7 +3526,14 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
if (lock_type != F_UNLCK)
{
DBUG_PRINT("info", ("lock_type != F_UNLCK"));
if (!thd->transaction.on)
if (thd->lex->sql_command == SQLCOM_LOAD)
{
m_transaction_on= FALSE;
/* Would be simpler if has_transactions() didn't always say "yes" */
thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
thd->no_trans_update= TRUE;
}
else if (!thd->transaction.on)
m_transaction_on= FALSE;
else
m_transaction_on= thd->variables.ndb_use_transactions;
......
......@@ -147,10 +147,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
MYF(0));
DBUG_RETURN(TRUE);
}
/*
This needs to be done before external_lock
*/
ha_enable_transaction(thd, FALSE);
if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(TRUE);
if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context,
......@@ -394,7 +390,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
table->next_number_field=0;
}
ha_enable_transaction(thd, TRUE);
if (file >= 0)
my_close(file,MYF(0));
free_blobs(table); /* if pack_blob was used */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment