Purpose
Creates and releases table locks.
Synopsis
virtual THR_LOCK_DATA **
store_lock
( |
thd, |
|
|
to, |
|
|
lock_type) ; |
|
THD * |
thd
; |
THR_LOCK_DATA ** |
to
; |
enum
thr_lock_type |
lock_type
; |
Description
This is the store_lock
method.
The idea with handler::store_lock() is the following:
The statement decided which locks we should need for the table
for updates/deletes/inserts we get WRITE locks, for SELECT... we
get read locks.
Before adding the lock into the table lock handler
mysqld calls store lock with the requested
locks. Store lock can modify the lock level, e.g. change
blocking write lock to non-blocking, ignore the lock (if we
don't want to use MySQL table locks at all) or add locks for
many tables (like we do when we are using a MERGE handler).
Berkeley DB for example, downgrades blocking table TL_WRITE
locks to non-blocking TL_WRITE_ALLOW_WRITE locks (which signals
that we are doing WRITES, but we are still allowing other
readers and writers).
When releasing locks, store_lock() are also called. In this case
one usually doesn't have to do anything.
If the argument of store_lock is TL_IGNORE, it means that MySQL
requests the handler to store the same lock level as the last
time.
Called from lock.cc by get_lock_data().
Parameters
Return Values
There are no return values.
Usage
The following example is from the ARCHIVE
storage engine:
/*
Below is an example of how to setup row level locking.
*/
THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
if (lock_type == TL_WRITE_DELAYED)
delayed_insert= TRUE;
else
delayed_insert= FALSE;
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
{
/*
Here is where we get into the guts of a row level lock.
If TL_UNLOCK is set
If we are not doing a LOCK TABLE or DISCARD/IMPORT
TABLESPACE, then allow multiple writers
*/
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
lock_type <= TL_WRITE) && !thd->in_lock_tables
&& !thd->tablespace_op)
lock_type = TL_WRITE_ALLOW_WRITE;
/*
In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
to t2. Convert the lock to a normal read lock to allow
concurrent inserts to t2.
*/
if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables)
lock_type = TL_READ;
lock.type=lock_type;
}
*to++= &lock;
return to;
}
The following is the minimal implementation, for a storage
engine that does not need to downgrade locks:
THR_LOCK_DATA **ha_tina::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
/* Note that if the lock type is TL_IGNORE we don't update lock.type,
preserving the previous lock level */
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
lock.type=lock_type;
/* the heart of the store_lock() method and it's main purpose -
storing the (possibly changed) lock level into the provided
memory */
*to++= &lock;
return to;
}
See also ha_berkeley::store_lock() and
ha_myisammrg::store_lock() for more complex implementation