summaryrefslogtreecommitdiff
path: root/innobase/lock
diff options
context:
space:
mode:
authorunknown <marko@hundin.mysql.fi>2004-04-29 16:42:33 +0300
committerunknown <marko@hundin.mysql.fi>2004-04-29 16:42:33 +0300
commit3594adb165279605c0cf6519f5c3a5b5378f3d91 (patch)
tree5013e7c0279115014b75320a87795fe461ac1285 /innobase/lock
parentb7468a97a2fd4a5500edbbf9884d548f78cbf57c (diff)
downloadmariadb-git-3594adb165279605c0cf6519f5c3a5b5378f3d91.tar.gz
InnoDB: implement LOCK TABLE (Bug #3299)
innobase/include/lock0lock.h: Add lock_table_unlock() and lock_release_tables_off_kernel() Add LOCK_TABLE_EXP innobase/include/row0mysql.h: Add row_unlock_table_for_mysql() and row_lock_table_for_mysql() innobase/include/trx0trx.h: Add n_tables_locked innobase/lock/lock0lock.c: Add LOCK_TABLE_EXP for explicit LOCK TABLE commands Add lock_table_unlock() Add lock_release_tables_off_kernel() innobase/row/row0mysql.c: Add row_unlock_table_for_mysql() and row_lock_table_for_mysql() innobase/trx/trx0trx.c: Add n_tables_locked mysql-test/r/innodb.result: Updated handling of auto_inc columns sql/ha_innodb.cc: Call row_lock_table_for_mysql() and row_unlock_table_for_mysql()
Diffstat (limited to 'innobase/lock')
-rw-r--r--innobase/lock/lock0lock.c130
1 files changed, 118 insertions, 12 deletions
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index e141e30ae97..6534387c22c 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -2001,7 +2001,11 @@ lock_grant(
release it at the end of the SQL statement */
lock->trx->auto_inc_lock = lock;
- }
+ } else if (lock_get_type(lock) == LOCK_TABLE_EXP) {
+ ut_ad(lock_get_mode(lock) == LOCK_S
+ || lock_get_mode(lock) == LOCK_X);
+ lock->trx->n_tables_locked++;
+ }
#ifdef UNIV_DEBUG
if (lock_print_waits) {
@@ -2939,7 +2943,7 @@ retry:
}
if (ret == LOCK_VICTIM_IS_START) {
- if (lock_get_type(lock) == LOCK_TABLE) {
+ if (lock_get_type(lock) & LOCK_TABLE) {
table = lock->un_member.tab_lock.table;
index = NULL;
} else {
@@ -3015,7 +3019,7 @@ lock_deadlock_recursive(
/* Look at the locks ahead of wait_lock in the lock queue */
for (;;) {
- if (lock_get_type(lock) == LOCK_TABLE) {
+ if (lock_get_type(lock) & LOCK_TABLE) {
lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
} else {
@@ -3347,7 +3351,9 @@ lock_table(
/* out: DB_SUCCESS, DB_LOCK_WAIT,
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
- does nothing */
+ does nothing;
+ if LOCK_TABLE_EXP bits are set,
+ creates an explicit table lock */
dict_table_t* table, /* in: database table in dictionary cache */
ulint mode, /* in: lock mode */
que_thr_t* thr) /* in: query thread */
@@ -3362,6 +3368,8 @@ lock_table(
return(DB_SUCCESS);
}
+ ut_ad(flags == 0 || flags == LOCK_TABLE_EXP);
+
trx = thr_get_trx(thr);
lock_mutex_enter_kernel();
@@ -3390,7 +3398,12 @@ lock_table(
return(err);
}
- lock_table_create(table, mode, trx);
+ lock_table_create(table, mode | flags, trx);
+
+ if (flags) {
+ ut_ad(mode == LOCK_S || mode == LOCK_X);
+ trx->n_tables_locked++;
+ }
lock_mutex_exit_kernel();
@@ -3471,7 +3484,8 @@ lock_table_dequeue(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- ut_ad(lock_get_type(in_lock) == LOCK_TABLE);
+ ut_ad(lock_get_type(in_lock) == LOCK_TABLE ||
+ lock_get_type(in_lock) == LOCK_TABLE_EXP);
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
@@ -3496,6 +3510,22 @@ lock_table_dequeue(
/*=========================== LOCK RELEASE ==============================*/
/*************************************************************************
+Releases a table lock.
+Releases possible other transactions waiting for this lock. */
+
+void
+lock_table_unlock(
+/*==============*/
+ lock_t* lock) /* in: lock */
+{
+ mutex_enter(&kernel_mutex);
+
+ lock_table_dequeue(lock);
+
+ mutex_exit(&kernel_mutex);
+}
+
+/*************************************************************************
Releases an auto-inc lock a transaction possibly has on a table.
Releases possible other transactions waiting for this lock. */
@@ -3542,7 +3572,7 @@ lock_release_off_kernel(
lock_rec_dequeue_from_page(lock);
} else {
- ut_ad(lock_get_type(lock) == LOCK_TABLE);
+ ut_ad(lock_get_type(lock) & LOCK_TABLE);
if (lock_get_mode(lock) != LOCK_IS
&& (trx->insert_undo || trx->update_undo)) {
@@ -3558,6 +3588,11 @@ lock_release_off_kernel(
}
lock_table_dequeue(lock);
+ if (lock_get_type(lock) == LOCK_TABLE_EXP) {
+ ut_ad(lock_get_mode(lock) == LOCK_S
+ || lock_get_mode(lock) == LOCK_X);
+ trx->n_tables_locked--;
+ }
}
if (count == LOCK_RELEASE_KERNEL_INTERVAL) {
@@ -3577,6 +3612,73 @@ lock_release_off_kernel(
mem_heap_empty(trx->lock_heap);
ut_a(trx->auto_inc_lock == NULL);
+ ut_a(trx->n_tables_locked == 0);
+}
+
+/*************************************************************************
+Releases table locks, and releases possible other transactions waiting
+because of these locks. */
+
+void
+lock_release_tables_off_kernel(
+/*===========================*/
+ trx_t* trx) /* in: transaction */
+{
+ dict_table_t* table;
+ ulint count;
+ lock_t* lock;
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
+
+ lock = UT_LIST_GET_LAST(trx->trx_locks);
+
+ count = 0;
+
+ while (lock != NULL) {
+
+ count++;
+
+ if (lock_get_type(lock) == LOCK_TABLE_EXP) {
+ ut_ad(lock_get_mode(lock) == LOCK_S
+ || lock_get_mode(lock) == LOCK_X);
+ if (trx->insert_undo || trx->update_undo) {
+
+ /* The trx may have modified the table.
+ We block the use of the MySQL query
+ cache for all currently active
+ transactions. */
+
+ table = lock->un_member.tab_lock.table;
+
+ table->query_cache_inv_trx_id =
+ trx_sys->max_trx_id;
+ }
+
+ lock_table_dequeue(lock);
+ trx->n_tables_locked--;
+ lock = UT_LIST_GET_LAST(trx->trx_locks);
+ continue;
+ }
+
+ if (count == LOCK_RELEASE_KERNEL_INTERVAL) {
+ /* Release the kernel mutex for a while, so that we
+ do not monopolize it */
+
+ lock_mutex_exit_kernel();
+
+ lock_mutex_enter_kernel();
+
+ count = 0;
+ }
+
+ lock = UT_LIST_GET_PREV(trx_locks, lock);
+ }
+
+ mem_heap_empty(trx->lock_heap);
+
+ ut_a(trx->n_tables_locked == 0);
}
/*************************************************************************
@@ -3596,7 +3698,7 @@ lock_cancel_waiting_and_release(
lock_rec_dequeue_from_page(lock);
} else {
- ut_ad(lock_get_type(lock) == LOCK_TABLE);
+ ut_ad(lock_get_type(lock) & LOCK_TABLE);
lock_table_dequeue(lock);
}
@@ -3637,7 +3739,7 @@ lock_reset_all_on_table_for_trx(
ut_a(!lock_get_wait(lock));
lock_rec_discard(lock);
- } else if (lock_get_type(lock) == LOCK_TABLE
+ } else if (lock_get_type(lock) & LOCK_TABLE
&& lock->un_member.tab_lock.table == table) {
ut_a(!lock_get_wait(lock));
@@ -3689,8 +3791,12 @@ lock_table_print(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- ut_a(lock_get_type(lock) == LOCK_TABLE);
+ ut_a(lock_get_type(lock) == LOCK_TABLE ||
+ lock_get_type(lock) == LOCK_TABLE_EXP);
+ if (lock_get_type(lock) == LOCK_TABLE_EXP) {
+ fputs("EXPLICIT ", file);
+ }
fputs("TABLE LOCK table ", file);
ut_print_name(file, lock->un_member.tab_lock.table->name);
fprintf(file, " trx id %lu %lu",
@@ -4009,7 +4115,7 @@ loop:
lock_rec_print(file, lock);
} else {
- ut_ad(lock_get_type(lock) == LOCK_TABLE);
+ ut_ad(lock_get_type(lock) & LOCK_TABLE);
lock_table_print(file, lock);
}
@@ -4290,7 +4396,7 @@ lock_validate(void)
lock = UT_LIST_GET_FIRST(trx->trx_locks);
while (lock) {
- if (lock_get_type(lock) == LOCK_TABLE) {
+ if (lock_get_type(lock) & LOCK_TABLE) {
lock_table_queue_validate(
lock->un_member.tab_lock.table);