diff options
author | unknown <marko@hundin.mysql.fi> | 2004-11-27 00:45:01 +0200 |
---|---|---|
committer | unknown <marko@hundin.mysql.fi> | 2004-11-27 00:45:01 +0200 |
commit | 346dce93c2a63757540ed15e660dd07d41f7f20d (patch) | |
tree | 8ca2dd048763662b02f24eeeac0e7571a2ffe83d /sql/ha_innodb.cc | |
parent | b0d586e5648e78981c63e68059c6c836a228a082 (diff) | |
download | mariadb-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.cc | 60 |
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( |