1/*****************************************************************************
2
3Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2017, 2018, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc.,
1651 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
18*****************************************************************************/
19
20/**************************************************//**
21@file include/lock0lock.h
22The transaction lock system
23
24Created 5/7/1996 Heikki Tuuri
25*******************************************************/
26
27#ifndef lock0lock_h
28#define lock0lock_h
29
30#include "univ.i"
31#include "buf0types.h"
32#include "trx0types.h"
33#include "mtr0types.h"
34#include "rem0types.h"
35#include "dict0types.h"
36#include "que0types.h"
37#include "lock0types.h"
38#include "hash0hash.h"
39#include "srv0srv.h"
40#include "ut0vec.h"
41#include "gis0rtree.h"
42#include "lock0prdt.h"
43
44/** Alternatives for innodb_lock_schedule_algorithm, which can be changed by
45 setting innodb_lock_schedule_algorithm. */
46enum innodb_lock_schedule_algorithm_t {
47 /*!< First Come First Served */
48 INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS,
49 /*!< Variance-Aware-Transaction-Scheduling */
50 INNODB_LOCK_SCHEDULE_ALGORITHM_VATS
51};
52
53extern ulong innodb_lock_schedule_algorithm;
54
55// Forward declaration
56class ReadView;
57
58/** The value of innodb_deadlock_detect */
59extern my_bool innobase_deadlock_detect;
60
61/*********************************************************************//**
62Gets the size of a lock struct.
63@return size in bytes */
64ulint
65lock_get_size(void);
66/*===============*/
67/*********************************************************************//**
68Gets the heap_no of the smallest user record on a page.
69@return heap_no of smallest user record, or PAGE_HEAP_NO_SUPREMUM */
70UNIV_INLINE
71ulint
72lock_get_min_heap_no(
73/*=================*/
74 const buf_block_t* block); /*!< in: buffer block */
75/*************************************************************//**
76Updates the lock table when we have reorganized a page. NOTE: we copy
77also the locks set on the infimum of the page; the infimum may carry
78locks if an update of a record is occurring on the page, and its locks
79were temporarily stored on the infimum. */
80void
81lock_move_reorganize_page(
82/*======================*/
83 const buf_block_t* block, /*!< in: old index page, now
84 reorganized */
85 const buf_block_t* oblock);/*!< in: copy of the old, not
86 reorganized page */
87/*************************************************************//**
88Moves the explicit locks on user records to another page if a record
89list end is moved to another page. */
90void
91lock_move_rec_list_end(
92/*===================*/
93 const buf_block_t* new_block, /*!< in: index page to move to */
94 const buf_block_t* block, /*!< in: index page */
95 const rec_t* rec); /*!< in: record on page: this
96 is the first record moved */
97/*************************************************************//**
98Moves the explicit locks on user records to another page if a record
99list start is moved to another page. */
100void
101lock_move_rec_list_start(
102/*=====================*/
103 const buf_block_t* new_block, /*!< in: index page to move to */
104 const buf_block_t* block, /*!< in: index page */
105 const rec_t* rec, /*!< in: record on page:
106 this is the first
107 record NOT copied */
108 const rec_t* old_end); /*!< in: old
109 previous-to-last
110 record on new_page
111 before the records
112 were copied */
113/*************************************************************//**
114Updates the lock table when a page is split to the right. */
115void
116lock_update_split_right(
117/*====================*/
118 const buf_block_t* right_block, /*!< in: right page */
119 const buf_block_t* left_block); /*!< in: left page */
120/*************************************************************//**
121Updates the lock table when a page is merged to the right. */
122void
123lock_update_merge_right(
124/*====================*/
125 const buf_block_t* right_block, /*!< in: right page to
126 which merged */
127 const rec_t* orig_succ, /*!< in: original
128 successor of infimum
129 on the right page
130 before merge */
131 const buf_block_t* left_block); /*!< in: merged index
132 page which will be
133 discarded */
134/*************************************************************//**
135Updates the lock table when the root page is copied to another in
136btr_root_raise_and_insert. Note that we leave lock structs on the
137root page, even though they do not make sense on other than leaf
138pages: the reason is that in a pessimistic update the infimum record
139of the root page will act as a dummy carrier of the locks of the record
140to be updated. */
141void
142lock_update_root_raise(
143/*===================*/
144 const buf_block_t* block, /*!< in: index page to which copied */
145 const buf_block_t* root); /*!< in: root page */
146/*************************************************************//**
147Updates the lock table when a page is copied to another and the original page
148is removed from the chain of leaf pages, except if page is the root! */
149void
150lock_update_copy_and_discard(
151/*=========================*/
152 const buf_block_t* new_block, /*!< in: index page to
153 which copied */
154 const buf_block_t* block); /*!< in: index page;
155 NOT the root! */
156/*************************************************************//**
157Updates the lock table when a page is split to the left. */
158void
159lock_update_split_left(
160/*===================*/
161 const buf_block_t* right_block, /*!< in: right page */
162 const buf_block_t* left_block); /*!< in: left page */
163/*************************************************************//**
164Updates the lock table when a page is merged to the left. */
165void
166lock_update_merge_left(
167/*===================*/
168 const buf_block_t* left_block, /*!< in: left page to
169 which merged */
170 const rec_t* orig_pred, /*!< in: original predecessor
171 of supremum on the left page
172 before merge */
173 const buf_block_t* right_block); /*!< in: merged index page
174 which will be discarded */
175/*************************************************************//**
176Updates the lock table when a page is split and merged to
177two pages. */
178UNIV_INTERN
179void
180lock_update_split_and_merge(
181 const buf_block_t* left_block, /*!< in: left page to which merged */
182 const rec_t* orig_pred, /*!< in: original predecessor of
183 supremum on the left page before merge*/
184 const buf_block_t* right_block);/*!< in: right page from which merged */
185/*************************************************************//**
186Resets the original locks on heir and replaces them with gap type locks
187inherited from rec. */
188void
189lock_rec_reset_and_inherit_gap_locks(
190/*=================================*/
191 const buf_block_t* heir_block, /*!< in: block containing the
192 record which inherits */
193 const buf_block_t* block, /*!< in: block containing the
194 record from which inherited;
195 does NOT reset the locks on
196 this record */
197 ulint heir_heap_no, /*!< in: heap_no of the
198 inheriting record */
199 ulint heap_no); /*!< in: heap_no of the
200 donating record */
201/*************************************************************//**
202Updates the lock table when a page is discarded. */
203void
204lock_update_discard(
205/*================*/
206 const buf_block_t* heir_block, /*!< in: index page
207 which will inherit the locks */
208 ulint heir_heap_no, /*!< in: heap_no of the record
209 which will inherit the locks */
210 const buf_block_t* block); /*!< in: index page
211 which will be discarded */
212/*************************************************************//**
213Updates the lock table when a new user record is inserted. */
214void
215lock_update_insert(
216/*===============*/
217 const buf_block_t* block, /*!< in: buffer block containing rec */
218 const rec_t* rec); /*!< in: the inserted record */
219/*************************************************************//**
220Updates the lock table when a record is removed. */
221void
222lock_update_delete(
223/*===============*/
224 const buf_block_t* block, /*!< in: buffer block containing rec */
225 const rec_t* rec); /*!< in: the record to be removed */
226/*********************************************************************//**
227Stores on the page infimum record the explicit locks of another record.
228This function is used to store the lock state of a record when it is
229updated and the size of the record changes in the update. The record
230is in such an update moved, perhaps to another page. The infimum record
231acts as a dummy carrier record, taking care of lock releases while the
232actual record is being moved. */
233void
234lock_rec_store_on_page_infimum(
235/*===========================*/
236 const buf_block_t* block, /*!< in: buffer block containing rec */
237 const rec_t* rec); /*!< in: record whose lock state
238 is stored on the infimum
239 record of the same page; lock
240 bits are reset on the
241 record */
242/*********************************************************************//**
243Restores the state of explicit lock requests on a single record, where the
244state was stored on the infimum of the page. */
245void
246lock_rec_restore_from_page_infimum(
247/*===============================*/
248 const buf_block_t* block, /*!< in: buffer block containing rec */
249 const rec_t* rec, /*!< in: record whose lock state
250 is restored */
251 const buf_block_t* donator);/*!< in: page (rec is not
252 necessarily on this page)
253 whose infimum stored the lock
254 state; lock bits are reset on
255 the infimum */
256/*********************************************************************//**
257Determines if there are explicit record locks on a page.
258@return an explicit record lock on the page, or NULL if there are none */
259lock_t*
260lock_rec_expl_exist_on_page(
261/*========================*/
262 ulint space, /*!< in: space id */
263 ulint page_no)/*!< in: page number */
264 MY_ATTRIBUTE((warn_unused_result));
265/*********************************************************************//**
266Checks if locks of other transactions prevent an immediate insert of
267a record. If they do, first tests if the query thread should anyway
268be suspended for some reason; if not, then puts the transaction and
269the query thread to the lock wait state and inserts a waiting request
270for a gap x-lock to the lock queue.
271@return DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK */
272dberr_t
273lock_rec_insert_check_and_lock(
274/*===========================*/
275 ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG bit is
276 set, does nothing */
277 const rec_t* rec, /*!< in: record after which to insert */
278 buf_block_t* block, /*!< in/out: buffer block of rec */
279 dict_index_t* index, /*!< in: index */
280 que_thr_t* thr, /*!< in: query thread */
281 mtr_t* mtr, /*!< in/out: mini-transaction */
282 bool* inherit)/*!< out: set to true if the new
283 inserted record maybe should inherit
284 LOCK_GAP type locks from the successor
285 record */
286 MY_ATTRIBUTE((warn_unused_result));
287
288/*********************************************************************//**
289Checks if locks of other transactions prevent an immediate modify (update,
290delete mark, or delete unmark) of a clustered index record. If they do,
291first tests if the query thread should anyway be suspended for some
292reason; if not, then puts the transaction and the query thread to the
293lock wait state and inserts a waiting request for a record x-lock to the
294lock queue.
295@return DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK */
296dberr_t
297lock_clust_rec_modify_check_and_lock(
298/*=================================*/
299 ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
300 bit is set, does nothing */
301 const buf_block_t* block, /*!< in: buffer block of rec */
302 const rec_t* rec, /*!< in: record which should be
303 modified */
304 dict_index_t* index, /*!< in: clustered index */
305 const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
306 que_thr_t* thr) /*!< in: query thread */
307 MY_ATTRIBUTE((warn_unused_result));
308/*********************************************************************//**
309Checks if locks of other transactions prevent an immediate modify
310(delete mark or delete unmark) of a secondary index record.
311@return DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK */
312dberr_t
313lock_sec_rec_modify_check_and_lock(
314/*===============================*/
315 ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
316 bit is set, does nothing */
317 buf_block_t* block, /*!< in/out: buffer block of rec */
318 const rec_t* rec, /*!< in: record which should be
319 modified; NOTE: as this is a secondary
320 index, we always have to modify the
321 clustered index record first: see the
322 comment below */
323 dict_index_t* index, /*!< in: secondary index */
324 que_thr_t* thr, /*!< in: query thread
325 (can be NULL if BTR_NO_LOCKING_FLAG) */
326 mtr_t* mtr) /*!< in/out: mini-transaction */
327 MY_ATTRIBUTE((warn_unused_result));
328/*********************************************************************//**
329Like lock_clust_rec_read_check_and_lock(), but reads a
330secondary index record.
331@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, or DB_DEADLOCK */
332dberr_t
333lock_sec_rec_read_check_and_lock(
334/*=============================*/
335 ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
336 bit is set, does nothing */
337 const buf_block_t* block, /*!< in: buffer block of rec */
338 const rec_t* rec, /*!< in: user record or page
339 supremum record which should
340 be read or passed over by a
341 read cursor */
342 dict_index_t* index, /*!< in: secondary index */
343 const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
344 lock_mode mode, /*!< in: mode of the lock which
345 the read cursor should set on
346 records: LOCK_S or LOCK_X; the
347 latter is possible in
348 SELECT FOR UPDATE */
349 ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
350 LOCK_REC_NOT_GAP */
351 que_thr_t* thr); /*!< in: query thread */
352/*********************************************************************//**
353Checks if locks of other transactions prevent an immediate read, or passing
354over by a read cursor, of a clustered index record. If they do, first tests
355if the query thread should anyway be suspended for some reason; if not, then
356puts the transaction and the query thread to the lock wait state and inserts a
357waiting request for a record lock to the lock queue. Sets the requested mode
358lock on the record.
359@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, or DB_DEADLOCK */
360dberr_t
361lock_clust_rec_read_check_and_lock(
362/*===============================*/
363 ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
364 bit is set, does nothing */
365 const buf_block_t* block, /*!< in: buffer block of rec */
366 const rec_t* rec, /*!< in: user record or page
367 supremum record which should
368 be read or passed over by a
369 read cursor */
370 dict_index_t* index, /*!< in: clustered index */
371 const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
372 lock_mode mode, /*!< in: mode of the lock which
373 the read cursor should set on
374 records: LOCK_S or LOCK_X; the
375 latter is possible in
376 SELECT FOR UPDATE */
377 ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
378 LOCK_REC_NOT_GAP */
379 que_thr_t* thr); /*!< in: query thread */
380/*********************************************************************//**
381Checks if locks of other transactions prevent an immediate read, or passing
382over by a read cursor, of a clustered index record. If they do, first tests
383if the query thread should anyway be suspended for some reason; if not, then
384puts the transaction and the query thread to the lock wait state and inserts a
385waiting request for a record lock to the lock queue. Sets the requested mode
386lock on the record. This is an alternative version of
387lock_clust_rec_read_check_and_lock() that does not require the parameter
388"offsets".
389@return DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK */
390dberr_t
391lock_clust_rec_read_check_and_lock_alt(
392/*===================================*/
393 ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
394 bit is set, does nothing */
395 const buf_block_t* block, /*!< in: buffer block of rec */
396 const rec_t* rec, /*!< in: user record or page
397 supremum record which should
398 be read or passed over by a
399 read cursor */
400 dict_index_t* index, /*!< in: clustered index */
401 lock_mode mode, /*!< in: mode of the lock which
402 the read cursor should set on
403 records: LOCK_S or LOCK_X; the
404 latter is possible in
405 SELECT FOR UPDATE */
406 ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
407 LOCK_REC_NOT_GAP */
408 que_thr_t* thr) /*!< in: query thread */
409 MY_ATTRIBUTE((warn_unused_result));
410/*********************************************************************//**
411Checks that a record is seen in a consistent read.
412@return true if sees, or false if an earlier version of the record
413should be retrieved */
414bool
415lock_clust_rec_cons_read_sees(
416/*==========================*/
417 const rec_t* rec, /*!< in: user record which should be read or
418 passed over by a read cursor */
419 dict_index_t* index, /*!< in: clustered index */
420 const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
421 ReadView* view); /*!< in: consistent read view */
422/*********************************************************************//**
423Checks that a non-clustered index record is seen in a consistent read.
424
425NOTE that a non-clustered index page contains so little information on
426its modifications that also in the case false, the present version of
427rec may be the right, but we must check this from the clustered index
428record.
429
430@return true if certainly sees, or false if an earlier version of the
431clustered index record might be needed */
432bool
433lock_sec_rec_cons_read_sees(
434/*========================*/
435 const rec_t* rec, /*!< in: user record which
436 should be read or passed over
437 by a read cursor */
438 const dict_index_t* index, /*!< in: index */
439 const ReadView* view) /*!< in: consistent read view */
440 MY_ATTRIBUTE((warn_unused_result));
441/*********************************************************************//**
442Locks the specified database table in the mode given. If the lock cannot
443be granted immediately, the query thread is put to wait.
444@return DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK */
445dberr_t
446lock_table(
447/*=======*/
448 ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG bit is set,
449 does nothing */
450 dict_table_t* table, /*!< in/out: database table
451 in dictionary cache */
452 lock_mode mode, /*!< in: lock mode */
453 que_thr_t* thr) /*!< in: query thread */
454 MY_ATTRIBUTE((warn_unused_result));
455/*********************************************************************//**
456Creates a table IX lock object for a resurrected transaction. */
457void
458lock_table_ix_resurrect(
459/*====================*/
460 dict_table_t* table, /*!< in/out: table */
461 trx_t* trx); /*!< in/out: transaction */
462
463/** Sets a lock on a table based on the given mode.
464@param[in] table table to lock
465@param[in,out] trx transaction
466@param[in] mode LOCK_X or LOCK_S
467@return error code or DB_SUCCESS. */
468dberr_t
469lock_table_for_trx(
470 dict_table_t* table,
471 trx_t* trx,
472 enum lock_mode mode)
473 MY_ATTRIBUTE((nonnull, warn_unused_result));
474
475/*************************************************************//**
476Removes a granted record lock of a transaction from the queue and grants
477locks to other transactions waiting in the queue if they now are entitled
478to a lock. */
479void
480lock_rec_unlock(
481/*============*/
482 trx_t* trx, /*!< in/out: transaction that has
483 set a record lock */
484 const buf_block_t* block, /*!< in: buffer block containing rec */
485 const rec_t* rec, /*!< in: record */
486 lock_mode lock_mode);/*!< in: LOCK_S or LOCK_X */
487/*********************************************************************//**
488Releases a transaction's locks, and releases possible other transactions
489waiting because of these locks. Change the state of the transaction to
490TRX_STATE_COMMITTED_IN_MEMORY. */
491void
492lock_trx_release_locks(
493/*===================*/
494 trx_t* trx); /*!< in/out: transaction */
495
496/*********************************************************************//**
497Calculates the fold value of a page file address: used in inserting or
498searching for a lock in the hash table.
499@return folded value */
500UNIV_INLINE
501ulint
502lock_rec_fold(
503/*==========*/
504 ulint space, /*!< in: space */
505 ulint page_no)/*!< in: page number */
506 MY_ATTRIBUTE((const));
507/*********************************************************************//**
508Calculates the hash value of a page file address: used in inserting or
509searching for a lock in the hash table.
510@return hashed value */
511UNIV_INLINE
512unsigned
513lock_rec_hash(
514/*==========*/
515 ulint space, /*!< in: space */
516 ulint page_no);/*!< in: page number */
517
518/*************************************************************//**
519Get the lock hash table */
520UNIV_INLINE
521hash_table_t*
522lock_hash_get(
523/*==========*/
524 ulint mode); /*!< in: lock mode */
525
526/**********************************************************************//**
527Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
528if none found.
529@return bit index == heap number of the record, or ULINT_UNDEFINED if
530none found */
531ulint
532lock_rec_find_set_bit(
533/*==================*/
534 const lock_t* lock); /*!< in: record lock with at least one
535 bit set */
536
537/*********************************************************************//**
538Checks if a lock request lock1 has to wait for request lock2.
539@return whether lock1 has to wait for lock2 to be removed */
540bool
541lock_has_to_wait(
542/*=============*/
543 const lock_t* lock1, /*!< in: waiting lock */
544 const lock_t* lock2); /*!< in: another lock; NOTE that it is
545 assumed that this has a lock bit set
546 on the same record as in lock1 if the
547 locks are record locks */
548/*********************************************************************//**
549Reports that a transaction id is insensible, i.e., in the future. */
550void
551lock_report_trx_id_insanity(
552/*========================*/
553 trx_id_t trx_id, /*!< in: trx id */
554 const rec_t* rec, /*!< in: user record */
555 dict_index_t* index, /*!< in: index */
556 const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */
557 trx_id_t max_trx_id); /*!< in: trx_sys.get_max_trx_id() */
558/*********************************************************************//**
559Prints info of locks for all transactions.
560@return FALSE if not able to obtain lock mutex and exits without
561printing info */
562ibool
563lock_print_info_summary(
564/*====================*/
565 FILE* file, /*!< in: file where to print */
566 ibool nowait) /*!< in: whether to wait for the lock mutex */
567 MY_ATTRIBUTE((warn_unused_result));
568
569/** Prints transaction lock wait and MVCC state.
570@param[in,out] file file where to print
571@param[in] trx transaction */
572void
573lock_trx_print_wait_and_mvcc_state(
574 FILE* file,
575 const trx_t* trx);
576
577/*********************************************************************//**
578Prints info of locks for each transaction. This function assumes that the
579caller holds the lock mutex and more importantly it will release the lock
580mutex on behalf of the caller. (This should be fixed in the future). */
581void
582lock_print_info_all_transactions(
583/*=============================*/
584 FILE* file); /*!< in: file where to print */
585/*********************************************************************//**
586Return approximate number or record locks (bits set in the bitmap) for
587this transaction. Since delete-marked records may be removed, the
588record count will not be precise.
589The caller must be holding lock_sys.mutex. */
590ulint
591lock_number_of_rows_locked(
592/*=======================*/
593 const trx_lock_t* trx_lock) /*!< in: transaction locks */
594 MY_ATTRIBUTE((warn_unused_result));
595
596/*********************************************************************//**
597Return the number of table locks for a transaction.
598The caller must be holding lock_sys.mutex. */
599ulint
600lock_number_of_tables_locked(
601/*=========================*/
602 const trx_lock_t* trx_lock) /*!< in: transaction locks */
603 MY_ATTRIBUTE((warn_unused_result));
604
605/*******************************************************************//**
606Gets the type of a lock. Non-inline version for using outside of the
607lock module.
608@return LOCK_TABLE or LOCK_REC */
609ulint
610lock_get_type(
611/*==========*/
612 const lock_t* lock); /*!< in: lock */
613
614/*******************************************************************//**
615Gets the trx of the lock. Non-inline version for using outside of the
616lock module.
617@return trx_t* */
618UNIV_INTERN
619trx_t*
620lock_get_trx(
621/*=========*/
622 const lock_t* lock); /*!< in: lock */
623
624/*******************************************************************//**
625Gets the id of the transaction owning a lock.
626@return transaction id */
627trx_id_t
628lock_get_trx_id(
629/*============*/
630 const lock_t* lock); /*!< in: lock */
631
632/*******************************************************************//**
633Gets the mode of a lock in a human readable string.
634The string should not be free()'d or modified.
635@return lock mode */
636const char*
637lock_get_mode_str(
638/*==============*/
639 const lock_t* lock); /*!< in: lock */
640
641/*******************************************************************//**
642Gets the type of a lock in a human readable string.
643The string should not be free()'d or modified.
644@return lock type */
645const char*
646lock_get_type_str(
647/*==============*/
648 const lock_t* lock); /*!< in: lock */
649
650/*******************************************************************//**
651Gets the id of the table on which the lock is.
652@return id of the table */
653table_id_t
654lock_get_table_id(
655/*==============*/
656 const lock_t* lock); /*!< in: lock */
657
658/** Determine which table a lock is associated with.
659@param[in] lock the lock
660@return name of the table */
661const table_name_t&
662lock_get_table_name(
663 const lock_t* lock);
664
665/*******************************************************************//**
666For a record lock, gets the index on which the lock is.
667@return index */
668const dict_index_t*
669lock_rec_get_index(
670/*===============*/
671 const lock_t* lock); /*!< in: lock */
672
673/*******************************************************************//**
674For a record lock, gets the name of the index on which the lock is.
675The string should not be free()'d or modified.
676@return name of the index */
677const char*
678lock_rec_get_index_name(
679/*====================*/
680 const lock_t* lock); /*!< in: lock */
681
682/*******************************************************************//**
683For a record lock, gets the tablespace number on which the lock is.
684@return tablespace number */
685ulint
686lock_rec_get_space_id(
687/*==================*/
688 const lock_t* lock); /*!< in: lock */
689
690/*******************************************************************//**
691For a record lock, gets the page number on which the lock is.
692@return page number */
693ulint
694lock_rec_get_page_no(
695/*=================*/
696 const lock_t* lock); /*!< in: lock */
697/*******************************************************************//**
698Check if there are any locks (table or rec) against table.
699@return TRUE if locks exist */
700bool
701lock_table_has_locks(
702/*=================*/
703 const dict_table_t* table); /*!< in: check if there are any locks
704 held on records in this table or on the
705 table itself */
706
707/*********************************************************************//**
708A thread which wakes up threads whose lock wait may have lasted too long.
709@return a dummy parameter */
710extern "C"
711os_thread_ret_t
712DECLARE_THREAD(lock_wait_timeout_thread)(
713/*=====================================*/
714 void* arg); /*!< in: a dummy parameter required by
715 os_thread_create */
716
717/********************************************************************//**
718Releases a user OS thread waiting for a lock to be released, if the
719thread is already suspended. */
720void
721lock_wait_release_thread_if_suspended(
722/*==================================*/
723 que_thr_t* thr); /*!< in: query thread associated with the
724 user OS thread */
725
726/***************************************************************//**
727Puts a user OS thread to wait for a lock to be released. If an error
728occurs during the wait trx->error_state associated with thr is
729!= DB_SUCCESS when we return. DB_LOCK_WAIT_TIMEOUT and DB_DEADLOCK
730are possible errors. DB_DEADLOCK is returned if selective deadlock
731resolution chose this transaction as a victim. */
732void
733lock_wait_suspend_thread(
734/*=====================*/
735 que_thr_t* thr); /*!< in: query thread associated with the
736 user OS thread */
737/*********************************************************************//**
738Unlocks AUTO_INC type locks that were possibly reserved by a trx. This
739function should be called at the the end of an SQL statement, by the
740connection thread that owns the transaction (trx->mysql_thd). */
741void
742lock_unlock_table_autoinc(
743/*======================*/
744 trx_t* trx); /*!< in/out: transaction */
745/*********************************************************************//**
746Check whether the transaction has already been rolled back because it
747was selected as a deadlock victim, or if it has to wait then cancel
748the wait lock.
749@return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */
750dberr_t
751lock_trx_handle_wait(
752/*=================*/
753 trx_t* trx); /*!< in/out: trx lock state */
754/*********************************************************************//**
755Get the number of locks on a table.
756@return number of locks */
757ulint
758lock_table_get_n_locks(
759/*===================*/
760 const dict_table_t* table); /*!< in: table */
761/*******************************************************************//**
762Initialise the trx lock list. */
763void
764lock_trx_lock_list_init(
765/*====================*/
766 trx_lock_list_t* lock_list); /*!< List to initialise */
767
768/*******************************************************************//**
769Set the lock system timeout event. */
770void
771lock_set_timeout_event();
772/*====================*/
773/*********************************************************************//**
774Checks that a transaction id is sensible, i.e., not in the future.
775@return true if ok */
776bool
777lock_check_trx_id_sanity(
778/*=====================*/
779 trx_id_t trx_id, /*!< in: trx id */
780 const rec_t* rec, /*!< in: user record */
781 dict_index_t* index, /*!< in: index */
782 const ulint* offsets); /*!< in: rec_get_offsets(rec, index) */
783#ifdef UNIV_DEBUG
784/*******************************************************************//**
785Check if the transaction holds any locks on the sys tables
786or its records.
787@return the strongest lock found on any sys table or 0 for none */
788const lock_t*
789lock_trx_has_sys_table_locks(
790/*=========================*/
791 const trx_t* trx) /*!< in: transaction to check */
792 MY_ATTRIBUTE((warn_unused_result));
793
794/*******************************************************************//**
795Check if the transaction holds an exclusive lock on a record.
796@return whether the locks are held */
797bool
798lock_trx_has_rec_x_lock(
799/*====================*/
800 const trx_t* trx, /*!< in: transaction to check */
801 const dict_table_t* table, /*!< in: table to check */
802 const buf_block_t* block, /*!< in: buffer block of the record */
803 ulint heap_no)/*!< in: record heap number */
804 MY_ATTRIBUTE((warn_unused_result));
805#endif /* UNIV_DEBUG */
806
807/**
808Allocate cached locks for the transaction.
809@param trx allocate cached record locks for this transaction */
810void
811lock_trx_alloc_locks(trx_t* trx);
812
813/** Lock modes and types */
814/* @{ */
815#define LOCK_MODE_MASK 0xFUL /*!< mask used to extract mode from the
816 type_mode field in a lock */
817/** Lock types */
818/* @{ */
819#define LOCK_TABLE 16U /*!< table lock */
820#define LOCK_REC 32U /*!< record lock */
821#define LOCK_TYPE_MASK 0xF0UL /*!< mask used to extract lock type from the
822 type_mode field in a lock */
823#if LOCK_MODE_MASK & LOCK_TYPE_MASK
824# error "LOCK_MODE_MASK & LOCK_TYPE_MASK"
825#endif
826
827#define LOCK_WAIT 256U /*!< Waiting lock flag; when set, it
828 means that the lock has not yet been
829 granted, it is just waiting for its
830 turn in the wait queue */
831/* Precise modes */
832#define LOCK_ORDINARY 0 /*!< this flag denotes an ordinary
833 next-key lock in contrast to LOCK_GAP
834 or LOCK_REC_NOT_GAP */
835#define LOCK_GAP 512U /*!< when this bit is set, it means that the
836 lock holds only on the gap before the record;
837 for instance, an x-lock on the gap does not
838 give permission to modify the record on which
839 the bit is set; locks of this type are created
840 when records are removed from the index chain
841 of records */
842#define LOCK_REC_NOT_GAP 1024U /*!< this bit means that the lock is only on
843 the index record and does NOT block inserts
844 to the gap before the index record; this is
845 used in the case when we retrieve a record
846 with a unique key, and is also used in
847 locking plain SELECTs (not part of UPDATE
848 or DELETE) when the user has set the READ
849 COMMITTED isolation level */
850#define LOCK_INSERT_INTENTION 2048U/*!< this bit is set when we place a waiting
851 gap type record lock request in order to let
852 an insert of an index record to wait until
853 there are no conflicting locks by other
854 transactions on the gap; note that this flag
855 remains set when the waiting lock is granted,
856 or if the lock is inherited to a neighboring
857 record */
858#define LOCK_PREDICATE 8192U /*!< Predicate lock */
859#define LOCK_PRDT_PAGE 16384U /*!< Page lock */
860
861
862#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_PREDICATE|LOCK_PRDT_PAGE)&LOCK_MODE_MASK
863# error
864#endif
865#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_PREDICATE|LOCK_PRDT_PAGE)&LOCK_TYPE_MASK
866# error
867#endif
868/* @} */
869
870/** Lock operation struct */
871struct lock_op_t{
872 dict_table_t* table; /*!< table to be locked */
873 lock_mode mode; /*!< lock mode */
874};
875
876typedef ib_mutex_t LockMutex;
877
878/** The lock system struct */
879class lock_sys_t
880{
881 bool m_initialised;
882
883public:
884 MY_ALIGNED(CACHE_LINE_SIZE)
885 LockMutex mutex; /*!< Mutex protecting the
886 locks */
887 hash_table_t* rec_hash; /*!< hash table of the record
888 locks */
889 hash_table_t* prdt_hash; /*!< hash table of the predicate
890 lock */
891 hash_table_t* prdt_page_hash; /*!< hash table of the page
892 lock */
893
894 MY_ALIGNED(CACHE_LINE_SIZE)
895 LockMutex wait_mutex; /*!< Mutex protecting the
896 next two fields */
897 srv_slot_t* waiting_threads; /*!< Array of user threads
898 suspended while waiting for
899 locks within InnoDB, protected
900 by the lock_sys.wait_mutex;
901 os_event_set() and
902 os_event_reset() on
903 waiting_threads[]->event
904 are protected by
905 trx_t::mutex */
906 srv_slot_t* last_slot; /*!< highest slot ever used
907 in the waiting_threads array,
908 protected by
909 lock_sys.wait_mutex */
910
911 ulint n_lock_max_wait_time; /*!< Max wait time */
912
913 os_event_t timeout_event; /*!< An event waited for by
914 lock_wait_timeout_thread.
915 Not protected by a mutex,
916 but the waits are timed.
917 Signaled on shutdown only. */
918
919 bool timeout_thread_active; /*!< True if the timeout thread
920 is running */
921
922
923 /**
924 Constructor.
925
926 Some members may require late initialisation, thus we just mark object as
927 uninitialised. Real initialisation happens in create().
928 */
929 lock_sys_t(): m_initialised(false) {}
930
931
932 bool is_initialised() { return m_initialised; }
933
934
935 /**
936 Creates the lock system at database start.
937
938 @param[in] n_cells number of slots in lock hash table
939 */
940 void create(ulint n_cells);
941
942
943 /**
944 Resize the lock hash table.
945
946 @param[in] n_cells number of slots in lock hash table
947 */
948 void resize(ulint n_cells);
949
950
951 /** Closes the lock system at database shutdown. */
952 void close();
953};
954
955/*********************************************************************//**
956Creates a new record lock and inserts it to the lock queue. Does NOT check
957for deadlocks or lock compatibility!
958@return created lock */
959UNIV_INLINE
960lock_t*
961lock_rec_create(
962/*============*/
963#ifdef WITH_WSREP
964 lock_t* c_lock, /*!< conflicting lock */
965 que_thr_t* thr, /*!< thread owning trx */
966#endif
967 ulint type_mode,/*!< in: lock mode and wait
968 flag, type is ignored and
969 replaced by LOCK_REC */
970 const buf_block_t* block, /*!< in: buffer block containing
971 the record */
972 ulint heap_no,/*!< in: heap number of the record */
973 dict_index_t* index, /*!< in: index of record */
974 trx_t* trx, /*!< in,out: transaction */
975 bool caller_owns_trx_mutex);
976 /*!< in: true if caller owns
977 trx mutex */
978
979/*************************************************************//**
980Removes a record lock request, waiting or granted, from the queue. */
981void
982lock_rec_discard(
983/*=============*/
984 lock_t* in_lock); /*!< in: record lock object: all
985 record locks which are contained
986 in this lock object are removed */
987
988/** Create a new record lock and inserts it to the lock queue,
989without checking for deadlocks or conflicts.
990@param[in] type_mode lock mode and wait flag; type will be replaced
991 with LOCK_REC
992@param[in] space tablespace id
993@param[in] page_no index page number
994@param[in] page R-tree index page, or NULL
995@param[in] heap_no record heap number in the index page
996@param[in] index the index tree
997@param[in,out] trx transaction
998@param[in] holds_trx_mutex whether the caller holds trx->mutex
999@return created lock */
1000lock_t*
1001lock_rec_create_low(
1002#ifdef WITH_WSREP
1003 lock_t* c_lock, /*!< conflicting lock */
1004 que_thr_t* thr, /*!< thread owning trx */
1005#endif
1006 ulint type_mode,
1007 ulint space,
1008 ulint page_no,
1009 const page_t* page,
1010 ulint heap_no,
1011 dict_index_t* index,
1012 trx_t* trx,
1013 bool holds_trx_mutex);
1014/** Enqueue a waiting request for a lock which cannot be granted immediately.
1015Check for deadlocks.
1016@param[in] type_mode the requested lock mode (LOCK_S or LOCK_X)
1017 possibly ORed with LOCK_GAP or
1018 LOCK_REC_NOT_GAP, ORed with
1019 LOCK_INSERT_INTENTION if this
1020 waiting lock request is set
1021 when performing an insert of
1022 an index record
1023@param[in] block leaf page in the index
1024@param[in] heap_no record heap number in the block
1025@param[in] index index tree
1026@param[in,out] thr query thread
1027@param[in] prdt minimum bounding box (spatial index)
1028@retval DB_LOCK_WAIT if the waiting lock was enqueued
1029@retval DB_DEADLOCK if this transaction was chosen as the victim
1030@retval DB_SUCCESS_LOCKED_REC if the other transaction was chosen as a victim
1031 (or it happened to commit) */
1032dberr_t
1033lock_rec_enqueue_waiting(
1034#ifdef WITH_WSREP
1035 lock_t* c_lock, /*!< conflicting lock */
1036#endif
1037 ulint type_mode,
1038 const buf_block_t* block,
1039 ulint heap_no,
1040 dict_index_t* index,
1041 que_thr_t* thr,
1042 lock_prdt_t* prdt);
1043/*************************************************************//**
1044Moves the explicit locks on user records to another page if a record
1045list start is moved to another page. */
1046void
1047lock_rtr_move_rec_list(
1048/*===================*/
1049 const buf_block_t* new_block, /*!< in: index page to
1050 move to */
1051 const buf_block_t* block, /*!< in: index page */
1052 rtr_rec_move_t* rec_move, /*!< in: recording records
1053 moved */
1054 ulint num_move); /*!< in: num of rec to move */
1055
1056/*************************************************************//**
1057Removes record lock objects set on an index page which is discarded. This
1058function does not move locks, or check for waiting locks, therefore the
1059lock bitmaps must already be reset when this function is called. */
1060void
1061lock_rec_free_all_from_discard_page(
1062/*================================*/
1063 const buf_block_t* block); /*!< in: page to be discarded */
1064
1065/** The lock system */
1066extern lock_sys_t lock_sys;
1067
1068/** Test if lock_sys.mutex can be acquired without waiting. */
1069#define lock_mutex_enter_nowait() \
1070 (lock_sys.mutex.trylock(__FILE__, __LINE__))
1071
1072/** Test if lock_sys.mutex is owned. */
1073#define lock_mutex_own() (lock_sys.mutex.is_owned())
1074
1075/** Acquire the lock_sys.mutex. */
1076#define lock_mutex_enter() do { \
1077 mutex_enter(&lock_sys.mutex); \
1078} while (0)
1079
1080/** Release the lock_sys.mutex. */
1081#define lock_mutex_exit() do { \
1082 lock_sys.mutex.exit(); \
1083} while (0)
1084
1085/** Test if lock_sys.wait_mutex is owned. */
1086#define lock_wait_mutex_own() (lock_sys.wait_mutex.is_owned())
1087
1088/** Acquire the lock_sys.wait_mutex. */
1089#define lock_wait_mutex_enter() do { \
1090 mutex_enter(&lock_sys.wait_mutex); \
1091} while (0)
1092
1093/** Release the lock_sys.wait_mutex. */
1094#define lock_wait_mutex_exit() do { \
1095 lock_sys.wait_mutex.exit(); \
1096} while (0)
1097
1098#ifdef WITH_WSREP
1099/*********************************************************************//**
1100Cancels a waiting lock request and releases possible other transactions
1101waiting behind it. */
1102UNIV_INTERN
1103void
1104lock_cancel_waiting_and_release(
1105/*============================*/
1106 lock_t* lock); /*!< in/out: waiting lock request */
1107
1108/*******************************************************************//**
1109Get lock mode and table/index name
1110@return string containing lock info */
1111std::string
1112lock_get_info(
1113 const lock_t*);
1114
1115/*******************************************************************//**
1116@return whether wsrep_on is true on trx->mysql_thd*/
1117#define wsrep_on_trx(trx) ((trx)->mysql_thd && wsrep_on((trx)->mysql_thd))
1118
1119#endif /* WITH_WSREP */
1120
1121#include "lock0lock.ic"
1122
1123#endif
1124