diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index 37fdc135ea7..32eaedcde2e 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -615,7 +615,7 @@ convert_error_code_to_mysql( cached binlog for this transaction */ if (thd) { - ha_rollback(thd); + thd_mark_transaction_to_rollback(thd, TRUE); } return(HA_ERR_LOCK_DEADLOCK); @@ -625,8 +625,9 @@ convert_error_code_to_mysql( latest SQL statement in a lock wait timeout. Previously, we rolled back the whole transaction. */ - if (thd && row_rollback_on_timeout) { - ha_rollback(thd); + if (thd) { + thd_mark_transaction_to_rollback( + thd, (bool)row_rollback_on_timeout); } return(HA_ERR_LOCK_WAIT_TIMEOUT); @@ -671,7 +672,7 @@ convert_error_code_to_mysql( cached binlog for this transaction */ if (thd) { - ha_rollback(thd); + thd_mark_transaction_to_rollback(thd, TRUE); } return(HA_ERR_LOCK_TABLE_FULL); @@ -2005,12 +2006,11 @@ retry: /* We just mark the SQL statement ended and do not do a transaction commit */ - if (trx->auto_inc_lock) { - /* If we had reserved the auto-inc lock for some - table in this SQL statement we release it now */ + /* If we had reserved the auto-inc lock for some + table in this SQL statement we release it now */ + + row_unlock_table_autoinc_for_mysql(trx); - row_unlock_table_autoinc_for_mysql(trx); - } /* Store the current undo_no of the transaction so that we know where to roll back if we have to roll back the next SQL statement */ @@ -2064,13 +2064,11 @@ innobase_rollback( innobase_release_stat_resources(trx); - if (trx->auto_inc_lock) { - /* If we had reserved the auto-inc lock for some table (if - we come here to roll back the latest SQL statement) we - release it now before a possibly lengthy rollback */ + /* If we had reserved the auto-inc lock for some table (if + we come here to roll back the latest SQL statement) we + release it now before a possibly lengthy rollback */ - row_unlock_table_autoinc_for_mysql(trx); - } + row_unlock_table_autoinc_for_mysql(trx); if (all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { @@ -2104,13 +2102,11 @@ innobase_rollback_trx( innobase_release_stat_resources(trx); - if (trx->auto_inc_lock) { - /* If we had reserved the auto-inc lock for some table (if - we come here to roll back the latest SQL statement) we - release it now before a possibly lengthy rollback */ + /* If we had reserved the auto-inc lock for some table (if + we come here to roll back the latest SQL statement) we + release it now before a possibly lengthy rollback */ - row_unlock_table_autoinc_for_mysql(trx); - } + row_unlock_table_autoinc_for_mysql(trx); error = trx_rollback_for_mysql(trx); @@ -3650,7 +3646,7 @@ set_max_autoinc: err = innobase_set_max_autoinc(auto_inc); if (err != DB_SUCCESS) { - error = err; + error = (int) err; } } break; @@ -7423,7 +7419,7 @@ ha_innobase::innobase_read_and_init_auto_inc( if (auto_inc == 0) { dict_index_t* index; - ulint error = DB_SUCCESS; + ulint error; const char* autoinc_col_name; ut_a(!innodb_table->autoinc_inited); @@ -7502,12 +7498,10 @@ ha_innobase::innobase_get_auto_increment( trx = prebuilt->trx; dict_table_autoinc_unlock(prebuilt->table); - if (trx->auto_inc_lock) { - /* If we had reserved the AUTO-INC - lock in this SQL statement we release - it before retrying.*/ - row_unlock_table_autoinc_for_mysql(trx); - } + /* If we had reserved the AUTO-INC + lock in this SQL statement we release + it before retrying.*/ + row_unlock_table_autoinc_for_mysql(trx); /* Just to make sure */ ut_a(!trx->auto_inc_lock); @@ -7598,10 +7592,10 @@ ha_innobase::get_auto_increment( trx->n_autoinc_rows = 1; } - *first_value = autoinc; + set_if_bigger(*first_value, autoinc); /* Not in the middle of a mult-row INSERT. */ } else if (prebuilt->last_value == 0) { - *first_value = autoinc; + set_if_bigger(*first_value, autoinc); } *nb_reserved_values = trx->n_autoinc_rows; @@ -7935,12 +7929,10 @@ innobase_xa_prepare( /* We just mark the SQL statement ended and do not do a transaction prepare */ - if (trx->auto_inc_lock) { - /* If we had reserved the auto-inc lock for some - table in this SQL statement we release it now */ + /* If we had reserved the auto-inc lock for some + table in this SQL statement we release it now */ - row_unlock_table_autoinc_for_mysql(trx); - } + row_unlock_table_autoinc_for_mysql(trx); /* Store the current undo_no of the transaction so that we know where to roll back if we have to roll back the next @@ -8314,7 +8306,7 @@ static MYSQL_SYSVAR_STR(data_file_path, innobase_data_file_path, NULL, NULL, NULL); static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode, - PLUGIN_VAR_RQCMDARG, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "The AUTOINC lock modes supported by InnoDB:\n" " 0 => Old style AUTOINC locking (for backward compatibility)\n" " 1 => New style AUTOINC locking\n" diff --git a/handler/ha_innodb.h b/handler/ha_innodb.h index 44db981b867..908a5d4a799 100644 --- a/handler/ha_innodb.h +++ b/handler/ha_innodb.h @@ -253,6 +253,13 @@ int thd_non_transactional_update(const MYSQL_THD thd); @return Value to be used as index into the binlog_format_names array */ int thd_binlog_format(const MYSQL_THD thd); + +/** + Mark transaction to rollback and mark error as fatal to a sub-statement. + @param thd Thread handle + @param all TRUE <=> rollback main transaction. +*/ +void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all); } typedef struct trx_struct trx_t; diff --git a/mysql-test/innodb.result b/mysql-test/innodb.result index 263e14970dc..43babd2dc62 100644 --- a/mysql-test/innodb.result +++ b/mysql-test/innodb.result @@ -1087,39 +1087,6 @@ n d 1 30 2 20 drop table t1,t2; -CREATE TABLE `t1` ( -`a` int(11) NOT NULL auto_increment, -`b` int(11) default NULL, -PRIMARY KEY (`a`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; -CREATE TABLE `t2` ( -`a` int(11) NOT NULL auto_increment, -`b` int(11) default NULL, -PRIMARY KEY (`a`) -) ENGINE=INNODB DEFAULT CHARSET=latin1 ; -insert into t1 values (1,1),(2,2); -insert into t2 values (1,1),(4,4); -reset master; -UPDATE t2,t1 SET t2.a=t1.a+2; -ERROR 23000: Duplicate entry '3' for key 'PRIMARY' -select * from t2 /* must be (3,1), (4,4) */; -a b -1 1 -4 4 -show master status /* there must no UPDATE in binlog */; -File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 106 -delete from t1; -delete from t2; -insert into t1 values (1,2),(3,4),(4,4); -insert into t2 values (1,2),(3,4),(4,4); -reset master; -UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a; -ERROR 23000: Duplicate entry '4' for key 'PRIMARY' -show master status /* there must be no UPDATE query event */; -File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000001 106 -drop table t1, t2; create table t1 (a int, b int) engine=innodb; insert into t1 values(20,null); select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on @@ -1785,13 +1752,13 @@ Variable_name Value Innodb_page_size 16384 show status like "Innodb_rows_deleted"; Variable_name Value -Innodb_rows_deleted 72 +Innodb_rows_deleted 70 show status like "Innodb_rows_inserted"; Variable_name Value -Innodb_rows_inserted 1088 +Innodb_rows_inserted 1083 show status like "Innodb_rows_updated"; Variable_name Value -Innodb_rows_updated 888 +Innodb_rows_updated 886 show status like "Innodb_row_lock_waits"; Variable_name Value Innodb_row_lock_waits 0 diff --git a/mysql-test/innodb.test b/mysql-test/innodb.test index 246a7653146..594f2a94565 100644 --- a/mysql-test/innodb.test +++ b/mysql-test/innodb.test @@ -11,13 +11,7 @@ # # ####################################################################### --- source include/not_embedded.inc -- source include/have_innodb.inc --- source include/have_log_bin.inc - -# Disabling it temporarily for statement-based logging since some -# tests are not safe while binlog is on. --- source include/have_binlog_format_mixed_or_row.inc # # Small basic test with ignore @@ -762,45 +756,6 @@ select * from t1; select * from t2; drop table t1,t2; -# -# Bug#27716 multi-update did partially and has not binlogged -# - -CREATE TABLE `t1` ( - `a` int(11) NOT NULL auto_increment, - `b` int(11) default NULL, - PRIMARY KEY (`a`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 ; - -CREATE TABLE `t2` ( - `a` int(11) NOT NULL auto_increment, - `b` int(11) default NULL, - PRIMARY KEY (`a`) -) ENGINE=INNODB DEFAULT CHARSET=latin1 ; - -# A. testing multi_update::send_eof() execution branch -insert into t1 values (1,1),(2,2); -insert into t2 values (1,1),(4,4); -reset master; ---error ER_DUP_ENTRY -UPDATE t2,t1 SET t2.a=t1.a+2; -# check -select * from t2 /* must be (3,1), (4,4) */; -show master status /* there must no UPDATE in binlog */; - -# B. testing multi_update::send_error() execution branch -delete from t1; -delete from t2; -insert into t1 values (1,2),(3,4),(4,4); -insert into t2 values (1,2),(3,4),(4,4); -reset master; ---error ER_DUP_ENTRY -UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a; -show master status /* there must be no UPDATE query event */; - -# cleanup bug#27716 -drop table t1, t2; - # # Testing of IFNULL # @@ -1178,9 +1133,8 @@ drop table t2; # Test error handling -# Clean up filename -- embedded server reports whole path without .frm, -# regular server reports relative path with .frm (argh!) ---replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t2.frm t2 +# Embedded server doesn't chdir to data directory +--replace_result $MYSQLTEST_VARDIR . master-data/ '' --error ER_WRONG_FK_DEF create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; @@ -1373,9 +1327,8 @@ source include/varchar.inc; # Some errors/warnings on create # -# Clean up filename -- embedded server reports whole path without .frm, -# regular server reports relative path with .frm (argh!) ---replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t1.frm t1 +# Embedded server doesn't chdir to data directory +--replace_result $MYSQLTEST_VARDIR . master-data/ '' create table t1 (v varchar(65530), key(v)); drop table t1; create table t1 (v varchar(65536)); @@ -1649,6 +1602,7 @@ disconnect b; set foreign_key_checks=0; create table t2 (a int primary key, b int, foreign key (b) references t1(a)) engine = innodb; +# Embedded server doesn't chdir to data directory --replace_result $MYSQLTEST_VARDIR . master-data/ '' -- error 1005 create table t1(a char(10) primary key, b varchar(20)) engine = innodb; @@ -1660,6 +1614,7 @@ drop table t2; set foreign_key_checks=0; create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin1; +# Embedded server doesn't chdir to data directory --replace_result $MYSQLTEST_VARDIR . master-data/ '' -- error 1005 create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=utf8; @@ -1690,6 +1645,7 @@ drop table t2,t1; set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; +# Embedded server doesn't chdir to data directory --replace_result $MYSQLTEST_VARDIR . master-data/ '' -- error 1025 rename table t3 to t1; @@ -2315,7 +2271,10 @@ CREATE TABLE t2 (a INT, INDEX(a)) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); INSERT INTO t2 VALUES (1); ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL; ---replace_regex /'\.\/test\/#sql-[0-9a-f_]*'/'#sql-temporary'/ +# mysqltest first does replace_regex, then replace_result +--replace_regex /'[^']*test\/#sql-[0-9a-f_]*'/'#sql-temporary'/ +# Embedded server doesn't chdir to data directory +--replace_result $MYSQLTEST_VARDIR . master-data/ '' --error 1025 ALTER TABLE t2 MODIFY a INT NOT NULL; DELETE FROM t1;