diff options
author | Konstantin Osipov <kostja@sun.com> | 2009-12-02 23:47:23 +0300 |
---|---|---|
committer | Konstantin Osipov <kostja@sun.com> | 2009-12-02 23:47:23 +0300 |
commit | 77cbfd85ee3f6969dcbe528a2f97ec12c9cf99dc (patch) | |
tree | ce951be1a1212aaa9bd9c5db2ef73257ce2f1f29 /mysys/thr_lock.c | |
parent | 124cda8a0a783180b280935fd4b62a2b7d6dc6c4 (diff) | |
download | mariadb-git-77cbfd85ee3f6969dcbe528a2f97ec12c9cf99dc.tar.gz |
Backport of:
----------------------------------------------------------
revno: 2630.4.35
committer: Konstantin Osipov <konstantin@mysql.com>
branch nick: mysql-6.0-3726
timestamp: Wed 2008-06-25 16:44:00 +0400
message:
Fix a MyISAM-specific bug in the new implementation of
LOCK TABLES (WL#3726).
If more than one instance of a MyISAM table are open in the
same connection, all of them must share the same status_param.
Otherwise, unlock of a table may lead to lost records.
See also comments in thr_lock.c.
include/thr_lock.h:
Declare thr_lock_merge_status().
mysql-test/r/lock.result:
Update test results (WL#3726).
mysql-test/t/lock.test:
Add a test case for the situation when the same table is locked
twice by LOCK TABLES, and only one instance is updated.
mysys/thr_lock.c:
Move the code that makes sure all status_params of the same
table are shared into a separate function.
sql/lock.cc:
Make sure that status_param is shared when a table is reopened.
Diffstat (limited to 'mysys/thr_lock.c')
-rw-r--r-- | mysys/thr_lock.c | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 1d724de641c..1288dc36a90 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -1026,12 +1026,43 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner) (long) pos[0]->lock, pos[0]->type); fflush(stdout); #endif } - /* - Ensure that all get_locks() have the same status - If we lock the same table multiple times, we must use the same - status_param! - */ + thr_lock_merge_status(data, count); + DBUG_RETURN(THR_LOCK_SUCCESS); +} + + +/** + Ensure that all locks for a given table have the same + status_param. + + This is a MyISAM and possibly Maria specific crutch. MyISAM + engine stores data file length, record count and other table + properties in status_param member of handler. When a table is + locked, connection-local copy is made from a global copy + (myisam_share) by mi_get_status(). When a table is unlocked, + the changed status is transferred back to the global share by + mi_update_status(). + + One thing MyISAM doesn't do is to ensure that when the same + table is opened twice in a connection all instances share the + same status_param. This is necessary, however: for one, to keep + all instances of a connection "on the same page" with regard to + the current state of the table. For other, unless this is done, + myisam_share will always get updated from the last unlocked + instance (in mi_update_status()), and when this instance was not + the one that was used to update data, records may be lost. + + For each table, this function looks up the last lock_data in the + list of acquired locks, and makes sure that all other instances + share status_param with it. +*/ + +void +thr_lock_merge_status(THR_LOCK_DATA **data, uint count) +{ #if !defined(DONT_USE_RW_LOCKS) + THR_LOCK_DATA **pos= data; + THR_LOCK_DATA **end= data + count; if (count > 1) { THR_LOCK_DATA *last_lock= end[-1]; @@ -1073,7 +1104,6 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner) } while (pos != data); } #endif - DBUG_RETURN(THR_LOCK_SUCCESS); } /* free all locks */ |