122
122
static bool auto_repair_table(THD *thd, TABLE_LIST *table_list);
123
123
static void free_cache_entry(TABLE *entry);
124
124
static bool tdc_wait_for_old_versions(THD *thd,
125
MDL_request_list *mdl_requests);
125
MDL_request_list *mdl_requests,
127
128
has_write_table_with_auto_increment(TABLE_LIST *tables);
2271
2272
proc_info=thd->proc_info;
2272
2273
thd_proc_info(thd, "Waiting for table");
2273
2274
DBUG_ENTER("wait_for_condition");
2275
DEBUG_SYNC(thd, "waiting_for_table");
2274
2276
if (!thd->killed)
2275
2277
mysql_cond_wait(cond, mutex);
2409
2411
mdl_requests.push_front(mdl_request);
2410
2412
mdl_requests.push_front(global_request);
2412
if (thd->mdl_context.acquire_locks(&mdl_requests,
2413
thd->variables.lock_wait_timeout))
2414
if (thd->mdl_context.acquire_locks(&mdl_requests, ot_ctx->get_timeout()))
2606
2607
(int) table_list->lock_type);
2609
If we are performing DDL operation we also should ensure
2610
that we will find TABLE instance with upgradable metadata
2613
if ((flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL) &&
2614
table_list->lock_type >= TL_WRITE_ALLOW_WRITE &&
2615
! table->mdl_ticket->is_upgradable_or_exclusive())
2619
2610
Find a table that either has the exact lock type requested,
2620
2611
or has the best suitable lock. In case there is no locked
2621
2612
table that has an equal or higher lock than requested,
2649
2640
if (best_table)
2651
if ((flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL) &&
2652
table_list->lock_type >= TL_WRITE_ALLOW_WRITE &&
2653
! best_table->mdl_ticket->is_upgradable_or_exclusive())
2655
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), alias);
2658
2642
table= best_table;
2659
2643
table->query_id= thd->query_id;
2660
2644
DBUG_PRINT("info",("Using locked table"));
3795
3779
/** Open_table_context */
3797
Open_table_context::Open_table_context(THD *thd)
3781
Open_table_context::Open_table_context(THD *thd, ulong timeout)
3798
3782
:m_action(OT_NO_ACTION),
3799
3783
m_start_of_statement_svp(thd->mdl_context.mdl_savepoint()),
3800
3784
m_has_locks((thd->in_multi_stmt_transaction() &&
3801
3785
thd->mdl_context.has_locks()) ||
3802
3786
thd->mdl_context.trans_sentinel()),
3803
m_global_mdl_request(NULL)
3787
m_global_mdl_request(NULL),
3895
3880
switch (m_action)
3897
3882
case OT_WAIT_MDL_LOCK:
3898
result= thd->mdl_context.wait_for_lock(mdl_request,
3899
thd->variables.lock_wait_timeout);
3883
result= thd->mdl_context.wait_for_lock(mdl_request, get_timeout());
3901
3885
case OT_WAIT_TDC:
3902
result= tdc_wait_for_old_versions(thd, &m_mdl_requests);
3886
result= tdc_wait_for_old_versions(thd, &m_mdl_requests, get_timeout());
3903
3887
DBUG_ASSERT(thd->mysys_var->current_mutex == NULL);
3905
3889
case OT_DISCOVER:
3916
3900
mdl_requests.push_front(&mdl_global_request);
3919
thd->mdl_context.acquire_locks(&mdl_requests,
3920
thd->variables.lock_wait_timeout)))
3903
thd->mdl_context.acquire_locks(&mdl_requests, get_timeout())))
3923
3906
DBUG_ASSERT(mdl_request->key.mdl_namespace() == MDL_key::TABLE);
3949
3932
mdl_requests.push_front(&mdl_global_request);
3952
thd->mdl_context.acquire_locks(&mdl_requests,
3953
thd->variables.lock_wait_timeout)))
3935
thd->mdl_context.acquire_locks(&mdl_requests, get_timeout())))
3956
3938
DBUG_ASSERT(mdl_request->key.mdl_namespace() == MDL_key::TABLE);
4408
4390
Acquire upgradable (SNW, SNRW) metadata locks on tables to be opened
4409
for LOCK TABLES or a DDL statement.
4391
for LOCK TABLES or a DDL statement. Under LOCK TABLES, we can't take
4392
new locks, so use open_tables_check_upgradable_mdl() instead.
4411
4394
@param thd Thread context.
4412
4395
@param tables_start Start of list of tables on which upgradable locks
4426
4409
MDL_request_list mdl_requests;
4427
4410
TABLE_LIST *table;
4412
DBUG_ASSERT(!thd->locked_tables_mode);
4413
DEBUG_SYNC(thd, "open_tables_acquire_upgradable_mdl");
4429
4415
for (table= tables_start; table && table != tables_end;
4430
4416
table= table->next_global)
4432
if (table->lock_type >= TL_WRITE_ALLOW_WRITE)
4418
if (table->lock_type >= TL_WRITE_ALLOW_WRITE &&
4419
!(table->open_type == OT_TEMPORARY_ONLY ||
4420
(table->open_type != OT_BASE_ONLY &&
4421
find_temporary_table(thd, table))))
4434
4423
table->mdl_request.set_type(table->lock_type > TL_WRITE_ALLOW_READ ?
4435
4424
MDL_SHARED_NO_READ_WRITE :
4447
4436
mdl_requests.push_front(global_request);
4450
if (thd->mdl_context.acquire_locks(&mdl_requests,
4451
thd->variables.lock_wait_timeout))
4439
if (thd->mdl_context.acquire_locks(&mdl_requests, ot_ctx->get_timeout()))
4454
4442
for (table= tables_start; table && table != tables_end;
4457
Check for upgradable (SNW, SNRW) metadata locks on tables to be opened
4458
for a DDL statement. Under LOCK TABLES, we can't take new locks, so we
4459
must check if appropriate locks were pre-acquired.
4461
@param thd Thread context.
4462
@param tables_start Start of list of tables on which upgradable locks
4463
should be searched for.
4464
@param tables_end End of list of tables.
4466
@retval FALSE Success.
4467
@retval TRUE Failure (e.g. connection was killed)
4471
open_tables_check_upgradable_mdl(THD *thd, TABLE_LIST *tables_start,
4472
TABLE_LIST *tables_end)
4476
DBUG_ASSERT(thd->locked_tables_mode);
4478
for (table= tables_start; table && table != tables_end;
4479
table= table->next_global)
4481
if (table->lock_type >= TL_WRITE_ALLOW_WRITE &&
4482
!(table->open_type == OT_TEMPORARY_ONLY ||
4483
(table->open_type != OT_BASE_ONLY &&
4484
find_temporary_table(thd, table))))
4487
We don't need to do anything about the found TABLE instance as it
4488
will be handled later in open_tables(), we only need to check that
4489
an upgradable lock is already acquired. When we enter LOCK TABLES
4490
mode, SNRW locks are acquired before all other locks. So if under
4491
LOCK TABLES we find that there is TABLE instance with upgradeable
4492
lock, all other instances of TABLE for the same table will have the
4495
Note that find_table_for_mdl_upgrade() will report an error if a
4496
ticket is not found.
4498
if (!find_table_for_mdl_upgrade(thd->open_tables, table->db,
4499
table->table_name, FALSE))
4469
4509
Open all tables in list
4471
4511
@param[in] thd Thread context.
4507
4547
TABLE_LIST **table_to_open;
4508
4548
Sroutine_hash_entry **sroutine_to_open;
4509
4549
TABLE_LIST *tables;
4510
Open_table_context ot_ctx(thd);
4550
Open_table_context ot_ctx(thd, (flags & MYSQL_LOCK_IGNORE_TIMEOUT) ?
4551
LONG_TIMEOUT : thd->variables.lock_wait_timeout);
4511
4552
bool error= FALSE;
4512
4553
MEM_ROOT new_frm_mem;
4513
4554
bool has_prelocking_list;
4550
4591
lock will be reused (thanks to the fact that in recursive case
4551
4592
metadata locks are acquired without waiting).
4553
if ((flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL) &&
4554
! thd->locked_tables_mode)
4594
if (flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL)
4556
if (open_tables_acquire_upgradable_mdl(thd, *start,
4557
thd->lex->first_not_own_table(),
4597
open_tables_acquire_upgradable_mdl() does not currenly handle
4598
these two flags. At this point, that does not matter as they
4599
are not used together with MYSQL_OPEN_TAKE_UPGRADABLE_MDL.
4601
DBUG_ASSERT(!(flags & (MYSQL_OPEN_SKIP_TEMPORARY |
4602
MYSQL_OPEN_TEMPORARY_ONLY)));
4603
if (thd->locked_tables_mode)
4606
Under LOCK TABLES, we can't acquire new locks, so we instead
4607
need to check if appropriate locks were pre-acquired.
4609
if (open_tables_check_upgradable_mdl(thd, *start,
4610
thd->lex->first_not_own_table()))
4616
else if (open_tables_acquire_upgradable_mdl(thd, *start,
4617
thd->lex->first_not_own_table(),
5011
5071
table_l->required_type= FRMTYPE_TABLE;
5013
5073
/* Open the table. */
5014
if (open_and_lock_tables_derived(thd, table_l, FALSE, flags))
5074
if (open_and_lock_tables(thd, table_l, FALSE, flags))
5015
5075
table_l->table= NULL; /* Just to be sure. */
5017
5077
/* Restore list. */
5049
5109
uint lock_flags)
5052
Open_table_context ot_ctx(thd);
5112
Open_table_context ot_ctx(thd, (lock_flags & MYSQL_LOCK_IGNORE_TIMEOUT) ?
5113
LONG_TIMEOUT : thd->variables.lock_wait_timeout);
5055
5116
DBUG_ENTER("open_ltable");
5149
5210
The lock will automaticaly be freed by close_thread_tables()
5152
There are several convenience functions, e.g. :
5153
- simple_open_n_lock_tables(thd, tables) without derived handling
5154
- open_and_lock_tables(thd, tables) with derived handling
5155
Both inline functions call open_and_lock_tables_derived() with
5156
the third argument set appropriately.
5158
5212
@retval FALSE OK.
5159
5213
@retval TRUE Error
5162
bool open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables,
5163
bool derived, uint flags,
5164
Prelocking_strategy *prelocking_strategy)
5216
bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
5217
bool derived, uint flags,
5218
Prelocking_strategy *prelocking_strategy)
5167
5221
bool need_reopen;
5177
5231
MDL_ticket *start_of_statement_svp= thd->mdl_context.mdl_savepoint();
5178
DBUG_ENTER("open_and_lock_tables_derived");
5232
DBUG_ENTER("open_and_lock_tables");
5179
5233
DBUG_PRINT("enter", ("derived handling: %d", derived));
8605
8659
@param thd Thread context
8606
8660
@param context Metadata locking context with locks.
8661
@param timeout Seconds to wait before reporting ER_LOCK_WAIT_TIMEOUT.
8610
tdc_wait_for_old_versions(THD *thd, MDL_request_list *mdl_requests)
8665
tdc_wait_for_old_versions(THD *thd, MDL_request_list *mdl_requests,
8612
8668
TABLE_SHARE *share;
8613
8669
const char *old_msg;
8614
8670
MDL_request *mdl_request;
8615
8671
struct timespec abstime;
8616
set_timespec(abstime, thd->variables.lock_wait_timeout);
8672
set_timespec(abstime, timeout);
8617
8673
int wait_result= 0;
8619
8675
while (!thd->killed)
8879
8935
lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
8880
8936
thd->reset_n_backup_open_tables_state(backup);
8882
if (open_and_lock_tables_derived(thd, table_list, FALSE,
8883
MYSQL_LOCK_IGNORE_FLUSH))
8938
if (open_and_lock_tables(thd, table_list, FALSE,
8939
MYSQL_LOCK_IGNORE_FLUSH |
8940
MYSQL_LOCK_IGNORE_TIMEOUT))
8885
8942
lex->restore_backup_query_tables_list(&query_tables_list_backup);
8943
9000
DBUG_ENTER("open_system_table_for_update");
8945
TABLE *table= open_ltable(thd, one_table, one_table->lock_type, 0);
9002
TABLE *table= open_ltable(thd, one_table, one_table->lock_type,
9003
MYSQL_LOCK_IGNORE_TIMEOUT);
8948
9006
DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_SYSTEM);
8969
9027
uint flags= ( MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK |
8970
9028
MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY |
8971
9029
MYSQL_LOCK_IGNORE_FLUSH |
9030
MYSQL_LOCK_IGNORE_TIMEOUT |
8972
9031
MYSQL_LOCK_PERF_SCHEMA);
8974
9033
/* Save value that is changed in mysql_lock_tables() */