summaryrefslogtreecommitdiff
path: root/sql/ha_innodb.cc
diff options
context:
space:
mode:
authorunknown <marko@hundin.mysql.fi>2004-11-27 00:45:01 +0200
committerunknown <marko@hundin.mysql.fi>2004-11-27 00:45:01 +0200
commit346dce93c2a63757540ed15e660dd07d41f7f20d (patch)
tree8ca2dd048763662b02f24eeeac0e7571a2ffe83d /sql/ha_innodb.cc
parentb0d586e5648e78981c63e68059c6c836a228a082 (diff)
downloadmariadb-git-346dce93c2a63757540ed15e660dd07d41f7f20d.tar.gz
InnoDB: Make intermediate COMMITs in ALTER TABLE more robust (Bug #6633)
innobase/include/lock0lock.h: Replaced lock_get_ix_table() with lock_get_table(). innobase/lock/lock0lock.c: Replaced lock_get_ix_table() with lock_get_table(). innobase/include/row0mysql.h: row_lock_table_for_mysql(): Added parameter mode. innobase/row/row0mysql.c: row_lock_table_for_mysql(): Added parameter mode. sql/ha_innodb.cc: ha_innobase::write_row(): Make ALTER TABLE commits more robust: account for conversions from non-InnoDB format, do not attempt to commit if there are other than a single IX or IS lock on the source table, and the source table is in InnoDB format. This prohibits intermediate commits for OPTIMIZE TABLE if the table contains an auto_increment field.
Diffstat (limited to 'sql/ha_innodb.cc')
-rw-r--r--sql/ha_innodb.cc60
1 files changed, 48 insertions, 12 deletions
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 2515b4956d0..2aaf69bd208 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -2324,20 +2324,55 @@ ha_innobase::write_row(
position in the source table need not be adjusted after the
intermediate COMMIT, since writes by other transactions are
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
- ut_a(prebuilt->trx->mysql_n_tables_locked == 2);
- ut_a(UT_LIST_GET_LEN(prebuilt->trx->trx_locks) >= 2);
- dict_table_t* table = lock_get_ix_table(
- UT_LIST_GET_FIRST(prebuilt->trx->trx_locks));
+
+ dict_table_t* table;
+ ibool mode;
+
num_write_row = 0;
+
/* Commit the transaction. This will release the table
locks, so they have to be acquired again. */
- innobase_commit(user_thd, prebuilt->trx);
- /* Note that this transaction is still active. */
- user_thd->transaction.all.innodb_active_trans = 1;
- /* Re-acquire the IX table lock on the source table. */
- row_lock_table_for_mysql(prebuilt, table);
- /* We will need an IX lock on the destination table. */
- prebuilt->sql_stat_start = TRUE;
+ switch (prebuilt->trx->mysql_n_tables_locked) {
+ case 1:
+ /* Altering to InnoDB format */
+ innobase_commit(user_thd, prebuilt->trx);
+ /* Note that this transaction is still active. */
+ user_thd->transaction.all.innodb_active_trans = 1;
+ /* We will need an IX lock on the destination table. */
+ prebuilt->sql_stat_start = TRUE;
+ break;
+ case 2:
+ /* Altering an InnoDB table */
+ ut_a(UT_LIST_GET_LEN(prebuilt->trx->trx_locks) >= 2);
+ table = lock_get_table(
+ UT_LIST_GET_FIRST(prebuilt->trx->trx_locks),
+ &mode);
+ if (!table) {
+ goto no_commit;
+ }
+
+ /* Commit the transaction. This will release the table
+ locks, so they have to be acquired again. */
+ innobase_commit(user_thd, prebuilt->trx);
+ /* Note that this transaction is still active. */
+ user_thd->transaction.all.innodb_active_trans = 1;
+ /* Re-acquire the table lock on the source table. */
+ row_lock_table_for_mysql(prebuilt, table, mode);
+ /* We will need an IX lock on the destination table. */
+ prebuilt->sql_stat_start = TRUE;
+ break;
+ default:
+ no_commit:
+ /* Unknown situation: do nothing (no commit) */
+ /*
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB error: ALTER TABLE is holding lock"
+ " on %lu tables!\n",
+ prebuilt->trx->mysql_n_tables_locked);
+ */
+ break;
+ }
}
num_write_row++;
@@ -5015,7 +5050,8 @@ ha_innobase::external_lock(
if (thd->in_lock_tables &&
thd->variables.innodb_table_locks) {
ulint error;
- error = row_lock_table_for_mysql(prebuilt, 0);
+ error = row_lock_table_for_mysql(prebuilt,
+ NULL, LOCK_TABLE_EXP);
if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(