summaryrefslogtreecommitdiff
path: root/innobase/lock
diff options
context:
space:
mode:
authorunknown <marko@hundin.mysql.fi>2004-11-30 17:34:37 +0200
committerunknown <marko@hundin.mysql.fi>2004-11-30 17:34:37 +0200
commitd6180d37be0fb11c5e1a5b9a090506e015934368 (patch)
tree0404a4610240b6bc7fb2939fc6f6ffe6494d7939 /innobase/lock
parent346dce93c2a63757540ed15e660dd07d41f7f20d (diff)
downloadmariadb-git-d6180d37be0fb11c5e1a5b9a090506e015934368.tar.gz
InnoDB: Allow ALTER TABLE to do intermediate COMMIT also when the table
contains auto_increment columns. (Bug #6633) innobase/include/lock0lock.h: Replaced lock_get_table() with lock_get_src_table() and lock_is_table_exclusive() innobase/lock/lock0lock.c: Replaced lock_get_table() with lock_get_src_table() and lock_is_table_exclusive() sql/ha_innodb.cc: ha_innobase::write_row(): Improve the ALTER TABLE optimization (do intermediate COMMIT also if table contains auto_increment columns)
Diffstat (limited to 'innobase/lock')
-rw-r--r--innobase/lock/lock0lock.c139
1 files changed, 111 insertions, 28 deletions
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index d9a10eb60c0..16c4ddfd96d 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -602,42 +602,125 @@ lock_get_wait(
}
/*************************************************************************
-Gets the table covered by an IX or IS table lock, if there are no
-other locks on the table. */
+Gets the source table of an ALTER TABLE transaction. The table must be
+covered by an IX or IS table lock. */
dict_table_t*
-lock_get_table(
-/*===========*/
- /* out: the table covered by the lock,
- or NULL if it is not an IX or IS table lock,
- or there are other locks on the table */
- lock_t* lock, /* in: lock */
- ulint* mode) /* out: lock mode of table */
+lock_get_src_table(
+/*===============*/
+ /* out: the source table of transaction,
+ if it is covered by an IX or IS table lock;
+ dest if there is no source table, and
+ NULL if the transaction is locking more than
+ two tables or an inconsistency is found */
+ trx_t* trx, /* in: transaction */
+ dict_table_t* dest, /* in: destination of ALTER TABLE */
+ ulint* mode) /* out: lock mode of the source table */
{
- dict_table_t* table;
- ulint lock_mode;
+ dict_table_t* src;
+ lock_t* lock;
- table = NULL;
+ src = NULL;
*mode = LOCK_NONE;
- if (lock_get_type(lock) != LOCK_TABLE) {
- return(table);
- }
-
- lock_mode = lock_get_mode(lock);
- switch (lock_mode) {
- case LOCK_IS:
- case LOCK_IX:
- *mode = lock_mode;
- table = lock->un_member.tab_lock.table;
- if (UT_LIST_GET_LEN(table->locks) != 1 ||
- UT_LIST_GET_FIRST(table->locks) != lock) {
- /* We only support the case when
- there is only one lock on this table. */
- table = NULL;
+ for (lock = UT_LIST_GET_FIRST(trx->trx_locks);
+ lock;
+ lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
+ lock_table_t* tab_lock;
+ ulint lock_mode;
+ if (!(lock_get_type(lock) & LOCK_TABLE)) {
+ /* We are only interested in table locks. */
+ continue;
+ }
+ tab_lock = &lock->un_member.tab_lock;
+ if (dest == tab_lock->table) {
+ /* We are not interested in the destination table. */
+ continue;
+ } else if (!src) {
+ /* This presumably is the source table. */
+ src = tab_lock->table;
+ if (UT_LIST_GET_LEN(src->locks) != 1 ||
+ UT_LIST_GET_FIRST(src->locks) != lock) {
+ /* We only support the case when
+ there is only one lock on this table. */
+ return(NULL);
+ }
+ } else if (src != tab_lock->table) {
+ /* The transaction is locking more than
+ two tables (src and dest): abort */
+ return(NULL);
+ }
+
+ /* Check that the source table is locked by
+ LOCK_IX or LOCK_IS. */
+ lock_mode = lock_get_mode(lock);
+ switch (lock_mode) {
+ case LOCK_IX:
+ case LOCK_IS:
+ if (*mode != LOCK_NONE && *mode != lock_mode) {
+ /* There are multiple locks on src. */
+ return(NULL);
+ }
+ *mode = lock_mode;
+ break;
}
}
- return(table);
+
+ if (!src) {
+ /* No source table lock found: flag the situation to caller */
+ src = dest;
+ }
+
+ return(src);
+}
+
+/*************************************************************************
+Determine if the given table is exclusively "owned" by the given
+transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
+on the table. */
+
+ibool
+lock_is_table_exclusive(
+/*====================*/
+ /* out: TRUE if table is only locked by trx,
+ with LOCK_IX, and possibly LOCK_AUTO_INC */
+ dict_table_t* table, /* in: table */
+ trx_t* trx) /* in: transaction */
+{
+ lock_t* lock;
+ bool ok = FALSE;
+
+ ut_ad(table && trx);
+
+ for (lock = UT_LIST_GET_FIRST(table->locks);
+ lock;
+ lock = UT_LIST_GET_NEXT(locks, &lock->un_member.tab_lock)) {
+ if (lock->trx != trx) {
+ /* A lock on the table is held
+ by some other transaction. */
+ return(FALSE);
+ }
+
+ if (!(lock_get_type(lock) & LOCK_TABLE)) {
+ /* We are interested in table locks only. */
+ continue;
+ }
+
+ switch (lock_get_mode(lock)) {
+ case LOCK_IX:
+ ok = TRUE;
+ break;
+ case LOCK_AUTO_INC:
+ /* It is allowed for trx to hold an
+ auto_increment lock. */
+ break;
+ default:
+ /* Other table locks than LOCK_IX are not allowed. */
+ return(FALSE);
+ }
+ }
+
+ return(ok);
}
/*************************************************************************