summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorJon Olav Hauglid <jon.hauglid@sun.com>2010-01-08 11:26:32 +0100
committerJon Olav Hauglid <jon.hauglid@sun.com>2010-01-08 11:26:32 +0100
commit0bce0c9041c5faf5a64855f21680f6898113d550 (patch)
tree498e792e2bf90d733b7698448ca454a4509fa060 /mysys
parent236539b47160a384901533fc41c6793bb5241e0b (diff)
downloadmariadb-git-0bce0c9041c5faf5a64855f21680f6898113d550.tar.gz
Fix for bug #48538 "Assertion in thr_lock() on LOAD DATA CONCURRENT
INFILE". Attempts to execute an INSERT statement for a MEMORY table which invoked a trigger or called a stored function which tried to perform LOW_PRIORITY update on the table being inserted into, resulted in debug servers aborting due to an assertion failure. On non-debug servers such INSERTs failed with "Can't update table t1 in stored function/trigger because it is already used by statement which invoked this stored function/trigger" as expected. The problem was that in the above scenario TL_WRITE_CONCURRENT_INSERT is converted to TL_WRITE inside the thr_lock() function since the MEMORY engine does not support concurrent inserts. This triggered an assertion which assumed that for the same table, one thread always requests locks with higher thr_lock_type value first. When TL_WRITE_CONCURRENT_INSERT is upgraded to TL_WRITE after the locks have been sorted, this is no longer true. In this case, TL_WRITE was requested after acquiring a TL_WRITE_LOW_PRIORITY lock on the table, triggering the assert. This fix solves the problem by adjusting this assert to take this scenario into account. An alternative approach to change handler::store_locks() methods for all engines which do not support concurrent inserts in such way that TL_WRITE_CONCURRENT_INSERT is upgraded to TL_WRITE there instead, was considered too intrusive. Commit on behalf of Dmitry Lenev.
Diffstat (limited to 'mysys')
-rw-r--r--mysys/thr_lock.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index a3f3e9ee080..a6bc128f32a 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -674,14 +674,23 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
write locks are of TL_WRITE_ALLOW_WRITE type.
Note that, since lock requests for the same table are sorted in
- such way that requests with higher thr_lock_type value come first,
- lock being requested usually has equal or "weaker" type than one
- which thread might have already acquired.
- The exceptions are situations when:
- - old lock type is TL_WRITE_ALLOW_READ and new lock type is
- TL_WRITE_ALLOW_WRITE
- - when old lock type is TL_WRITE_DELAYED
- But these should never happen within MySQL.
+ such way that requests with higher thr_lock_type value come first
+ (with one exception (*)), lock being requested usually (**) has
+ equal or "weaker" type than one which thread might have already
+ acquired.
+ *) The only exception to this rule is case when type of old lock
+ is TL_WRITE_LOW_PRIORITY and type of new lock is changed inside
+ of thr_lock() from TL_WRITE_CONCURRENT_INSERT to TL_WRITE since
+ engine turns out to be not supporting concurrent inserts.
+ Note that since TL_WRITE has the same compatibility rules as
+ TL_WRITE_LOW_PRIORITY (their only difference is priority),
+ it is OK to grant new lock without additional checks in such
+ situation.
+ **) The exceptions are situations when:
+ - old lock type is TL_WRITE_ALLOW_READ and new lock type is
+ TL_WRITE_ALLOW_WRITE
+ - when old lock type is TL_WRITE_DELAYED
+ But these should never happen within MySQL.
Therefore it is OK to allow acquiring write lock on the table if
this thread already holds some write lock on it.
@@ -690,7 +699,9 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
different types of write lock on the same table).
*/
DBUG_ASSERT(! has_old_lock(lock->write.data, data->owner) ||
- (lock_type <= lock->write.data->type &&
+ ((lock_type <= lock->write.data->type ||
+ (lock_type == TL_WRITE &&
+ lock->write.data->type == TL_WRITE_LOW_PRIORITY)) &&
! ((lock_type < TL_WRITE_ALLOW_READ &&
lock->write.data->type == TL_WRITE_ALLOW_READ) ||
lock->write.data->type == TL_WRITE_DELAYED)));