214
session->set_proc_info("Notify start statement");
216
* Here, we advise all storage engines involved in the
217
* statement that we are starting a new statement
219
if (sql_lock->table_count)
199
if (!(flags & DRIZZLE_LOCK_IGNORE_GLOBAL_READ_ONLY) &&
202
!session->slave_thread)
221
size_t num_tables= sql_lock->table_count;
222
plugin::StorageEngine *engine;
223
set<size_t> involved_slots;
224
for (size_t x= 1; x <= num_tables; x++, tables++)
226
engine= (*tables)->cursor->engine;
227
if (involved_slots.count(engine->getId()) > 0)
228
continue; /* already added to involved engines */
229
involved_engines.push_back(engine);
230
involved_slots.insert(engine->getId());
233
for_each(involved_engines.begin(),
234
involved_engines.end(),
235
bind2nd(mem_fun(&plugin::StorageEngine::startStatement), session));
205
Someone has issued SET GLOBAL READ_ONLY=1 and we want a write lock.
206
We do not wait for READ_ONLY=0, and fail.
208
reset_lock_data_and_free(&sql_lock);
209
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
238
session->set_proc_info("External lock");
240
* Here, the call to lock_external() informs the
241
* all engines for all tables used in this statement
242
* of the type of lock that Drizzle intends to take on a
213
session->set_proc_info("System lock");
245
214
if (sql_lock->table_count && lock_external(session, sql_lock->table,
246
215
sql_lock->table_count))
473
435
effect is desired.
476
void mysql_lock_remove(Session *session, Table *table)
478
mysql_unlock_some_tables(session, &table, /* table count */ 1);
438
void mysql_lock_remove(Session *session, DRIZZLE_LOCK *locked,Table *table,
441
if (always_unlock == true)
442
mysql_unlock_some_tables(session, &table, /* table count */ 1);
446
for (i=0; i < locked->table_count; i++)
448
if (locked->table[i] == table)
450
uint32_t j, removed_locks, old_tables;
452
uint32_t lock_data_end;
454
assert(table->lock_position == i);
456
/* Unlock if not yet unlocked */
457
if (always_unlock == false)
458
mysql_unlock_some_tables(session, &table, /* table count */ 1);
460
/* Decrement table_count in advance, making below expressions easier */
461
old_tables= --locked->table_count;
463
/* The table has 'removed_locks' lock data elements in locked->locks */
464
removed_locks= table->lock_count;
466
/* Move down all table pointers above 'i'. */
467
memcpy((locked->table+i), (locked->table+i+1),
468
(old_tables - i) * sizeof(Table*));
470
lock_data_end= table->lock_data_start + table->lock_count;
471
/* Move down all lock data pointers above 'table->lock_data_end-1' */
472
memcpy((locked->locks + table->lock_data_start),
473
(locked->locks + lock_data_end),
474
(locked->lock_count - lock_data_end) *
475
sizeof(THR_LOCK_DATA*));
478
Fix moved table elements.
479
lock_position is the index in the 'locked->table' array,
480
it must be fixed by one.
481
table->lock_data_start is pointer to the lock data for this table
482
in the 'locked->locks' array, they must be fixed by 'removed_locks',
483
the lock data count of the removed table.
485
for (j= i ; j < old_tables; j++)
487
tbl= locked->table[j];
488
tbl->lock_position--;
489
assert(tbl->lock_position == j);
490
tbl->lock_data_start-= removed_locks;
493
/* Finally adjust lock_count. */
494
locked->lock_count-= removed_locks;
501
/* Downgrade all locks on a table to new WRITE level from WRITE_ONLY */
503
void mysql_lock_downgrade_write(Session *session, Table *table,
504
thr_lock_type new_lock_type)
506
DRIZZLE_LOCK *locked;
507
Table *write_lock_used;
508
if ((locked = get_lock_data(session, &table, 1, GET_LOCK_UNLOCK,
511
for (uint32_t i=0; i < locked->lock_count; i++)
512
thr_downgrade_write_lock(locked->locks[i], new_lock_type);
513
free((unsigned char*) locked);
482
518
/** Abort all other threads waiting to get lock in table. */
484
void mysql_lock_abort(Session *session, Table *table)
520
void mysql_lock_abort(Session *session, Table *table, bool upgrade_lock)
486
522
DRIZZLE_LOCK *locked;
487
523
Table *write_lock_used;
489
if ((locked= get_lock_data(session, &table, 1, false,
525
if ((locked= get_lock_data(session, &table, 1, GET_LOCK_UNLOCK,
490
526
&write_lock_used)))
492
for (uint32_t x= 0; x < locked->lock_count; x++)
493
thr_abort_locks(locked->locks[x]->lock);
528
for (uint32_t i=0; i < locked->lock_count; i++)
529
thr_abort_locks(locked->locks[i]->lock, upgrade_lock);
494
530
free((unsigned char*) locked);
526
563
free((unsigned char*) locked);
569
DRIZZLE_LOCK *mysql_lock_merge(DRIZZLE_LOCK *a,DRIZZLE_LOCK *b)
571
DRIZZLE_LOCK *sql_lock;
572
Table **table, **end_table;
574
if (!(sql_lock= (DRIZZLE_LOCK*)
575
my_malloc(sizeof(*sql_lock)+
576
sizeof(THR_LOCK_DATA*)*(a->lock_count+b->lock_count)+
577
sizeof(Table*)*(a->table_count+b->table_count),MYF(MY_WME))))
578
return(0); // Fatal error
579
sql_lock->lock_count=a->lock_count+b->lock_count;
580
sql_lock->table_count=a->table_count+b->table_count;
581
sql_lock->locks=(THR_LOCK_DATA**) (sql_lock+1);
582
sql_lock->table=(Table**) (sql_lock->locks+sql_lock->lock_count);
583
memcpy(sql_lock->locks,a->locks,a->lock_count*sizeof(*a->locks));
584
memcpy(sql_lock->locks+a->lock_count,b->locks,
585
b->lock_count*sizeof(*b->locks));
586
memcpy(sql_lock->table,a->table,a->table_count*sizeof(*a->table));
587
memcpy(sql_lock->table+a->table_count,b->table,
588
b->table_count*sizeof(*b->table));
591
Now adjust lock_position and lock_data_start for all objects that was
592
moved in 'b' (as there is now all objects in 'a' before these).
594
for (table= sql_lock->table + a->table_count,
595
end_table= table + b->table_count;
599
(*table)->lock_position+= a->table_count;
600
(*table)->lock_data_start+= a->lock_count;
603
/* Delete old, not needed locks */
604
free((unsigned char*) a);
605
free((unsigned char*) b);
611
Find duplicate lock in tables.
613
Temporary tables are ignored here like they are ignored in
614
get_lock_data(). If we allow two opens on temporary tables later,
615
both functions should be checked.
617
@param session The current thread.
618
@param needle The table to check for duplicate lock.
619
@param haystack The list of tables to search for the dup lock.
622
This is mainly meant for MERGE tables in INSERT ... SELECT
623
situations. The 'real', underlying tables can be found only after
624
the MERGE tables are opened. This function assumes that the tables are
628
NULL No duplicate lock found.
630
!NULL First table from 'haystack' that matches a lock on 'needle'.
633
TableList *mysql_lock_have_duplicate(Session *session, TableList *needle,
636
DRIZZLE_LOCK *mylock;
640
THR_LOCK_DATA **lock_locks;
641
THR_LOCK_DATA **table_lock_data;
642
THR_LOCK_DATA **end_data;
643
THR_LOCK_DATA **lock_data2;
644
THR_LOCK_DATA **end_data2;
647
Table may not be defined for derived or view tables.
648
Table may not be part of a lock for delayed operations.
650
if (! (table= needle->table) || ! table->lock_count)
653
/* A temporary table does not have locks. */
654
if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
657
/* Get command lock or LOCK TABLES lock. Maybe empty for INSERT DELAYED. */
658
if (! (mylock= session->lock ? session->lock : session->locked_tables))
661
/* If we have less than two tables, we cannot have duplicates. */
662
if (mylock->table_count < 2)
665
lock_locks= mylock->locks;
666
lock_tables= mylock->table;
668
/* Prepare table related variables that don't change in loop. */
669
assert((table->lock_position < mylock->table_count) &&
670
(table == lock_tables[table->lock_position]));
671
table_lock_data= lock_locks + table->lock_data_start;
672
end_data= table_lock_data + table->lock_count;
674
for (; haystack; haystack= haystack->next_global)
676
if (haystack->placeholder())
678
table2= haystack->table;
679
if (table2->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE)
682
/* All tables in list must be in lock. */
683
assert((table2->lock_position < mylock->table_count) &&
684
(table2 == lock_tables[table2->lock_position]));
686
for (lock_data2= lock_locks + table2->lock_data_start,
687
end_data2= lock_data2 + table2->lock_count;
688
lock_data2 < end_data2;
691
THR_LOCK_DATA **lock_data;
692
THR_LOCK *lock2= (*lock_data2)->lock;
694
for (lock_data= table_lock_data;
695
lock_data < end_data;
698
if ((*lock_data)->lock == lock2)
531
711
/** Unlock a set of external. */
558
738
@param session Thread handler
559
739
@param table_ptr Pointer to tables that should be locks
560
@param should_lock One of:
561
- false : If we should send TL_IGNORE to store lock
562
- true : Store lock info in Table
741
- GET_LOCK_UNLOCK : If we should send TL_IGNORE to store lock
742
- GET_LOCK_STORE_LOCKS : Store lock info in Table
563
743
@param write_lock_used Store pointer to last table with WRITE_ALLOW_WRITE
566
746
static DRIZZLE_LOCK *get_lock_data(Session *session, Table **table_ptr, uint32_t count,
567
bool should_lock, Table **write_lock_used)
747
uint32_t flags, Table **write_lock_used)
569
749
uint32_t i,tables,lock_count;
570
750
DRIZZLE_LOCK *sql_lock;
571
751
THR_LOCK_DATA **locks, **locks_buf, **locks_start;
572
752
Table **to, **table_buf;
754
assert((flags == GET_LOCK_UNLOCK) || (flags == GET_LOCK_STORE_LOCKS));
574
756
*write_lock_used=0;
575
for (i= tables= lock_count= 0 ; i < count ; i++)
757
for (i=tables=lock_count=0 ; i < count ; i++)
577
759
Table *t= table_ptr[i];
579
if (! (t->getEngine()->check_flag(HTON_BIT_SKIP_STORE_LOCK)))
761
if (t->s->tmp_table != NON_TRANSACTIONAL_TMP_TABLE)
763
tables+= t->file->lock_count();
648
829
And in the FLUSH case, the memory is released quickly anyway.
650
831
sql_lock->lock_count= locks - locks_buf;
836
/*****************************************************************************
837
Lock table based on the name.
838
This is used when we need total access to a closed, not open table
839
*****************************************************************************/
842
Lock and wait for the named lock.
844
@param session Thread handler
845
@param table_list Lock first table in this list
849
Works together with global read lock.
857
int lock_and_wait_for_table_name(Session *session, TableList *table_list)
862
if (wait_if_global_read_lock(session, 0, 1))
864
pthread_mutex_lock(&LOCK_open);
865
if ((lock_retcode = lock_table_name(session, table_list, true)) < 0)
867
if (lock_retcode && wait_for_locked_table_names(session, table_list))
869
unlock_table_name(session, table_list);
875
pthread_mutex_unlock(&LOCK_open);
876
start_waiting_global_read_lock(session);
1099
Test is 'table' is protected by an exclusive name lock.
1101
@param[in] session The current thread handler
1102
@param[in] table_list Table container containing the single table to be
1105
@note Needs to be protected by LOCK_open mutex.
1107
@return Error status code
1108
@retval TRUE Table is protected
1109
@retval FALSE Table is not protected
1113
is_table_name_exclusively_locked_by_this_thread(Session *session,
1114
TableList *table_list)
1116
char key[MAX_DBKEY_LENGTH];
1117
uint32_t key_length;
1119
key_length= create_table_def_key(session, key, table_list, 0);
1121
return is_table_name_exclusively_locked_by_this_thread(session, (unsigned char *)key,
1127
Test is 'table key' is protected by an exclusive name lock.
1129
@param[in] session The current thread handler.
1131
@param[in] key_length
1133
@note Needs to be protected by LOCK_open mutex
1135
@retval TRUE Table is protected
1136
@retval FALSE Table is not protected
1140
is_table_name_exclusively_locked_by_this_thread(Session *session, unsigned char *key,
1143
HASH_SEARCH_STATE state;
1146
for (table= (Table*) hash_first(&open_cache, key,
1147
key_length, &state);
1149
table= (Table*) hash_next(&open_cache, key,
1150
key_length, &state))
1152
if (table->in_use == session &&
1153
table->open_placeholder == 1 &&
1154
table->s->version == 0)
857
1162
Unlock all tables in list with a name lock.
1165
session Thread handle
860
1167
table_list Names of tables to unlock
862
1169
last_table Don't unlock any tables after this one.
1492
Try to get transactional table locks for the tables in the list.
1495
try_transactional_lock()
1496
session Thread handle
1497
table_list List of tables to lock
1500
This is called if transactional table locks are requested for all
1501
tables in table_list and no non-transactional locks pre-exist.
1504
0 OK. All tables are transactional locked.
1505
1 Error: must fall back to non-transactional locks.
1506
-1 Error: no recovery possible.
1509
int try_transactional_lock(Session *session, TableList *table_list)
1511
uint32_t dummy_counter;
1515
/* Need to open the tables to be able to access engine methods. */
1516
if (open_tables(session, &table_list, &dummy_counter, 0))
1518
/* purecov: begin tested */
1523
/* Required by InnoDB. */
1524
session->in_lock_tables= true;
1526
if ((error= set_handler_table_locks(session, table_list, true)))
1529
Not all transactional locks could be taken. If the error was
1530
something else but "unsupported by storage engine", abort the
1531
execution of this statement.
1533
if (error != HA_ERR_WRONG_COMMAND)
1539
Fall back to non-transactional locks because transactional locks
1540
are unsupported by a storage engine. No need to unlock the
1541
successfully taken transactional locks. They go away at end of
1548
/* We need to explicitly commit if autocommit mode is active. */
1549
(void) ha_autocommit_or_rollback(session, 0);
1550
/* Close the tables. The locks (if taken) persist in the storage engines. */
1551
close_tables_for_reopen(session, &table_list);
1552
session->in_lock_tables= false;
1558
Check if lock method conversion was done and was allowed.
1561
check_transactional_lock()
1562
session Thread handle
1563
table_list List of tables to lock
1567
Lock method conversion can be done during parsing if one of the
1568
locks is non-transactional. It can also happen if non-transactional
1569
table locks exist when the statement is executed or if a storage
1570
engine does not support transactional table locks.
1572
Check if transactional table locks have been converted to
1573
non-transactional and if this was allowed. In a running transaction
1574
or in strict mode lock method conversion is not allowed - report an
1575
error. Otherwise it is allowed - issue a warning.
1578
0 OK. Proceed with non-transactional locks.
1579
-1 Error: Lock conversion is prohibited.
1582
int check_transactional_lock(Session *session, TableList *table_list)
1586
char warn_buff[DRIZZLE_ERRMSG_SIZE];
1588
for (tlist= table_list; tlist; tlist= tlist->next_global)
1592
Unfortunately we cannot use tlist->placeholder() here. This method
1593
returns TRUE if the table is not open, which is always the case
1594
here. Whenever the definition of TableList::placeholder() is
1595
changed, probably this condition needs to be changed too.
1597
if (tlist->derived || tlist->schema_table || !tlist->lock_transactional)
1602
/* We must not convert the lock method in strict mode. */
1604
my_error(ER_NO_AUTO_CONVERT_LOCK_STRICT, MYF(0),
1605
tlist->alias ? tlist->alias : tlist->table_name);
1610
/* We must not convert the lock method within an active transaction. */
1611
if (session->active_transaction())
1613
my_error(ER_NO_AUTO_CONVERT_LOCK_TRANSACTION, MYF(0),
1614
tlist->alias ? tlist->alias : tlist->table_name);
1619
/* Warn about the conversion. */
1620
snprintf(warn_buff, sizeof(warn_buff), ER(ER_WARN_AUTO_CONVERT_LOCK),
1621
tlist->alias ? tlist->alias : tlist->table_name);
1622
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1623
ER_WARN_AUTO_CONVERT_LOCK, warn_buff);
1631
Set table locks in the table handler.
1634
set_handler_table_locks()
1635
session Thread handle
1636
table_list List of tables to lock
1637
transactional If to lock transactional or non-transactional
1641
!= 0 Error code from handler::lock_table().
1644
int set_handler_table_locks(Session *session, TableList *table_list,
1650
for (tlist= table_list; tlist; tlist= tlist->next_global)
1653
int lock_timeout= -1; /* Use default for non-transactional locks. */
1655
if (tlist->placeholder())
1658
assert((tlist->lock_type == TL_READ) ||
1659
(tlist->lock_type == TL_READ_NO_INSERT) ||
1660
(tlist->lock_type == TL_WRITE_DEFAULT) ||
1661
(tlist->lock_type == TL_WRITE) ||
1662
(tlist->lock_type == TL_WRITE_LOW_PRIORITY));
1665
Every tlist object has a proper lock_type set. Even if it came in
1666
the list as a base table from a view only.
1668
lock_type= ((tlist->lock_type <= TL_READ_NO_INSERT) ?
1669
HA_LOCK_IN_SHARE_MODE : HA_LOCK_IN_EXCLUSIVE_MODE);
1674
The lock timeout is not set if this table belongs to a view. We
1675
need to take it from the top-level view. After this loop
1676
iteration, lock_timeout is not needed any more. Not even if the
1677
locks are converted to non-transactional locks later.
1678
Non-transactional locks do not support a lock_timeout.
1680
lock_timeout= tlist->top_table()->lock_timeout;
1683
For warning/error reporting we need to set the intended lock
1684
method in the TableList object. It will be used later by
1685
check_transactional_lock(). The lock method is not set if this
1686
table belongs to a view. We can safely set it to transactional
1687
locking here. Even for non-view tables. This function is not
1688
called if non-transactional locking was requested for any
1691
tlist->lock_transactional= true;
1695
Because we need to set the lock method (see above) for all
1696
involved tables, we cannot break the loop on an error.
1697
But we do not try more locks after the first error.
1698
However, for non-transactional locking handler::lock_table() is
1699
a hint only. So we continue to call it for other tables.
1701
if (!error || !transactional)
1703
error= tlist->table->file->lock_table(session, lock_type, lock_timeout);
1704
if (error && transactional && (error != HA_ERR_WRONG_COMMAND))
1705
tlist->table->file->print_error(error, MYF(0));
1179
1714
@} (end of group Locking)
1182
} /* namespace drizzled */