1
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
20
Locking functions for mysql.
22
Because of the new concurrent inserts, we must first get external locks
23
before getting internal locks. If we do it in the other order, the status
24
information is not up to date when called from the lock handler.
26
GENERAL DESCRIPTION OF LOCKING
28
When not using LOCK TABLES:
30
- For each SQL statement mysql_lock_tables() is called for all involved
32
- mysql_lock_tables() will call
33
table_handler->external_lock(thd,locktype) for each table.
34
This is followed by a call to thr_multi_lock() for all tables.
36
- When statement is done, we call mysql_unlock_tables().
37
This will call thr_multi_unlock() followed by
38
table_handler->external_lock(thd, F_UNLCK) for each table.
40
- Note that mysql_unlock_tables() may be called several times as
41
MySQL in some cases can free some tables earlier than others.
43
- The above is true both for normal and temporary tables.
45
- Temporary non transactional tables are never passed to thr_multi_lock()
46
and we never call external_lock(thd, F_UNLOCK) on these.
48
When using LOCK TABLES:
50
- LOCK TABLE will call mysql_lock_tables() for all tables.
51
mysql_lock_tables() will call
52
table_handler->external_lock(thd,locktype) for each table.
53
This is followed by a call to thr_multi_lock() for all tables.
55
- For each statement, we will call table_handler->start_stmt(THD)
56
to inform the table handler that we are using the table.
58
The tables used can only be tables used in LOCK TABLES or a
61
- When statement is done, we will call ha_commit_stmt(thd);
63
- When calling UNLOCK TABLES we call mysql_unlock_tables() for all
64
tables used in LOCK TABLES
66
If table_handler->external_lock(thd, locktype) fails, we call
67
table_handler->external_lock(thd, F_UNLCK) for each table that was locked,
68
excluding one that caused failure. That means handler must cleanup itself
69
in case external_lock() fails.
72
Change to use my_malloc() ONLY when using LOCK TABLES command or when
73
we are forced to use mysql_lock_merge.
76
#include "mysql_priv.h"
81
@defgroup Locking Locking
85
extern HASH open_cache;
87
/* flags for get_lock_data */
88
#define GET_LOCK_UNLOCK 1
89
#define GET_LOCK_STORE_LOCKS 2
91
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count,
92
uint flags, TABLE **write_locked);
93
static void reset_lock_data(MYSQL_LOCK *sql_lock);
94
static int lock_external(THD *thd, TABLE **table,uint count);
95
static int unlock_external(THD *thd, TABLE **table,uint count);
96
static void print_lock_error(int error, const char *);
103
thd The current thread.
104
tables An array of pointers to the tables to lock.
105
count The number of tables to lock.
107
MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK Ignore a global read lock
108
MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY Ignore SET GLOBAL READ_ONLY
109
MYSQL_LOCK_IGNORE_FLUSH Ignore a flush tables.
110
MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN Instead of reopening altered
111
or dropped tables by itself,
112
mysql_lock_tables() should
113
notify upper level and rely
114
on caller doing this.
115
need_reopen Out parameter, TRUE if some tables were altered
116
or deleted and should be reopened by caller.
119
A lock structure pointer on success.
120
NULL on error or if some tables should be reopen.
123
/* Map the return value of thr_lock to an error from errmsg.txt */
124
static int thr_lock_errno_to_mysql[]=
125
{ 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
128
Perform semantic checks for mysql_lock_tables.
129
@param thd The current thread
130
@param tables The tables to lock
131
@param count The number of tables to lock
132
@param flags Lock flags
133
@return 0 if all the check passed, non zero if a check failed.
135
int mysql_lock_tables_check(THD *thd, TABLE **tables, uint count, uint flags)
137
bool log_table_write_query;
141
DBUG_ENTER("mysql_lock_tables_check");
144
log_table_write_query= (is_log_table_write_query(thd->lex->sql_command)
145
|| ((flags & MYSQL_LOCK_PERF_SCHEMA) != 0));
147
for (i=0 ; i<count; i++)
151
/* Protect against 'fake' partially initialized TABLE_SHARE */
152
DBUG_ASSERT(t->s->table_category != TABLE_UNKNOWN_CATEGORY);
155
Table I/O to performance schema tables is performed
156
only internally by the server implementation.
157
When a user is requesting a lock, the following
158
constraints are enforced:
160
if (t->s->require_write_privileges() &&
161
! log_table_write_query)
164
A user should not be able to prevent writes,
165
or hold any type of lock in a session,
166
since this would be a DOS attack.
168
if ((t->reginfo.lock_type >= TL_READ_NO_INSERT)
169
|| (thd->lex->sql_command == SQLCOM_LOCK_TABLES))
171
my_error(ER_CANT_LOCK_LOG_TABLE, MYF(0));
176
if ((t->s->table_category == TABLE_CATEGORY_SYSTEM) &&
177
(t->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE))
184
Locking of system tables is restricted:
185
locking a mix of system and non-system tables in the same lock
186
is prohibited, to prevent contention.
188
if ((system_count > 0) && (system_count < count))
190
my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0));
197
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
198
uint flags, bool *need_reopen)
200
MYSQL_LOCK *sql_lock;
201
TABLE *write_lock_used;
204
DBUG_ENTER("mysql_lock_tables");
208
if (mysql_lock_tables_check(thd, tables, count, flags))
213
if (! (sql_lock= get_lock_data(thd, tables, count, GET_LOCK_STORE_LOCKS,
217
if (global_read_lock && write_lock_used &&
218
! (flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK))
221
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
222
Wait until the lock is gone
224
if (wait_if_global_read_lock(thd, 1, 1))
226
/* Clear the lock type of all lock data to avoid reusage. */
227
reset_lock_data(sql_lock);
228
my_free((uchar*) sql_lock,MYF(0));
232
if (thd->version != refresh_version)
234
/* Clear the lock type of all lock data to avoid reusage. */
235
reset_lock_data(sql_lock);
236
my_free((uchar*) sql_lock,MYF(0));
241
if (!(flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY) &&
244
!(thd->security_ctx->master_access & SUPER_ACL) &&
248
Someone has issued SET GLOBAL READ_ONLY=1 and we want a write lock.
249
We do not wait for READ_ONLY=0, and fail.
251
reset_lock_data(sql_lock);
252
my_free((uchar*) sql_lock, MYF(0));
254
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
258
thd_proc_info(thd, "System lock");
259
DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info));
260
if (sql_lock->table_count && lock_external(thd, sql_lock->table,
261
sql_lock->table_count))
263
/* Clear the lock type of all lock data to avoid reusage. */
264
reset_lock_data(sql_lock);
265
my_free((uchar*) sql_lock,MYF(0));
269
thd_proc_info(thd, "Table lock");
270
DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info));
272
/* Copy the lock data array. thr_multi_lock() reorders its contens. */
273
memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
274
sql_lock->lock_count * sizeof(*sql_lock->locks));
275
/* Lock on the copied half of the lock data array. */
276
rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks +
277
sql_lock->lock_count,
278
sql_lock->lock_count,
280
if (rc > 1) /* a timeout or a deadlock */
282
if (sql_lock->table_count)
283
VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count));
284
my_error(rc, MYF(0));
285
my_free((uchar*) sql_lock,MYF(0));
289
else if (rc == 1) /* aborted */
292
reset_lock_data is required here. If thr_multi_lock fails it
293
resets lock type for tables, which were locked before (and
294
including) one that caused error. Lock type for other tables
297
reset_lock_data(sql_lock);
298
thd->some_tables_deleted=1; // Try again
299
sql_lock->lock_count= 0; // Locks are already freed
301
else if (!thd->some_tables_deleted || (flags & MYSQL_LOCK_IGNORE_FLUSH))
304
Thread was killed or lock aborted. Let upper level close all
305
used tables and retry or give error.
310
else if (!thd->open_tables)
312
// Only using temporary tables, no need to unlock
313
thd->some_tables_deleted=0;
317
thd_proc_info(thd, 0);
319
/* some table was altered or deleted. reopen tables marked deleted */
320
mysql_unlock_tables(thd,sql_lock);
324
if (flags & MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN)
329
if (wait_for_tables(thd))
330
break; // Couldn't open tables
332
thd_proc_info(thd, 0);
335
thd->send_kill_message();
338
mysql_unlock_tables(thd,sql_lock);
343
thd->set_time_after_lock();
344
DBUG_RETURN (sql_lock);
348
static int lock_external(THD *thd, TABLE **tables, uint count)
352
DBUG_ENTER("lock_external");
354
DBUG_PRINT("info", ("count %d", count));
355
for (i=1 ; i <= count ; i++, tables++)
357
DBUG_ASSERT((*tables)->reginfo.lock_type >= TL_READ);
358
lock_type=F_WRLCK; /* Lock exclusive */
359
if ((*tables)->db_stat & HA_READ_ONLY ||
360
((*tables)->reginfo.lock_type >= TL_READ &&
361
(*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
364
if ((error=(*tables)->file->ha_external_lock(thd,lock_type)))
366
print_lock_error(error, (*tables)->file->table_type());
370
(*tables)->file->ha_external_lock(thd, F_UNLCK);
371
(*tables)->current_lock=F_UNLCK;
377
(*tables)->db_stat &= ~ HA_BLOCK_LOCK;
378
(*tables)->current_lock= lock_type;
385
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock)
387
DBUG_ENTER("mysql_unlock_tables");
388
if (sql_lock->lock_count)
389
thr_multi_unlock(sql_lock->locks,sql_lock->lock_count);
390
if (sql_lock->table_count)
391
VOID(unlock_external(thd,sql_lock->table,sql_lock->table_count));
392
my_free((uchar*) sql_lock,MYF(0));
397
Unlock some of the tables locked by mysql_lock_tables.
399
This will work even if get_lock_data fails (next unlock will free all)
402
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count)
404
MYSQL_LOCK *sql_lock;
405
TABLE *write_lock_used;
406
if ((sql_lock= get_lock_data(thd, table, count, GET_LOCK_UNLOCK,
408
mysql_unlock_tables(thd, sql_lock);
413
unlock all tables locked for read.
416
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock)
419
DBUG_ENTER("mysql_unlock_read_tables");
421
/* Move all write locks first */
422
THR_LOCK_DATA **lock=sql_lock->locks;
423
for (i=found=0 ; i < sql_lock->lock_count ; i++)
425
if (sql_lock->locks[i]->type >= TL_WRITE_ALLOW_READ)
427
swap_variables(THR_LOCK_DATA *, *lock, sql_lock->locks[i]);
432
/* unlock the read locked tables */
435
thr_multi_unlock(lock,i-found);
436
sql_lock->lock_count= found;
439
/* Then do the same for the external locks */
440
/* Move all write locked tables first */
441
TABLE **table=sql_lock->table;
442
for (i=found=0 ; i < sql_lock->table_count ; i++)
444
DBUG_ASSERT(sql_lock->table[i]->lock_position == i);
445
if ((uint) sql_lock->table[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ)
447
swap_variables(TABLE *, *table, sql_lock->table[i]);
452
/* Unlock all read locked tables */
455
VOID(unlock_external(thd,table,i-found));
456
sql_lock->table_count=found;
458
/* Fix the lock positions in TABLE */
459
table= sql_lock->table;
461
for (i= 0; i < sql_lock->table_count; i++)
464
tbl->lock_position= (uint) (table - sql_lock->table);
465
tbl->lock_data_start= found;
466
found+= tbl->lock_count;
474
Try to find the table in the list of locked tables.
475
In case of success, unlock the table and remove it from this list.
477
@note This function has a legacy side effect: the table is
478
unlocked even if it is not found in the locked list.
479
It's not clear if this side effect is intentional or still
480
desirable. It might lead to unmatched calls to
481
unlock_external(). Moreover, a discrepancy can be left
482
unnoticed by the storage engine, because in
483
unlock_external() we call handler::external_lock(F_UNLCK) only
484
if table->current_lock is not F_UNLCK.
486
@param thd thread context
487
@param locked list of locked tables
488
@param table the table to unlock
489
@param always_unlock specify explicitly if the legacy side
493
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table,
496
if (always_unlock == TRUE)
497
mysql_unlock_some_tables(thd, &table, /* table count */ 1);
501
for (i=0; i < locked->table_count; i++)
503
if (locked->table[i] == table)
505
uint j, removed_locks, old_tables;
509
DBUG_ASSERT(table->lock_position == i);
511
/* Unlock if not yet unlocked */
512
if (always_unlock == FALSE)
513
mysql_unlock_some_tables(thd, &table, /* table count */ 1);
515
/* Decrement table_count in advance, making below expressions easier */
516
old_tables= --locked->table_count;
518
/* The table has 'removed_locks' lock data elements in locked->locks */
519
removed_locks= table->lock_count;
521
/* Move down all table pointers above 'i'. */
522
bmove((char*) (locked->table+i),
523
(char*) (locked->table+i+1),
524
(old_tables - i) * sizeof(TABLE*));
526
lock_data_end= table->lock_data_start + table->lock_count;
527
/* Move down all lock data pointers above 'table->lock_data_end-1' */
528
bmove((char*) (locked->locks + table->lock_data_start),
529
(char*) (locked->locks + lock_data_end),
530
(locked->lock_count - lock_data_end) *
531
sizeof(THR_LOCK_DATA*));
534
Fix moved table elements.
535
lock_position is the index in the 'locked->table' array,
536
it must be fixed by one.
537
table->lock_data_start is pointer to the lock data for this table
538
in the 'locked->locks' array, they must be fixed by 'removed_locks',
539
the lock data count of the removed table.
541
for (j= i ; j < old_tables; j++)
543
tbl= locked->table[j];
544
tbl->lock_position--;
545
DBUG_ASSERT(tbl->lock_position == j);
546
tbl->lock_data_start-= removed_locks;
549
/* Finally adjust lock_count. */
550
locked->lock_count-= removed_locks;
557
/* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
559
void mysql_lock_downgrade_write(THD *thd, TABLE *table,
560
thr_lock_type new_lock_type)
563
TABLE *write_lock_used;
564
if ((locked = get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
567
for (uint i=0; i < locked->lock_count; i++)
568
thr_downgrade_write_lock(locked->locks[i], new_lock_type);
569
my_free((uchar*) locked,MYF(0));
574
/** Abort all other threads waiting to get lock in table. */
576
void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock)
579
TABLE *write_lock_used;
580
DBUG_ENTER("mysql_lock_abort");
582
if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
585
for (uint i=0; i < locked->lock_count; i++)
586
thr_abort_locks(locked->locks[i]->lock, upgrade_lock);
587
my_free((uchar*) locked,MYF(0));
594
Abort one thread / table combination.
596
@param thd Thread handler
597
@param table Table that should be removed from lock queue
600
0 Table was not locked by another thread
602
1 Table was locked by at least one other thread
605
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table)
608
TABLE *write_lock_used;
610
DBUG_ENTER("mysql_lock_abort_for_thread");
612
if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
615
for (uint i=0; i < locked->lock_count; i++)
617
if (thr_abort_locks_for_thread(locked->locks[i]->lock,
618
table->in_use->thread_id))
621
my_free((uchar*) locked,MYF(0));
627
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
629
MYSQL_LOCK *sql_lock;
630
TABLE **table, **end_table;
631
DBUG_ENTER("mysql_lock_merge");
633
if (!(sql_lock= (MYSQL_LOCK*)
634
my_malloc(sizeof(*sql_lock)+
635
sizeof(THR_LOCK_DATA*)*(a->lock_count+b->lock_count)+
636
sizeof(TABLE*)*(a->table_count+b->table_count),MYF(MY_WME))))
637
DBUG_RETURN(0); // Fatal error
638
sql_lock->lock_count=a->lock_count+b->lock_count;
639
sql_lock->table_count=a->table_count+b->table_count;
640
sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
641
sql_lock->table=(TABLE**) (sql_lock->locks+sql_lock->lock_count);
642
memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
643
memcpy(sql_lock->locks+a->lock_count,b->locks,
644
b->lock_count*sizeof(*b->locks));
645
memcpy(sql_lock->table,a->table,a->table_count*sizeof(*a->table));
646
memcpy(sql_lock->table+a->table_count,b->table,
647
b->table_count*sizeof(*b->table));
650
Now adjust lock_position and lock_data_start for all objects that was
651
moved in 'b' (as there is now all objects in 'a' before these).
653
for (table= sql_lock->table + a->table_count,
654
end_table= table + b->table_count;
658
(*table)->lock_position+= a->table_count;
659
(*table)->lock_data_start+= a->lock_count;
662
/* Delete old, not needed locks */
663
my_free((uchar*) a,MYF(0));
664
my_free((uchar*) b,MYF(0));
665
DBUG_RETURN(sql_lock);
670
Find duplicate lock in tables.
672
Temporary tables are ignored here like they are ignored in
673
get_lock_data(). If we allow two opens on temporary tables later,
674
both functions should be checked.
676
@param thd The current thread.
677
@param needle The table to check for duplicate lock.
678
@param haystack The list of tables to search for the dup lock.
681
This is mainly meant for MERGE tables in INSERT ... SELECT
682
situations. The 'real', underlying tables can be found only after
683
the MERGE tables are opened. This function assumes that the tables are
687
NULL No duplicate lock found.
689
!NULL First table from 'haystack' that matches a lock on 'needle'.
692
TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle,
693
TABLE_LIST *haystack)
699
THR_LOCK_DATA **lock_locks;
700
THR_LOCK_DATA **table_lock_data;
701
THR_LOCK_DATA **end_data;
702
THR_LOCK_DATA **lock_data2;
703
THR_LOCK_DATA **end_data2;
704
DBUG_ENTER("mysql_lock_have_duplicate");
707
Table may not be defined for derived or view tables.
708
Table may not be part of a lock for delayed operations.
710
if (! (table= needle->table) || ! table->lock_count)
713
/* A temporary table does not have locks. */
714
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
717
/* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
718
if (! (mylock= thd->lock ? thd->lock : thd->locked_tables))
721
/* If we have less than two tables, we cannot have duplicates. */
722
if (mylock->table_count < 2)
725
lock_locks= mylock->locks;
726
lock_tables= mylock->table;
728
/* Prepare table related variables that don't change in loop. */
729
DBUG_ASSERT((table->lock_position < mylock->table_count) &&
730
(table == lock_tables[table->lock_position]));
731
table_lock_data= lock_locks + table->lock_data_start;
732
end_data= table_lock_data + table->lock_count;
734
for (; haystack; haystack= haystack->next_global)
736
if (haystack->placeholder())
738
table2= haystack->table;
739
if (table2->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
742
/* All tables in list must be in lock. */
743
DBUG_ASSERT((table2->lock_position < mylock->table_count) &&
744
(table2 == lock_tables[table2->lock_position]));
746
for (lock_data2= lock_locks + table2->lock_data_start,
747
end_data2= lock_data2 + table2->lock_count;
748
lock_data2 < end_data2;
751
THR_LOCK_DATA **lock_data;
752
THR_LOCK *lock2= (*lock_data2)->lock;
754
for (lock_data= table_lock_data;
755
lock_data < end_data;
758
if ((*lock_data)->lock == lock2)
760
DBUG_PRINT("info", ("haystack match: '%s'", haystack->table_name));
761
DBUG_RETURN(haystack);
768
DBUG_PRINT("info", ("no duplicate found"));
773
/** Unlock a set of external. */
775
static int unlock_external(THD *thd, TABLE **table,uint count)
777
int error,error_code;
778
DBUG_ENTER("unlock_external");
783
if ((*table)->current_lock != F_UNLCK)
785
(*table)->current_lock = F_UNLCK;
786
if ((error=(*table)->file->ha_external_lock(thd, F_UNLCK)))
789
print_lock_error(error_code, (*table)->file->table_type());
794
DBUG_RETURN(error_code);
799
Get lock structures from table structs and initialize locks.
801
@param thd Thread handler
802
@param table_ptr Pointer to tables that should be locks
804
- GET_LOCK_UNLOCK : If we should send TL_IGNORE to store lock
805
- GET_LOCK_STORE_LOCKS : Store lock info in TABLE
806
@param write_lock_used Store pointer to last table with WRITE_ALLOW_WRITE
809
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
810
uint flags, TABLE **write_lock_used)
812
uint i,tables,lock_count;
813
MYSQL_LOCK *sql_lock;
814
THR_LOCK_DATA **locks, **locks_buf, **locks_start;
815
TABLE **to, **table_buf;
816
DBUG_ENTER("get_lock_data");
818
DBUG_ASSERT((flags == GET_LOCK_UNLOCK) || (flags == GET_LOCK_STORE_LOCKS));
820
DBUG_PRINT("info", ("count %d", count));
822
for (i=tables=lock_count=0 ; i < count ; i++)
824
TABLE *t= table_ptr[i];
826
if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
828
tables+= t->file->lock_count();
834
Allocating twice the number of pointers for lock data for use in
835
thr_mulit_lock(). This function reorders the lock data, but cannot
836
update the table values. So the second part of the array is copied
837
from the first part immediately before calling thr_multi_lock().
839
if (!(sql_lock= (MYSQL_LOCK*)
840
my_malloc(sizeof(*sql_lock) +
841
sizeof(THR_LOCK_DATA*) * tables * 2 +
842
sizeof(table_ptr) * lock_count,
845
locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
846
to= table_buf= sql_lock->table= (TABLE**) (locks + tables * 2);
847
sql_lock->table_count=lock_count;
849
for (i=0 ; i < count ; i++)
852
enum thr_lock_type lock_type;
854
if ((table=table_ptr[i])->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
856
lock_type= table->reginfo.lock_type;
857
DBUG_ASSERT(lock_type != TL_WRITE_DEFAULT && lock_type != TL_READ_DEFAULT);
858
if (lock_type >= TL_WRITE_ALLOW_WRITE)
860
*write_lock_used=table;
861
if (table->db_stat & HA_READ_ONLY)
863
my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias);
864
/* Clear the lock type of the lock data that are stored already. */
865
sql_lock->lock_count= (uint) (locks - sql_lock->locks);
866
reset_lock_data(sql_lock);
867
my_free((uchar*) sql_lock,MYF(0));
871
THR_LOCK_DATA **org_locks = locks;
873
locks= table->file->store_lock(thd, locks,
874
(flags & GET_LOCK_UNLOCK) ? TL_IGNORE :
876
if (flags & GET_LOCK_STORE_LOCKS)
878
table->lock_position= (uint) (to - table_buf);
879
table->lock_data_start= (uint) (locks_start - locks_buf);
880
table->lock_count= (uint) (locks - locks_start);
884
for ( ; org_locks != locks ; org_locks++)
885
(*org_locks)->debug_print_param= (void *) table;
888
We do not use 'tables', because there are cases where store_lock()
889
returns less locks than lock_count() claimed. This can happen when
890
a FLUSH TABLES tries to abort locks from a MERGE table of another
891
thread. When that thread has just opened the table, but not yet
892
attached its children, it cannot return the locks. lock_count()
893
always returns the number of locks that an attached table has.
894
This is done to avoid the reverse situation: If lock_count() would
895
return 0 for a non-attached MERGE table, and that table becomes
896
attached between the calls to lock_count() and store_lock(), then
897
we would have allocated too little memory for the lock data. Now
898
we may allocate too much, but better safe than memory overrun.
899
And in the FLUSH case, the memory is released quickly anyway.
901
sql_lock->lock_count= locks - locks_buf;
902
DBUG_PRINT("info", ("sql_lock->table_count %d sql_lock->lock_count %d",
903
sql_lock->table_count, sql_lock->lock_count));
904
DBUG_RETURN(sql_lock);
909
Reset lock type in lock data.
911
After a locking error we want to quit the locking of the table(s).
912
The test case in the bug report for Bug #18544 has the following
914
-# Locking error in lock_external() due to InnoDB timeout.
915
-# Locking error in get_lock_data() due to missing write permission.
916
-# Locking error in wait_if_global_read_lock() due to lock conflict.
918
In all these cases we have already set the lock type into the lock
919
data of the open table(s). If the table(s) are in the open table
920
cache, they could be reused with the non-zero lock type set. This
921
could lead to ignoring a different lock type with the next lock.
923
Clear the lock type of all lock data. This ensures that the next
924
lock request will set its lock type properly.
926
@param sql_lock The MySQL lock.
929
static void reset_lock_data(MYSQL_LOCK *sql_lock)
931
THR_LOCK_DATA **ldata;
932
THR_LOCK_DATA **ldata_end;
934
for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
938
/* Reset lock type. */
939
(*ldata)->type= TL_UNLOCK;
944
/*****************************************************************************
945
Lock table based on the name.
946
This is used when we need total access to a closed, not open table
947
*****************************************************************************/
950
Lock and wait for the named lock.
952
@param thd Thread handler
953
@param table_list Lock first table in this list
957
Works together with global read lock.
965
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list)
969
DBUG_ENTER("lock_and_wait_for_table_name");
971
if (wait_if_global_read_lock(thd, 0, 1))
973
VOID(pthread_mutex_lock(&LOCK_open));
974
if ((lock_retcode = lock_table_name(thd, table_list, TRUE)) < 0)
976
if (lock_retcode && wait_for_locked_table_names(thd, table_list))
978
unlock_table_name(thd, table_list);
984
pthread_mutex_unlock(&LOCK_open);
985
start_waiting_global_read_lock(thd);
991
Put a not open table with an old refresh version in the table cache.
993
@param thd Thread handler
994
@param table_list Lock first table in this list
995
@param check_in_use Do we need to check if table already in use by us
998
One must have a lock on LOCK_open!
1001
If you are going to update the table, you should use
1002
lock_and_wait_for_table_name instead of this function as this works
1003
together with 'FLUSH TABLES WITH READ LOCK'
1006
This will force any other threads that uses the table to release it
1007
as soon as possible.
1014
> 0 table locked, but someone is using it
1017
int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use)
1020
char key[MAX_DBKEY_LENGTH];
1021
char *db= table_list->db;
1023
HASH_SEARCH_STATE state;
1024
DBUG_ENTER("lock_table_name");
1025
DBUG_PRINT("enter",("db: %s name: %s", db, table_list->table_name));
1027
key_length= create_table_def_key(thd, key, table_list, 0);
1031
/* Only insert the table if we haven't insert it already */
1032
for (table=(TABLE*) hash_first(&open_cache, (uchar*)key,
1033
key_length, &state);
1035
table = (TABLE*) hash_next(&open_cache,(uchar*) key,
1036
key_length, &state))
1038
if (table->in_use == thd)
1040
DBUG_PRINT("info", ("Table is in use"));
1041
table->s->version= 0; // Ensure no one can use this
1042
table->locked_by_name= 1;
1048
if (!(table= table_cache_insert_placeholder(thd, key, key_length)))
1051
table_list->table=table;
1053
/* Return 1 if table is in use */
1054
DBUG_RETURN(test(remove_table_from_cache(thd, db, table_list->table_name,
1055
check_in_use ? RTFC_NO_FLAG : RTFC_WAIT_OTHER_THREAD_FLAG)));
1059
void unlock_table_name(THD *thd, TABLE_LIST *table_list)
1061
if (table_list->table)
1063
hash_delete(&open_cache, (uchar*) table_list->table);
1064
broadcast_refresh();
1069
static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
1071
for (; table_list ; table_list=table_list->next_local)
1073
TABLE *table= table_list->table;
1076
TABLE *save_next= table->next;
1079
result= table_is_used(table_list->table, 0);
1080
table->next= save_next;
1085
return 0; // All tables are locked
1089
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
1092
DBUG_ENTER("wait_for_locked_table_names");
1094
safe_mutex_assert_owner(&LOCK_open);
1096
while (locked_named_table(thd,table_list))
1103
wait_for_condition(thd, &LOCK_open, &COND_refresh);
1104
pthread_mutex_lock(&LOCK_open);
1106
DBUG_RETURN(result);
1111
Lock all tables in list with a name lock.
1114
- One must have a lock on LOCK_open when calling this
1116
@param thd Thread handle
1117
@param table_list Names of tables to lock
1120
If you are just locking one table, you should use
1121
lock_and_wait_for_table_name().
1126
1 Fatal error (end of memory ?)
1129
bool lock_table_names(THD *thd, TABLE_LIST *table_list)
1131
bool got_all_locks=1;
1132
TABLE_LIST *lock_table;
1134
for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
1137
if ((got_lock=lock_table_name(thd,lock_table, TRUE)) < 0)
1138
goto end; // Fatal error
1140
got_all_locks=0; // Someone is using table
1143
/* If some table was in use, wait until we got the lock */
1144
if (!got_all_locks && wait_for_locked_table_names(thd, table_list))
1149
unlock_table_names(thd, table_list, lock_table);
1155
Unlock all tables in list with a name lock.
1157
@param thd Thread handle.
1158
@param table_list Names of tables to lock.
1161
This function needs to be protected by LOCK_open. If we're
1162
under LOCK TABLES, this function does not work as advertised. Namely,
1163
it does not exclude other threads from using this table and does not
1164
put an exclusive name lock on this table into the table cache.
1166
@see lock_table_names
1167
@see unlock_table_names
1169
@retval TRUE An error occured.
1170
@retval FALSE Name lock successfully acquired.
1173
bool lock_table_names_exclusively(THD *thd, TABLE_LIST *table_list)
1175
if (lock_table_names(thd, table_list))
1179
Upgrade the table name locks from semi-exclusive to exclusive locks.
1181
for (TABLE_LIST *table= table_list; table; table= table->next_global)
1184
table->table->open_placeholder= 1;
1191
Test is 'table' is protected by an exclusive name lock.
1193
@param[in] thd The current thread handler
1194
@param[in] table_list Table container containing the single table to be
1197
@note Needs to be protected by LOCK_open mutex.
1199
@return Error status code
1200
@retval TRUE Table is protected
1201
@retval FALSE Table is not protected
1205
is_table_name_exclusively_locked_by_this_thread(THD *thd,
1206
TABLE_LIST *table_list)
1208
char key[MAX_DBKEY_LENGTH];
1211
key_length= create_table_def_key(thd, key, table_list, 0);
1213
return is_table_name_exclusively_locked_by_this_thread(thd, (uchar *)key,
1219
Test is 'table key' is protected by an exclusive name lock.
1221
@param[in] thd The current thread handler.
1223
@param[in] key_length
1225
@note Needs to be protected by LOCK_open mutex
1227
@retval TRUE Table is protected
1228
@retval FALSE Table is not protected
1232
is_table_name_exclusively_locked_by_this_thread(THD *thd, uchar *key,
1235
HASH_SEARCH_STATE state;
1238
for (table= (TABLE*) hash_first(&open_cache, key,
1239
key_length, &state);
1241
table= (TABLE*) hash_next(&open_cache, key,
1242
key_length, &state))
1244
if (table->in_use == thd &&
1245
table->open_placeholder == 1 &&
1246
table->s->version == 0)
1254
Unlock all tables in list with a name lock.
1259
table_list Names of tables to unlock
1261
last_table Don't unlock any tables after this one.
1262
(default 0, which will unlock all tables)
1265
One must have a lock on LOCK_open when calling this.
1268
This function will broadcast refresh signals to inform other threads
1269
that the name locks are removed.
1274
1 Fatal error (end of memory ?)
1277
void unlock_table_names(THD *thd, TABLE_LIST *table_list,
1278
TABLE_LIST *last_table)
1280
DBUG_ENTER("unlock_table_names");
1281
for (TABLE_LIST *table= table_list;
1282
table != last_table;
1283
table= table->next_local)
1284
unlock_table_name(thd,table);
1285
broadcast_refresh();
1290
static void print_lock_error(int error, const char *table)
1293
DBUG_ENTER("print_lock_error");
1296
case HA_ERR_LOCK_WAIT_TIMEOUT:
1297
textno=ER_LOCK_WAIT_TIMEOUT;
1299
case HA_ERR_READ_ONLY_TRANSACTION:
1300
textno=ER_READ_ONLY_TRANSACTION;
1302
case HA_ERR_LOCK_DEADLOCK:
1303
textno=ER_LOCK_DEADLOCK;
1305
case HA_ERR_WRONG_COMMAND:
1306
textno=ER_ILLEGAL_HA;
1309
textno=ER_CANT_LOCK;
1313
if ( textno == ER_ILLEGAL_HA )
1314
my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), table);
1316
my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), error);
1322
/****************************************************************************
1323
Handling of global read locks
1325
Taking the global read lock is TWO steps (2nd step is optional; without
1326
it, COMMIT of existing transactions will be allowed):
1327
lock_global_read_lock() THEN make_global_read_lock_block_commit().
1329
The global locks are handled through the global variables:
1331
count of threads which have the global read lock (i.e. have completed at
1332
least the first step above)
1333
global_read_lock_blocks_commit
1334
count of threads which have the global read lock and block
1335
commits (i.e. are in or have completed the second step above)
1336
waiting_for_read_lock
1337
count of threads which want to take a global read lock but cannot
1338
protect_against_global_read_lock
1339
count of threads which have set protection against global read lock.
1341
access to them is protected with a mutex LOCK_global_read_lock
1343
(XXX: one should never take LOCK_open if LOCK_global_read_lock is
1344
taken, otherwise a deadlock may occur. Other mutexes could be a
1345
problem too - grep the code for global_read_lock if you want to use
1346
any other mutex here) Also one must not hold LOCK_open when calling
1347
wait_if_global_read_lock(). When the thread with the global read lock
1348
tries to close its tables, it needs to take LOCK_open in
1349
close_thread_table().
1351
How blocking of threads by global read lock is achieved: that's
1352
advisory. Any piece of code which should be blocked by global read lock must
1353
be designed like this:
1354
- call to wait_if_global_read_lock(). When this returns 0, no global read
1355
lock is owned; if argument abort_on_refresh was 0, none can be obtained.
1357
- if abort_on_refresh was 0, call to start_waiting_global_read_lock() to
1358
allow other threads to get the global read lock. I.e. removal of the
1360
(Note: it's a bit like an implementation of rwlock).
1362
[ I am sorry to mention some SQL syntaxes below I know I shouldn't but found
1363
no better descriptive way ]
1365
Why does FLUSH TABLES WITH READ LOCK need to block COMMIT: because it's used
1366
to read a non-moving SHOW MASTER STATUS, and a COMMIT writes to the binary
1369
Why getting the global read lock is two steps and not one. Because FLUSH
1370
TABLES WITH READ LOCK needs to insert one other step between the two:
1371
flushing tables. So the order is
1372
1) lock_global_read_lock() (prevents any new table write locks, i.e. stalls
1374
2) close_cached_tables() (the FLUSH TABLES), which will wait for tables
1375
currently opened and being updated to close (so it's possible that there is
1376
a moment where all new updates of server are stalled *and* FLUSH TABLES WITH
1378
3) make_global_read_lock_block_commit().
1379
If we have merged 1) and 3) into 1), we would have had this deadlock:
1380
imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB
1382
thd1: SELECT * FROM t FOR UPDATE;
1383
thd2: UPDATE t SET a=1; # blocked by row-level locks of thd1
1384
thd3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the
1385
table instance of thd2
1386
thd1: COMMIT; # blocked by thd3.
1387
thd1 blocks thd2 which blocks thd3 which blocks thd1: deadlock.
1389
Note that we need to support that one thread does
1390
FLUSH TABLES WITH READ LOCK; and then COMMIT;
1391
(that's what innobackup does, for some good reason).
1392
So in this exceptional case the COMMIT should not be blocked by the FLUSH
1393
TABLES WITH READ LOCK.
1395
****************************************************************************/
1397
volatile uint global_read_lock=0;
1398
volatile uint global_read_lock_blocks_commit=0;
1399
static volatile uint protect_against_global_read_lock=0;
1400
static volatile uint waiting_for_read_lock=0;
1402
#define GOT_GLOBAL_READ_LOCK 1
1403
#define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
1405
bool lock_global_read_lock(THD *thd)
1407
DBUG_ENTER("lock_global_read_lock");
1409
if (!thd->global_read_lock)
1411
const char *old_message;
1412
(void) pthread_mutex_lock(&LOCK_global_read_lock);
1413
old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1414
"Waiting to get readlock");
1416
("waiting_for: %d protect_against: %d",
1417
waiting_for_read_lock, protect_against_global_read_lock));
1419
waiting_for_read_lock++;
1420
while (protect_against_global_read_lock && !thd->killed)
1421
pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1422
waiting_for_read_lock--;
1425
thd->exit_cond(old_message);
1428
thd->global_read_lock= GOT_GLOBAL_READ_LOCK;
1430
thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1433
We DON'T set global_read_lock_blocks_commit now, it will be set after
1434
tables are flushed (as the present function serves for FLUSH TABLES WITH
1435
READ LOCK only). Doing things in this order is necessary to avoid
1436
deadlocks (we must allow COMMIT until all tables are closed; we should not
1437
forbid it before, or we can have a 3-thread deadlock if 2 do SELECT FOR
1438
UPDATE and one does FLUSH TABLES WITH READ LOCK).
1444
void unlock_global_read_lock(THD *thd)
1447
DBUG_ENTER("unlock_global_read_lock");
1449
("global_read_lock: %u global_read_lock_blocks_commit: %u",
1450
global_read_lock, global_read_lock_blocks_commit));
1452
pthread_mutex_lock(&LOCK_global_read_lock);
1453
tmp= --global_read_lock;
1454
if (thd->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
1455
--global_read_lock_blocks_commit;
1456
pthread_mutex_unlock(&LOCK_global_read_lock);
1457
/* Send the signal outside the mutex to avoid a context switch */
1460
DBUG_PRINT("signal", ("Broadcasting COND_global_read_lock"));
1461
pthread_cond_broadcast(&COND_global_read_lock);
1463
thd->global_read_lock= 0;
1468
#define must_wait (global_read_lock && \
1470
global_read_lock_blocks_commit))
1472
bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
1475
const char *UNINIT_VAR(old_message);
1476
bool result= 0, need_exit_cond;
1477
DBUG_ENTER("wait_if_global_read_lock");
1480
Assert that we do not own LOCK_open. If we would own it, other
1481
threads could not close their tables. This would make a pretty
1484
safe_mutex_assert_not_owner(&LOCK_open);
1486
(void) pthread_mutex_lock(&LOCK_global_read_lock);
1487
if ((need_exit_cond= must_wait))
1489
if (thd->global_read_lock) // This thread had the read locks
1492
my_message(ER_CANT_UPDATE_WITH_READLOCK,
1493
ER(ER_CANT_UPDATE_WITH_READLOCK), MYF(0));
1494
(void) pthread_mutex_unlock(&LOCK_global_read_lock);
1496
We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
1497
This allowance is needed to not break existing versions of innobackup
1498
which do a BEGIN; INSERT; FLUSH TABLES WITH READ LOCK; COMMIT.
1500
DBUG_RETURN(is_not_commit);
1502
old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1503
"Waiting for release of readlock");
1504
while (must_wait && ! thd->killed &&
1505
(!abort_on_refresh || thd->version == refresh_version))
1507
DBUG_PRINT("signal", ("Waiting for COND_global_read_lock"));
1508
(void) pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1509
DBUG_PRINT("signal", ("Got COND_global_read_lock"));
1514
if (!abort_on_refresh && !result)
1515
protect_against_global_read_lock++;
1517
The following is only true in case of a global read locks (which is rare)
1518
and if old_message is set
1520
if (unlikely(need_exit_cond))
1521
thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1523
pthread_mutex_unlock(&LOCK_global_read_lock);
1524
DBUG_RETURN(result);
1528
void start_waiting_global_read_lock(THD *thd)
1531
DBUG_ENTER("start_waiting_global_read_lock");
1532
if (unlikely(thd->global_read_lock))
1534
(void) pthread_mutex_lock(&LOCK_global_read_lock);
1535
DBUG_ASSERT(protect_against_global_read_lock);
1536
tmp= (!--protect_against_global_read_lock &&
1537
(waiting_for_read_lock || global_read_lock_blocks_commit));
1538
(void) pthread_mutex_unlock(&LOCK_global_read_lock);
1540
pthread_cond_broadcast(&COND_global_read_lock);
1545
bool make_global_read_lock_block_commit(THD *thd)
1548
const char *old_message;
1549
DBUG_ENTER("make_global_read_lock_block_commit");
1551
If we didn't succeed lock_global_read_lock(), or if we already suceeded
1552
make_global_read_lock_block_commit(), do nothing.
1554
if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK)
1556
pthread_mutex_lock(&LOCK_global_read_lock);
1557
/* increment this BEFORE waiting on cond (otherwise race cond) */
1558
global_read_lock_blocks_commit++;
1559
/* For testing we set up some blocking, to see if we can be killed */
1560
DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
1561
protect_against_global_read_lock++;);
1562
old_message= thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1563
"Waiting for all running commits to finish");
1564
while (protect_against_global_read_lock && !thd->killed)
1565
pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1566
DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
1567
protect_against_global_read_lock--;);
1568
if ((error= test(thd->killed)))
1569
global_read_lock_blocks_commit--; // undo what we did
1571
thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
1572
thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1578
Broadcast COND_refresh and COND_global_read_lock.
1580
Due to a bug in a threading library it could happen that a signal
1581
did not reach its target. A condition for this was that the same
1582
condition variable was used with different mutexes in
1583
pthread_cond_wait(). Some time ago we changed LOCK_open to
1584
LOCK_global_read_lock in global read lock handling. So COND_refresh
1585
was used with LOCK_open and LOCK_global_read_lock.
1587
We did now also change from COND_refresh to COND_global_read_lock
1588
in global read lock handling. But now it is necessary to signal
1589
both conditions at the same time.
1592
When signalling COND_global_read_lock within the global read lock
1593
handling, it is not necessary to also signal COND_refresh.
1596
void broadcast_refresh(void)
1598
VOID(pthread_cond_broadcast(&COND_refresh));
1599
VOID(pthread_cond_broadcast(&COND_global_read_lock));
1603
@} (end of group Locking)