1
/* Copyright (C) 2000-2006 MySQL AB
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 int lock_external(THD *thd, TABLE **table,uint count);
94
static int unlock_external(THD *thd, TABLE **table,uint count);
95
static void print_lock_error(int error, const char *);
102
thd The current thread.
103
tables An array of pointers to the tables to lock.
104
count The number of tables to lock.
106
MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK Ignore a global read lock
107
MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY Ignore SET GLOBAL READ_ONLY
108
MYSQL_LOCK_IGNORE_FLUSH Ignore a flush tables.
109
MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN Instead of reopening altered
110
or dropped tables by itself,
111
mysql_lock_tables() should
112
notify upper level and rely
113
on caller doing this.
114
need_reopen Out parameter, TRUE if some tables were altered
115
or deleted and should be reopened by caller.
118
A lock structure pointer on success.
119
NULL on error or if some tables should be reopen.
122
/* Map the return value of thr_lock to an error from errmsg.txt */
123
static int thr_lock_errno_to_mysql[]=
124
{ 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
127
Perform semantic checks for mysql_lock_tables.
128
@param thd The current thread
129
@param tables The tables to lock
130
@param count The number of tables to lock
131
@param flags Lock flags
132
@return 0 if all the check passed, non zero if a check failed.
134
int mysql_lock_tables_check(THD *thd, TABLE **tables, uint count, uint flags)
139
DBUG_ENTER("mysql_lock_tables_check");
143
for (i=0 ; i<count; i++)
147
/* Protect against 'fake' partially initialized TABLE_SHARE */
148
DBUG_ASSERT(t->s->table_category != TABLE_UNKNOWN_CATEGORY);
150
if ((t->s->table_category == TABLE_CATEGORY_SYSTEM) &&
151
(t->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE))
158
Locking of system tables is restricted:
159
locking a mix of system and non-system tables in the same lock
160
is prohibited, to prevent contention.
162
if ((system_count > 0) && (system_count < count))
164
my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0));
173
Reset lock type in lock data and free.
175
@param mysql_lock Lock structures to reset.
177
@note After a locking error we want to quit the locking of the table(s).
178
The test case in the bug report for Bug #18544 has the following
179
cases: 1. Locking error in lock_external() due to InnoDB timeout.
180
2. Locking error in get_lock_data() due to missing write permission.
181
3. Locking error in wait_if_global_read_lock() due to lock conflict.
183
@note In all these cases we have already set the lock type into the lock
184
data of the open table(s). If the table(s) are in the open table
185
cache, they could be reused with the non-zero lock type set. This
186
could lead to ignoring a different lock type with the next lock.
188
@note Clear the lock type of all lock data. This ensures that the next
189
lock request will set its lock type properly.
192
static void reset_lock_data_and_free(MYSQL_LOCK **mysql_lock)
194
MYSQL_LOCK *sql_lock= *mysql_lock;
195
THR_LOCK_DATA **ldata, **ldata_end;
197
/* Clear the lock type of all lock data to avoid reusage. */
198
for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count;
202
/* Reset lock type. */
203
(*ldata)->type= TL_UNLOCK;
205
my_free((uchar*) sql_lock, MYF(0));
210
MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
211
uint flags, bool *need_reopen)
213
MYSQL_LOCK *sql_lock;
214
TABLE *write_lock_used;
217
DBUG_ENTER("mysql_lock_tables");
221
if (mysql_lock_tables_check(thd, tables, count, flags))
226
if (! (sql_lock= get_lock_data(thd, tables, count, GET_LOCK_STORE_LOCKS,
230
if (global_read_lock && write_lock_used &&
231
! (flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK))
234
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
235
Wait until the lock is gone
237
if (wait_if_global_read_lock(thd, 1, 1))
239
/* Clear the lock type of all lock data to avoid reusage. */
240
reset_lock_data_and_free(&sql_lock);
243
if (thd->version != refresh_version)
245
/* Clear the lock type of all lock data to avoid reusage. */
246
reset_lock_data_and_free(&sql_lock);
251
if (!(flags & MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY) &&
257
Someone has issued SET GLOBAL READ_ONLY=1 and we want a write lock.
258
We do not wait for READ_ONLY=0, and fail.
260
reset_lock_data_and_free(&sql_lock);
261
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
265
thd_proc_info(thd, "System lock");
266
DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info));
267
if (sql_lock->table_count && lock_external(thd, sql_lock->table,
268
sql_lock->table_count))
270
/* Clear the lock type of all lock data to avoid reusage. */
271
reset_lock_data_and_free(&sql_lock);
274
thd_proc_info(thd, "Table lock");
275
DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info));
276
/* Copy the lock data array. thr_multi_lock() reorders its contens. */
277
memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks,
278
sql_lock->lock_count * sizeof(*sql_lock->locks));
279
/* Lock on the copied half of the lock data array. */
280
rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks +
281
sql_lock->lock_count,
282
sql_lock->lock_count,
284
if (rc > 1) /* a timeout or a deadlock */
286
if (sql_lock->table_count)
287
VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count));
288
reset_lock_data_and_free(&sql_lock);
289
my_error(rc, MYF(0));
292
else if (rc == 1) /* aborted */
294
thd->some_tables_deleted=1; // Try again
295
sql_lock->lock_count= 0; // Locks are already freed
296
// Fall through: unlock, reset lock data, free and retry
298
else if (!thd->some_tables_deleted || (flags & MYSQL_LOCK_IGNORE_FLUSH))
301
Thread was killed or lock aborted. Let upper level close all
302
used tables and retry or give error.
306
else if (!thd->open_tables)
308
// Only using temporary tables, no need to unlock
309
thd->some_tables_deleted=0;
312
thd_proc_info(thd, 0);
314
/* going to retry, unlock all tables */
315
if (sql_lock->lock_count)
316
thr_multi_unlock(sql_lock->locks, sql_lock->lock_count);
318
if (sql_lock->table_count)
319
VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count));
322
If thr_multi_lock fails it resets lock type for tables, which
323
were locked before (and including) one that caused error. Lock
324
type for other tables preserved.
326
reset_lock_data_and_free(&sql_lock);
328
if (flags & MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN)
333
if (wait_for_tables(thd))
334
break; // Couldn't open tables
336
thd_proc_info(thd, 0);
339
thd->send_kill_message();
342
mysql_unlock_tables(thd,sql_lock);
347
thd->set_time_after_lock();
348
DBUG_RETURN (sql_lock);
352
static int lock_external(THD *thd, TABLE **tables, uint count)
356
DBUG_ENTER("lock_external");
358
DBUG_PRINT("info", ("count %d", count));
359
for (i=1 ; i <= count ; i++, tables++)
361
DBUG_ASSERT((*tables)->reginfo.lock_type >= TL_READ);
362
lock_type=F_WRLCK; /* Lock exclusive */
363
if ((*tables)->db_stat & HA_READ_ONLY ||
364
((*tables)->reginfo.lock_type >= TL_READ &&
365
(*tables)->reginfo.lock_type <= TL_READ_NO_INSERT))
368
if ((error=(*tables)->file->ha_external_lock(thd,lock_type)))
370
print_lock_error(error, (*tables)->file->table_type());
374
(*tables)->file->ha_external_lock(thd, F_UNLCK);
375
(*tables)->current_lock=F_UNLCK;
381
(*tables)->db_stat &= ~ HA_BLOCK_LOCK;
382
(*tables)->current_lock= lock_type;
389
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock)
391
DBUG_ENTER("mysql_unlock_tables");
392
if (sql_lock->lock_count)
393
thr_multi_unlock(sql_lock->locks,sql_lock->lock_count);
394
if (sql_lock->table_count)
395
VOID(unlock_external(thd,sql_lock->table,sql_lock->table_count));
396
my_free((uchar*) sql_lock,MYF(0));
401
Unlock some of the tables locked by mysql_lock_tables.
403
This will work even if get_lock_data fails (next unlock will free all)
406
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count)
408
MYSQL_LOCK *sql_lock;
409
TABLE *write_lock_used;
410
if ((sql_lock= get_lock_data(thd, table, count, GET_LOCK_UNLOCK,
412
mysql_unlock_tables(thd, sql_lock);
417
unlock all tables locked for read.
420
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock)
423
DBUG_ENTER("mysql_unlock_read_tables");
425
/* Move all write locks first */
426
THR_LOCK_DATA **lock=sql_lock->locks;
427
for (i=found=0 ; i < sql_lock->lock_count ; i++)
429
if (sql_lock->locks[i]->type >= TL_WRITE_ALLOW_READ)
431
swap_variables(THR_LOCK_DATA *, *lock, sql_lock->locks[i]);
436
/* unlock the read locked tables */
439
thr_multi_unlock(lock,i-found);
440
sql_lock->lock_count= found;
443
/* Then do the same for the external locks */
444
/* Move all write locked tables first */
445
TABLE **table=sql_lock->table;
446
for (i=found=0 ; i < sql_lock->table_count ; i++)
448
DBUG_ASSERT(sql_lock->table[i]->lock_position == i);
449
if ((uint) sql_lock->table[i]->reginfo.lock_type >= TL_WRITE_ALLOW_READ)
451
swap_variables(TABLE *, *table, sql_lock->table[i]);
456
/* Unlock all read locked tables */
459
VOID(unlock_external(thd,table,i-found));
460
sql_lock->table_count=found;
462
/* Fix the lock positions in TABLE */
463
table= sql_lock->table;
465
for (i= 0; i < sql_lock->table_count; i++)
468
tbl->lock_position= table - sql_lock->table;
469
tbl->lock_data_start= found;
470
found+= tbl->lock_count;
478
Try to find the table in the list of locked tables.
479
In case of success, unlock the table and remove it from this list.
481
@note This function has a legacy side effect: the table is
482
unlocked even if it is not found in the locked list.
483
It's not clear if this side effect is intentional or still
484
desirable. It might lead to unmatched calls to
485
unlock_external(). Moreover, a discrepancy can be left
486
unnoticed by the storage engine, because in
487
unlock_external() we call handler::external_lock(F_UNLCK) only
488
if table->current_lock is not F_UNLCK.
490
@param thd thread context
491
@param locked list of locked tables
492
@param table the table to unlock
493
@param always_unlock specify explicitly if the legacy side
497
void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table,
500
if (always_unlock == TRUE)
501
mysql_unlock_some_tables(thd, &table, /* table count */ 1);
505
for (i=0; i < locked->table_count; i++)
507
if (locked->table[i] == table)
509
uint j, removed_locks, old_tables;
513
DBUG_ASSERT(table->lock_position == i);
515
/* Unlock if not yet unlocked */
516
if (always_unlock == FALSE)
517
mysql_unlock_some_tables(thd, &table, /* table count */ 1);
519
/* Decrement table_count in advance, making below expressions easier */
520
old_tables= --locked->table_count;
522
/* The table has 'removed_locks' lock data elements in locked->locks */
523
removed_locks= table->lock_count;
525
/* Move down all table pointers above 'i'. */
526
bmove((char*) (locked->table+i),
527
(char*) (locked->table+i+1),
528
(old_tables - i) * sizeof(TABLE*));
530
lock_data_end= table->lock_data_start + table->lock_count;
531
/* Move down all lock data pointers above 'table->lock_data_end-1' */
532
bmove((char*) (locked->locks + table->lock_data_start),
533
(char*) (locked->locks + lock_data_end),
534
(locked->lock_count - lock_data_end) *
535
sizeof(THR_LOCK_DATA*));
538
Fix moved table elements.
539
lock_position is the index in the 'locked->table' array,
540
it must be fixed by one.
541
table->lock_data_start is pointer to the lock data for this table
542
in the 'locked->locks' array, they must be fixed by 'removed_locks',
543
the lock data count of the removed table.
545
for (j= i ; j < old_tables; j++)
547
tbl= locked->table[j];
548
tbl->lock_position--;
549
DBUG_ASSERT(tbl->lock_position == j);
550
tbl->lock_data_start-= removed_locks;
553
/* Finally adjust lock_count. */
554
locked->lock_count-= removed_locks;
561
/* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
563
void mysql_lock_downgrade_write(THD *thd, TABLE *table,
564
thr_lock_type new_lock_type)
567
TABLE *write_lock_used;
568
if ((locked = get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
571
for (uint i=0; i < locked->lock_count; i++)
572
thr_downgrade_write_lock(locked->locks[i], new_lock_type);
573
my_free((uchar*) locked,MYF(0));
578
/** Abort all other threads waiting to get lock in table. */
580
void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock)
583
TABLE *write_lock_used;
584
DBUG_ENTER("mysql_lock_abort");
586
if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
589
for (uint i=0; i < locked->lock_count; i++)
590
thr_abort_locks(locked->locks[i]->lock, upgrade_lock);
591
my_free((uchar*) locked,MYF(0));
598
Abort one thread / table combination.
600
@param thd Thread handler
601
@param table Table that should be removed from lock queue
604
0 Table was not locked by another thread
606
1 Table was locked by at least one other thread
609
bool mysql_lock_abort_for_thread(THD *thd, TABLE *table)
612
TABLE *write_lock_used;
614
DBUG_ENTER("mysql_lock_abort_for_thread");
616
if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK,
619
for (uint i=0; i < locked->lock_count; i++)
621
if (thr_abort_locks_for_thread(locked->locks[i]->lock,
622
table->in_use->thread_id))
625
my_free((uchar*) locked,MYF(0));
631
MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b)
633
MYSQL_LOCK *sql_lock;
634
TABLE **table, **end_table;
635
DBUG_ENTER("mysql_lock_merge");
637
if (!(sql_lock= (MYSQL_LOCK*)
638
my_malloc(sizeof(*sql_lock)+
639
sizeof(THR_LOCK_DATA*)*(a->lock_count+b->lock_count)+
640
sizeof(TABLE*)*(a->table_count+b->table_count),MYF(MY_WME))))
641
DBUG_RETURN(0); // Fatal error
642
sql_lock->lock_count=a->lock_count+b->lock_count;
643
sql_lock->table_count=a->table_count+b->table_count;
644
sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
645
sql_lock->table=(TABLE**) (sql_lock->locks+sql_lock->lock_count);
646
memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
647
memcpy(sql_lock->locks+a->lock_count,b->locks,
648
b->lock_count*sizeof(*b->locks));
649
memcpy(sql_lock->table,a->table,a->table_count*sizeof(*a->table));
650
memcpy(sql_lock->table+a->table_count,b->table,
651
b->table_count*sizeof(*b->table));
654
Now adjust lock_position and lock_data_start for all objects that was
655
moved in 'b' (as there is now all objects in 'a' before these).
657
for (table= sql_lock->table + a->table_count,
658
end_table= table + b->table_count;
662
(*table)->lock_position+= a->table_count;
663
(*table)->lock_data_start+= a->lock_count;
666
/* Delete old, not needed locks */
667
my_free((uchar*) a,MYF(0));
668
my_free((uchar*) b,MYF(0));
669
DBUG_RETURN(sql_lock);
674
Find duplicate lock in tables.
676
Temporary tables are ignored here like they are ignored in
677
get_lock_data(). If we allow two opens on temporary tables later,
678
both functions should be checked.
680
@param thd The current thread.
681
@param needle The table to check for duplicate lock.
682
@param haystack The list of tables to search for the dup lock.
685
This is mainly meant for MERGE tables in INSERT ... SELECT
686
situations. The 'real', underlying tables can be found only after
687
the MERGE tables are opened. This function assumes that the tables are
691
NULL No duplicate lock found.
693
!NULL First table from 'haystack' that matches a lock on 'needle'.
696
TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle,
697
TABLE_LIST *haystack)
703
THR_LOCK_DATA **lock_locks;
704
THR_LOCK_DATA **table_lock_data;
705
THR_LOCK_DATA **end_data;
706
THR_LOCK_DATA **lock_data2;
707
THR_LOCK_DATA **end_data2;
708
DBUG_ENTER("mysql_lock_have_duplicate");
711
Table may not be defined for derived or view tables.
712
Table may not be part of a lock for delayed operations.
714
if (! (table= needle->table) || ! table->lock_count)
717
/* A temporary table does not have locks. */
718
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
721
/* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
722
if (! (mylock= thd->lock ? thd->lock : thd->locked_tables))
725
/* If we have less than two tables, we cannot have duplicates. */
726
if (mylock->table_count < 2)
729
lock_locks= mylock->locks;
730
lock_tables= mylock->table;
732
/* Prepare table related variables that don't change in loop. */
733
DBUG_ASSERT((table->lock_position < mylock->table_count) &&
734
(table == lock_tables[table->lock_position]));
735
table_lock_data= lock_locks + table->lock_data_start;
736
end_data= table_lock_data + table->lock_count;
738
for (; haystack; haystack= haystack->next_global)
740
if (haystack->placeholder())
742
table2= haystack->table;
743
if (table2->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
746
/* All tables in list must be in lock. */
747
DBUG_ASSERT((table2->lock_position < mylock->table_count) &&
748
(table2 == lock_tables[table2->lock_position]));
750
for (lock_data2= lock_locks + table2->lock_data_start,
751
end_data2= lock_data2 + table2->lock_count;
752
lock_data2 < end_data2;
755
THR_LOCK_DATA **lock_data;
756
THR_LOCK *lock2= (*lock_data2)->lock;
758
for (lock_data= table_lock_data;
759
lock_data < end_data;
762
if ((*lock_data)->lock == lock2)
764
DBUG_PRINT("info", ("haystack match: '%s'", haystack->table_name));
765
DBUG_RETURN(haystack);
772
DBUG_PRINT("info", ("no duplicate found"));
777
/** Unlock a set of external. */
779
static int unlock_external(THD *thd, TABLE **table,uint count)
781
int error,error_code;
782
DBUG_ENTER("unlock_external");
787
if ((*table)->current_lock != F_UNLCK)
789
(*table)->current_lock = F_UNLCK;
790
if ((error=(*table)->file->ha_external_lock(thd, F_UNLCK)))
793
print_lock_error(error_code, (*table)->file->table_type());
798
DBUG_RETURN(error_code);
803
Get lock structures from table structs and initialize locks.
805
@param thd Thread handler
806
@param table_ptr Pointer to tables that should be locks
808
- GET_LOCK_UNLOCK : If we should send TL_IGNORE to store lock
809
- GET_LOCK_STORE_LOCKS : Store lock info in TABLE
810
@param write_lock_used Store pointer to last table with WRITE_ALLOW_WRITE
813
static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
814
uint flags, TABLE **write_lock_used)
816
uint i,tables,lock_count;
817
MYSQL_LOCK *sql_lock;
818
THR_LOCK_DATA **locks, **locks_buf, **locks_start;
819
TABLE **to, **table_buf;
820
DBUG_ENTER("get_lock_data");
822
DBUG_ASSERT((flags == GET_LOCK_UNLOCK) || (flags == GET_LOCK_STORE_LOCKS));
824
DBUG_PRINT("info", ("count %d", count));
826
for (i=tables=lock_count=0 ; i < count ; i++)
828
TABLE *t= table_ptr[i];
830
if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
832
tables+= t->file->lock_count();
838
Allocating twice the number of pointers for lock data for use in
839
thr_mulit_lock(). This function reorders the lock data, but cannot
840
update the table values. So the second part of the array is copied
841
from the first part immediately before calling thr_multi_lock().
843
if (!(sql_lock= (MYSQL_LOCK*)
844
my_malloc(sizeof(*sql_lock) +
845
sizeof(THR_LOCK_DATA*) * tables * 2 +
846
sizeof(table_ptr) * lock_count,
849
locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
850
to= table_buf= sql_lock->table= (TABLE**) (locks + tables * 2);
851
sql_lock->table_count=lock_count;
853
for (i=0 ; i < count ; i++)
856
enum thr_lock_type lock_type;
858
if ((table=table_ptr[i])->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
860
lock_type= table->reginfo.lock_type;
861
DBUG_ASSERT (lock_type != TL_WRITE_DEFAULT);
862
if (lock_type >= TL_WRITE_ALLOW_WRITE)
864
*write_lock_used=table;
865
if (table->db_stat & HA_READ_ONLY)
867
my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias);
868
/* Clear the lock type of the lock data that are stored already. */
869
sql_lock->lock_count= locks - sql_lock->locks;
870
reset_lock_data_and_free(&sql_lock);
874
THR_LOCK_DATA **org_locks = locks;
876
locks= table->file->store_lock(thd, locks,
877
(flags & GET_LOCK_UNLOCK) ? TL_IGNORE :
879
if (flags & GET_LOCK_STORE_LOCKS)
881
table->lock_position= (uint) (to - table_buf);
882
table->lock_data_start= (uint) (locks_start - locks_buf);
883
table->lock_count= (uint) (locks - locks_start);
887
for ( ; org_locks != locks ; org_locks++)
888
(*org_locks)->debug_print_param= (void *) table;
891
We do not use 'tables', because there are cases where store_lock()
892
returns less locks than lock_count() claimed. This can happen when
893
a FLUSH TABLES tries to abort locks from a MERGE table of another
894
thread. When that thread has just opened the table, but not yet
895
attached its children, it cannot return the locks. lock_count()
896
always returns the number of locks that an attached table has.
897
This is done to avoid the reverse situation: If lock_count() would
898
return 0 for a non-attached MERGE table, and that table becomes
899
attached between the calls to lock_count() and store_lock(), then
900
we would have allocated too little memory for the lock data. Now
901
we may allocate too much, but better safe than memory overrun.
902
And in the FLUSH case, the memory is released quickly anyway.
904
sql_lock->lock_count= locks - locks_buf;
905
DBUG_PRINT("info", ("sql_lock->table_count %d sql_lock->lock_count %d",
906
sql_lock->table_count, sql_lock->lock_count));
907
DBUG_RETURN(sql_lock);
911
/*****************************************************************************
912
Lock table based on the name.
913
This is used when we need total access to a closed, not open table
914
*****************************************************************************/
917
Lock and wait for the named lock.
919
@param thd Thread handler
920
@param table_list Lock first table in this list
924
Works together with global read lock.
932
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list)
936
DBUG_ENTER("lock_and_wait_for_table_name");
938
if (wait_if_global_read_lock(thd, 0, 1))
940
VOID(pthread_mutex_lock(&LOCK_open));
941
if ((lock_retcode = lock_table_name(thd, table_list, TRUE)) < 0)
943
if (lock_retcode && wait_for_locked_table_names(thd, table_list))
945
unlock_table_name(thd, table_list);
951
pthread_mutex_unlock(&LOCK_open);
952
start_waiting_global_read_lock(thd);
958
Put a not open table with an old refresh version in the table cache.
960
@param thd Thread handler
961
@param table_list Lock first table in this list
962
@param check_in_use Do we need to check if table already in use by us
965
One must have a lock on LOCK_open!
968
If you are going to update the table, you should use
969
lock_and_wait_for_table_name instead of this function as this works
970
together with 'FLUSH TABLES WITH READ LOCK'
973
This will force any other threads that uses the table to release it
981
> 0 table locked, but someone is using it
984
int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use)
987
char key[MAX_DBKEY_LENGTH];
988
char *db= table_list->db;
990
bool found_locked_table= FALSE;
991
HASH_SEARCH_STATE state;
992
DBUG_ENTER("lock_table_name");
993
DBUG_PRINT("enter",("db: %s name: %s", db, table_list->table_name));
995
key_length= create_table_def_key(thd, key, table_list, 0);
999
/* Only insert the table if we haven't insert it already */
1000
for (table=(TABLE*) hash_first(&open_cache, (uchar*)key,
1001
key_length, &state);
1003
table = (TABLE*) hash_next(&open_cache,(uchar*) key,
1004
key_length, &state))
1006
if (table->reginfo.lock_type < TL_WRITE)
1008
if (table->in_use == thd)
1009
found_locked_table= TRUE;
1013
if (table->in_use == thd)
1015
DBUG_PRINT("info", ("Table is in use"));
1016
table->s->version= 0; // Ensure no one can use this
1017
table->locked_by_name= 1;
1023
if (thd->locked_tables && thd->locked_tables->table_count &&
1024
! find_temporary_table(thd, table_list->db, table_list->table_name))
1026
if (found_locked_table)
1027
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_list->alias);
1029
my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_list->alias);
1034
if (!(table= table_cache_insert_placeholder(thd, key, key_length)))
1037
table_list->table=table;
1039
/* Return 1 if table is in use */
1040
DBUG_RETURN(test(remove_table_from_cache(thd, db, table_list->table_name,
1041
check_in_use ? RTFC_NO_FLAG : RTFC_WAIT_OTHER_THREAD_FLAG)));
1045
void unlock_table_name(THD *thd, TABLE_LIST *table_list)
1047
if (table_list->table)
1049
hash_delete(&open_cache, (uchar*) table_list->table);
1050
broadcast_refresh();
1055
static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
1057
for (; table_list ; table_list=table_list->next_local)
1059
TABLE *table= table_list->table;
1062
TABLE *save_next= table->next;
1065
result= table_is_used(table_list->table, 0);
1066
table->next= save_next;
1071
return 0; // All tables are locked
1075
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
1078
DBUG_ENTER("wait_for_locked_table_names");
1080
safe_mutex_assert_owner(&LOCK_open);
1082
while (locked_named_table(thd,table_list))
1089
wait_for_condition(thd, &LOCK_open, &COND_refresh);
1090
pthread_mutex_lock(&LOCK_open);
1092
DBUG_RETURN(result);
1097
Lock all tables in list with a name lock.
1100
- One must have a lock on LOCK_open when calling this
1102
@param thd Thread handle
1103
@param table_list Names of tables to lock
1106
If you are just locking one table, you should use
1107
lock_and_wait_for_table_name().
1112
1 Fatal error (end of memory ?)
1115
bool lock_table_names(THD *thd, TABLE_LIST *table_list)
1117
bool got_all_locks=1;
1118
TABLE_LIST *lock_table;
1120
for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
1123
if ((got_lock=lock_table_name(thd,lock_table, TRUE)) < 0)
1124
goto end; // Fatal error
1126
got_all_locks=0; // Someone is using table
1129
/* If some table was in use, wait until we got the lock */
1130
if (!got_all_locks && wait_for_locked_table_names(thd, table_list))
1135
unlock_table_names(thd, table_list, lock_table);
1141
Unlock all tables in list with a name lock.
1143
@param thd Thread handle.
1144
@param table_list Names of tables to lock.
1147
This function needs to be protected by LOCK_open. If we're
1148
under LOCK TABLES, this function does not work as advertised. Namely,
1149
it does not exclude other threads from using this table and does not
1150
put an exclusive name lock on this table into the table cache.
1152
@see lock_table_names
1153
@see unlock_table_names
1155
@retval TRUE An error occured.
1156
@retval FALSE Name lock successfully acquired.
1159
bool lock_table_names_exclusively(THD *thd, TABLE_LIST *table_list)
1161
if (lock_table_names(thd, table_list))
1165
Upgrade the table name locks from semi-exclusive to exclusive locks.
1167
for (TABLE_LIST *table= table_list; table; table= table->next_global)
1170
table->table->open_placeholder= 1;
1177
Test is 'table' is protected by an exclusive name lock.
1179
@param[in] thd The current thread handler
1180
@param[in] table_list Table container containing the single table to be
1183
@note Needs to be protected by LOCK_open mutex.
1185
@return Error status code
1186
@retval TRUE Table is protected
1187
@retval FALSE Table is not protected
1191
is_table_name_exclusively_locked_by_this_thread(THD *thd,
1192
TABLE_LIST *table_list)
1194
char key[MAX_DBKEY_LENGTH];
1197
key_length= create_table_def_key(thd, key, table_list, 0);
1199
return is_table_name_exclusively_locked_by_this_thread(thd, (uchar *)key,
1205
Test is 'table key' is protected by an exclusive name lock.
1207
@param[in] thd The current thread handler.
1209
@param[in] key_length
1211
@note Needs to be protected by LOCK_open mutex
1213
@retval TRUE Table is protected
1214
@retval FALSE Table is not protected
1218
is_table_name_exclusively_locked_by_this_thread(THD *thd, uchar *key,
1221
HASH_SEARCH_STATE state;
1224
for (table= (TABLE*) hash_first(&open_cache, key,
1225
key_length, &state);
1227
table= (TABLE*) hash_next(&open_cache, key,
1228
key_length, &state))
1230
if (table->in_use == thd &&
1231
table->open_placeholder == 1 &&
1232
table->s->version == 0)
1240
Unlock all tables in list with a name lock.
1245
table_list Names of tables to unlock
1247
last_table Don't unlock any tables after this one.
1248
(default 0, which will unlock all tables)
1251
One must have a lock on LOCK_open when calling this.
1254
This function will broadcast refresh signals to inform other threads
1255
that the name locks are removed.
1260
1 Fatal error (end of memory ?)
1263
void unlock_table_names(THD *thd, TABLE_LIST *table_list,
1264
TABLE_LIST *last_table)
1266
DBUG_ENTER("unlock_table_names");
1267
for (TABLE_LIST *table= table_list;
1268
table != last_table;
1269
table= table->next_local)
1270
unlock_table_name(thd,table);
1271
broadcast_refresh();
1276
static void print_lock_error(int error, const char *table)
1279
DBUG_ENTER("print_lock_error");
1282
case HA_ERR_LOCK_WAIT_TIMEOUT:
1283
textno=ER_LOCK_WAIT_TIMEOUT;
1285
case HA_ERR_READ_ONLY_TRANSACTION:
1286
textno=ER_READ_ONLY_TRANSACTION;
1288
case HA_ERR_LOCK_DEADLOCK:
1289
textno=ER_LOCK_DEADLOCK;
1291
case HA_ERR_WRONG_COMMAND:
1292
textno=ER_ILLEGAL_HA;
1295
textno=ER_CANT_LOCK;
1299
if ( textno == ER_ILLEGAL_HA )
1300
my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), table);
1302
my_error(textno, MYF(ME_BELL+ME_OLDWIN+ME_WAITTANG), error);
1308
/****************************************************************************
1309
Handling of global read locks
1311
Taking the global read lock is TWO steps (2nd step is optional; without
1312
it, COMMIT of existing transactions will be allowed):
1313
lock_global_read_lock() THEN make_global_read_lock_block_commit().
1315
The global locks are handled through the global variables:
1317
count of threads which have the global read lock (i.e. have completed at
1318
least the first step above)
1319
global_read_lock_blocks_commit
1320
count of threads which have the global read lock and block
1321
commits (i.e. are in or have completed the second step above)
1322
waiting_for_read_lock
1323
count of threads which want to take a global read lock but cannot
1324
protect_against_global_read_lock
1325
count of threads which have set protection against global read lock.
1327
access to them is protected with a mutex LOCK_global_read_lock
1329
(XXX: one should never take LOCK_open if LOCK_global_read_lock is
1330
taken, otherwise a deadlock may occur. Other mutexes could be a
1331
problem too - grep the code for global_read_lock if you want to use
1332
any other mutex here) Also one must not hold LOCK_open when calling
1333
wait_if_global_read_lock(). When the thread with the global read lock
1334
tries to close its tables, it needs to take LOCK_open in
1335
close_thread_table().
1337
How blocking of threads by global read lock is achieved: that's
1338
advisory. Any piece of code which should be blocked by global read lock must
1339
be designed like this:
1340
- call to wait_if_global_read_lock(). When this returns 0, no global read
1341
lock is owned; if argument abort_on_refresh was 0, none can be obtained.
1343
- if abort_on_refresh was 0, call to start_waiting_global_read_lock() to
1344
allow other threads to get the global read lock. I.e. removal of the
1346
(Note: it's a bit like an implementation of rwlock).
1348
[ I am sorry to mention some SQL syntaxes below I know I shouldn't but found
1349
no better descriptive way ]
1351
Why does FLUSH TABLES WITH READ LOCK need to block COMMIT: because it's used
1352
to read a non-moving SHOW MASTER STATUS, and a COMMIT writes to the binary
1355
Why getting the global read lock is two steps and not one. Because FLUSH
1356
TABLES WITH READ LOCK needs to insert one other step between the two:
1357
flushing tables. So the order is
1358
1) lock_global_read_lock() (prevents any new table write locks, i.e. stalls
1360
2) close_cached_tables() (the FLUSH TABLES), which will wait for tables
1361
currently opened and being updated to close (so it's possible that there is
1362
a moment where all new updates of server are stalled *and* FLUSH TABLES WITH
1364
3) make_global_read_lock_block_commit().
1365
If we have merged 1) and 3) into 1), we would have had this deadlock:
1366
imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB
1368
thd1: SELECT * FROM t FOR UPDATE;
1369
thd2: UPDATE t SET a=1; # blocked by row-level locks of thd1
1370
thd3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the
1371
table instance of thd2
1372
thd1: COMMIT; # blocked by thd3.
1373
thd1 blocks thd2 which blocks thd3 which blocks thd1: deadlock.
1375
Note that we need to support that one thread does
1376
FLUSH TABLES WITH READ LOCK; and then COMMIT;
1377
(that's what innobackup does, for some good reason).
1378
So in this exceptional case the COMMIT should not be blocked by the FLUSH
1379
TABLES WITH READ LOCK.
1381
****************************************************************************/
1383
volatile uint global_read_lock=0;
1384
volatile uint global_read_lock_blocks_commit=0;
1385
static volatile uint protect_against_global_read_lock=0;
1386
static volatile uint waiting_for_read_lock=0;
1388
#define GOT_GLOBAL_READ_LOCK 1
1389
#define MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT 2
1391
bool lock_global_read_lock(THD *thd)
1393
DBUG_ENTER("lock_global_read_lock");
1395
if (!thd->global_read_lock)
1397
const char *old_message;
1398
(void) pthread_mutex_lock(&LOCK_global_read_lock);
1399
old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1400
"Waiting to get readlock");
1402
("waiting_for: %d protect_against: %d",
1403
waiting_for_read_lock, protect_against_global_read_lock));
1405
waiting_for_read_lock++;
1406
while (protect_against_global_read_lock && !thd->killed)
1407
pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1408
waiting_for_read_lock--;
1411
thd->exit_cond(old_message);
1414
thd->global_read_lock= GOT_GLOBAL_READ_LOCK;
1416
thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1419
We DON'T set global_read_lock_blocks_commit now, it will be set after
1420
tables are flushed (as the present function serves for FLUSH TABLES WITH
1421
READ LOCK only). Doing things in this order is necessary to avoid
1422
deadlocks (we must allow COMMIT until all tables are closed; we should not
1423
forbid it before, or we can have a 3-thread deadlock if 2 do SELECT FOR
1424
UPDATE and one does FLUSH TABLES WITH READ LOCK).
1430
void unlock_global_read_lock(THD *thd)
1433
DBUG_ENTER("unlock_global_read_lock");
1435
("global_read_lock: %u global_read_lock_blocks_commit: %u",
1436
global_read_lock, global_read_lock_blocks_commit));
1438
pthread_mutex_lock(&LOCK_global_read_lock);
1439
tmp= --global_read_lock;
1440
if (thd->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT)
1441
--global_read_lock_blocks_commit;
1442
pthread_mutex_unlock(&LOCK_global_read_lock);
1443
/* Send the signal outside the mutex to avoid a context switch */
1446
DBUG_PRINT("signal", ("Broadcasting COND_global_read_lock"));
1447
pthread_cond_broadcast(&COND_global_read_lock);
1449
thd->global_read_lock= 0;
1454
#define must_wait (global_read_lock && \
1456
global_read_lock_blocks_commit))
1458
bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
1461
const char *old_message= NULL;
1462
bool result= 0, need_exit_cond;
1463
DBUG_ENTER("wait_if_global_read_lock");
1466
Assert that we do not own LOCK_open. If we would own it, other
1467
threads could not close their tables. This would make a pretty
1470
safe_mutex_assert_not_owner(&LOCK_open);
1472
(void) pthread_mutex_lock(&LOCK_global_read_lock);
1473
if ((need_exit_cond= must_wait))
1475
if (thd->global_read_lock) // This thread had the read locks
1478
my_message(ER_CANT_UPDATE_WITH_READLOCK,
1479
ER(ER_CANT_UPDATE_WITH_READLOCK), MYF(0));
1480
(void) pthread_mutex_unlock(&LOCK_global_read_lock);
1482
We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
1483
This allowance is needed to not break existing versions of innobackup
1484
which do a BEGIN; INSERT; FLUSH TABLES WITH READ LOCK; COMMIT.
1486
DBUG_RETURN(is_not_commit);
1488
old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1489
"Waiting for release of readlock");
1490
while (must_wait && ! thd->killed &&
1491
(!abort_on_refresh || thd->version == refresh_version))
1493
DBUG_PRINT("signal", ("Waiting for COND_global_read_lock"));
1494
(void) pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1495
DBUG_PRINT("signal", ("Got COND_global_read_lock"));
1500
if (!abort_on_refresh && !result)
1501
protect_against_global_read_lock++;
1503
The following is only true in case of a global read locks (which is rare)
1504
and if old_message is set
1506
if (unlikely(need_exit_cond))
1507
thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1509
pthread_mutex_unlock(&LOCK_global_read_lock);
1510
DBUG_RETURN(result);
1514
void start_waiting_global_read_lock(THD *thd)
1517
DBUG_ENTER("start_waiting_global_read_lock");
1518
if (unlikely(thd->global_read_lock))
1520
(void) pthread_mutex_lock(&LOCK_global_read_lock);
1521
tmp= (!--protect_against_global_read_lock &&
1522
(waiting_for_read_lock || global_read_lock_blocks_commit));
1523
(void) pthread_mutex_unlock(&LOCK_global_read_lock);
1525
pthread_cond_broadcast(&COND_global_read_lock);
1530
bool make_global_read_lock_block_commit(THD *thd)
1533
const char *old_message;
1534
DBUG_ENTER("make_global_read_lock_block_commit");
1536
If we didn't succeed lock_global_read_lock(), or if we already suceeded
1537
make_global_read_lock_block_commit(), do nothing.
1539
if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK)
1541
pthread_mutex_lock(&LOCK_global_read_lock);
1542
/* increment this BEFORE waiting on cond (otherwise race cond) */
1543
global_read_lock_blocks_commit++;
1544
/* For testing we set up some blocking, to see if we can be killed */
1545
DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
1546
protect_against_global_read_lock++;);
1547
old_message= thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock,
1548
"Waiting for all running commits to finish");
1549
while (protect_against_global_read_lock && !thd->killed)
1550
pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock);
1551
DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
1552
protect_against_global_read_lock--;);
1553
if ((error= test(thd->killed)))
1554
global_read_lock_blocks_commit--; // undo what we did
1556
thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
1557
thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock
1563
Broadcast COND_refresh and COND_global_read_lock.
1565
Due to a bug in a threading library it could happen that a signal
1566
did not reach its target. A condition for this was that the same
1567
condition variable was used with different mutexes in
1568
pthread_cond_wait(). Some time ago we changed LOCK_open to
1569
LOCK_global_read_lock in global read lock handling. So COND_refresh
1570
was used with LOCK_open and LOCK_global_read_lock.
1572
We did now also change from COND_refresh to COND_global_read_lock
1573
in global read lock handling. But now it is necessary to signal
1574
both conditions at the same time.
1577
When signalling COND_global_read_lock within the global read lock
1578
handling, it is not necessary to also signal COND_refresh.
1581
void broadcast_refresh(void)
1583
VOID(pthread_cond_broadcast(&COND_refresh));
1584
VOID(pthread_cond_broadcast(&COND_global_read_lock));
1589
Try to get transactional table locks for the tables in the list.
1592
try_transactional_lock()
1594
table_list List of tables to lock
1597
This is called if transactional table locks are requested for all
1598
tables in table_list and no non-transactional locks pre-exist.
1601
0 OK. All tables are transactional locked.
1602
1 Error: must fall back to non-transactional locks.
1603
-1 Error: no recovery possible.
1606
int try_transactional_lock(THD *thd, TABLE_LIST *table_list)
1611
DBUG_ENTER("try_transactional_lock");
1613
/* Need to open the tables to be able to access engine methods. */
1614
if (open_tables(thd, &table_list, &dummy_counter, 0))
1616
/* purecov: begin tested */
1617
DBUG_PRINT("lock_info", ("aborting, open_tables failed"));
1622
/* Required by InnoDB. */
1623
thd->in_lock_tables= TRUE;
1625
if ((error= set_handler_table_locks(thd, table_list, TRUE)))
1628
Not all transactional locks could be taken. If the error was
1629
something else but "unsupported by storage engine", abort the
1630
execution of this statement.
1632
if (error != HA_ERR_WRONG_COMMAND)
1634
DBUG_PRINT("lock_info", ("aborting, lock_table failed"));
1639
Fall back to non-transactional locks because transactional locks
1640
are unsupported by a storage engine. No need to unlock the
1641
successfully taken transactional locks. They go away at end of
1644
DBUG_PRINT("lock_info", ("fall back to non-trans lock: no SE support"));
1649
/* We need to explicitly commit if autocommit mode is active. */
1650
(void) ha_autocommit_or_rollback(thd, 0);
1651
/* Close the tables. The locks (if taken) persist in the storage engines. */
1652
close_tables_for_reopen(thd, &table_list);
1653
thd->in_lock_tables= FALSE;
1654
DBUG_PRINT("lock_info", ("result: %d", result));
1655
DBUG_RETURN(result);
1660
Check if lock method conversion was done and was allowed.
1663
check_transactional_lock()
1665
table_list List of tables to lock
1669
Lock method conversion can be done during parsing if one of the
1670
locks is non-transactional. It can also happen if non-transactional
1671
table locks exist when the statement is executed or if a storage
1672
engine does not support transactional table locks.
1674
Check if transactional table locks have been converted to
1675
non-transactional and if this was allowed. In a running transaction
1676
or in strict mode lock method conversion is not allowed - report an
1677
error. Otherwise it is allowed - issue a warning.
1680
0 OK. Proceed with non-transactional locks.
1681
-1 Error: Lock conversion is prohibited.
1684
int check_transactional_lock(THD *thd, TABLE_LIST *table_list)
1688
char warn_buff[MYSQL_ERRMSG_SIZE];
1689
DBUG_ENTER("check_transactional_lock");
1691
for (tlist= table_list; tlist; tlist= tlist->next_global)
1693
DBUG_PRINT("lock_info", ("checking table: '%s'", tlist->table_name));
1696
Unfortunately we cannot use tlist->placeholder() here. This method
1697
returns TRUE if the table is not open, which is always the case
1698
here. Whenever the definition of TABLE_LIST::placeholder() is
1699
changed, probably this condition needs to be changed too.
1701
if (tlist->derived || tlist->schema_table || !tlist->lock_transactional)
1703
DBUG_PRINT("lock_info", ("skipping placeholder: %d transactional: %d",
1704
tlist->placeholder(),
1705
tlist->lock_transactional));
1709
/* We must not convert the lock method in strict mode. */
1711
my_error(ER_NO_AUTO_CONVERT_LOCK_STRICT, MYF(0),
1712
tlist->alias ? tlist->alias : tlist->table_name);
1717
/* We must not convert the lock method within an active transaction. */
1718
if (thd->active_transaction())
1720
my_error(ER_NO_AUTO_CONVERT_LOCK_TRANSACTION, MYF(0),
1721
tlist->alias ? tlist->alias : tlist->table_name);
1726
/* Warn about the conversion. */
1727
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_WARN_AUTO_CONVERT_LOCK),
1728
tlist->alias ? tlist->alias : tlist->table_name);
1729
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1730
ER_WARN_AUTO_CONVERT_LOCK, warn_buff);
1733
DBUG_PRINT("lock_info", ("result: %d", result));
1734
DBUG_RETURN(result);
1739
Set table locks in the table handler.
1742
set_handler_table_locks()
1744
table_list List of tables to lock
1745
transactional If to lock transactional or non-transactional
1749
!= 0 Error code from handler::lock_table().
1752
int set_handler_table_locks(THD *thd, TABLE_LIST *table_list,
1757
DBUG_ENTER("set_handler_table_locks");
1758
DBUG_PRINT("lock_info", ("transactional: %d", transactional));
1760
for (tlist= table_list; tlist; tlist= tlist->next_global)
1763
int lock_timeout= -1; /* Use default for non-transactional locks. */
1765
if (tlist->placeholder())
1768
DBUG_ASSERT((tlist->lock_type == TL_READ) ||
1769
(tlist->lock_type == TL_READ_NO_INSERT) ||
1770
(tlist->lock_type == TL_WRITE_DEFAULT) ||
1771
(tlist->lock_type == TL_WRITE) ||
1772
(tlist->lock_type == TL_WRITE_LOW_PRIORITY));
1775
Every tlist object has a proper lock_type set. Even if it came in
1776
the list as a base table from a view only.
1778
lock_type= ((tlist->lock_type <= TL_READ_NO_INSERT) ?
1779
HA_LOCK_IN_SHARE_MODE : HA_LOCK_IN_EXCLUSIVE_MODE);
1784
The lock timeout is not set if this table belongs to a view. We
1785
need to take it from the top-level view. After this loop
1786
iteration, lock_timeout is not needed any more. Not even if the
1787
locks are converted to non-transactional locks later.
1788
Non-transactional locks do not support a lock_timeout.
1790
lock_timeout= tlist->top_table()->lock_timeout;
1791
DBUG_PRINT("lock_info",
1792
("table: '%s' tlist==top_table: %d lock_timeout: %d",
1793
tlist->table_name, tlist==tlist->top_table(), lock_timeout));
1796
For warning/error reporting we need to set the intended lock
1797
method in the TABLE_LIST object. It will be used later by
1798
check_transactional_lock(). The lock method is not set if this
1799
table belongs to a view. We can safely set it to transactional
1800
locking here. Even for non-view tables. This function is not
1801
called if non-transactional locking was requested for any
1804
tlist->lock_transactional= TRUE;
1808
Because we need to set the lock method (see above) for all
1809
involved tables, we cannot break the loop on an error.
1810
But we do not try more locks after the first error.
1811
However, for non-transactional locking handler::lock_table() is
1812
a hint only. So we continue to call it for other tables.
1814
if (!error || !transactional)
1816
error= tlist->table->file->lock_table(thd, lock_type, lock_timeout);
1817
if (error && transactional && (error != HA_ERR_WRONG_COMMAND))
1818
tlist->table->file->print_error(error, MYF(0));
1827
@} (end of group Locking)