1
/******************************************************
2
The transaction lock system
6
Created 5/7/1996 Heikki Tuuri
7
*******************************************************/
13
#include "trx0types.h"
14
#include "rem0types.h"
15
#include "dict0types.h"
16
#include "que0types.h"
17
#include "page0types.h"
18
#include "lock0types.h"
19
#include "read0types.h"
20
#include "hash0hash.h"
23
extern ibool lock_print_waits;
24
#endif /* UNIV_DEBUG */
25
/* Buffer for storing information about the most recent deadlock error */
26
extern FILE* lock_latest_err_file;
28
/*************************************************************************
29
Gets the size of a lock struct. */
34
/* out: size in bytes */
35
/*************************************************************************
36
Creates the lock system at database start. */
41
ulint n_cells); /* in: number of slots in lock hash table */
42
/*************************************************************************
43
Checks if some transaction has an implicit x-lock on a record in a secondary
47
lock_sec_rec_some_has_impl_off_kernel(
48
/*==================================*/
49
/* out: transaction which has the x-lock, or
51
rec_t* rec, /* in: user record */
52
dict_index_t* index, /* in: secondary index */
53
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
54
/*************************************************************************
55
Checks if some transaction has an implicit x-lock on a record in a clustered
59
lock_clust_rec_some_has_impl(
60
/*=========================*/
61
/* out: transaction which has the x-lock, or
63
rec_t* rec, /* in: user record */
64
dict_index_t* index, /* in: clustered index */
65
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
66
/*****************************************************************
67
Makes a record to inherit the locks of another record as gap type
68
locks, but does not reset the lock bits of the other record. Also
69
waiting lock requests on rec are inherited as GRANTED gap locks. */
72
lock_rec_inherit_to_gap(
73
/*====================*/
74
rec_t* heir, /* in: record which inherits */
75
rec_t* rec); /* in: record from which inherited; does NOT reset
76
the locks on this record */
77
/*****************************************************************
78
Updates the lock table when we have reorganized a page. NOTE: we copy
79
also the locks set on the infimum of the page; the infimum may carry
80
locks if an update of a record is occurring on the page, and its locks
81
were temporarily stored on the infimum. */
84
lock_move_reorganize_page(
85
/*======================*/
86
page_t* page, /* in: old index page */
87
page_t* new_page); /* in: reorganized page */
88
/*****************************************************************
89
Moves the explicit locks on user records to another page if a record
90
list end is moved to another page. */
93
lock_move_rec_list_end(
94
/*===================*/
95
page_t* new_page, /* in: index page to move to */
96
page_t* page, /* in: index page */
97
rec_t* rec); /* in: record on page: this is the
99
/*****************************************************************
100
Moves the explicit locks on user records to another page if a record
101
list start is moved to another page. */
104
lock_move_rec_list_start(
105
/*=====================*/
106
page_t* new_page, /* in: index page to move to */
107
page_t* page, /* in: index page */
108
rec_t* rec, /* in: record on page: this is the
109
first record NOT copied */
110
rec_t* old_end); /* in: old previous-to-last record on
111
new_page before the records were copied */
112
/*****************************************************************
113
Updates the lock table when a page is split to the right. */
116
lock_update_split_right(
117
/*====================*/
118
page_t* right_page, /* in: right page */
119
page_t* left_page); /* in: left page */
120
/*****************************************************************
121
Updates the lock table when a page is merged to the right. */
124
lock_update_merge_right(
125
/*====================*/
126
rec_t* orig_succ, /* in: original successor of infimum
127
on the right page before merge */
128
page_t* left_page); /* in: merged index page which will be
130
/*****************************************************************
131
Updates the lock table when the root page is copied to another in
132
btr_root_raise_and_insert. Note that we leave lock structs on the
133
root page, even though they do not make sense on other than leaf
134
pages: the reason is that in a pessimistic update the infimum record
135
of the root page will act as a dummy carrier of the locks of the record
139
lock_update_root_raise(
140
/*===================*/
141
page_t* new_page, /* in: index page to which copied */
142
page_t* root); /* in: root page */
143
/*****************************************************************
144
Updates the lock table when a page is copied to another and the original page
145
is removed from the chain of leaf pages, except if page is the root! */
148
lock_update_copy_and_discard(
149
/*=========================*/
150
page_t* new_page, /* in: index page to which copied */
151
page_t* page); /* in: index page; NOT the root! */
152
/*****************************************************************
153
Updates the lock table when a page is split to the left. */
156
lock_update_split_left(
157
/*===================*/
158
page_t* right_page, /* in: right page */
159
page_t* left_page); /* in: left page */
160
/*****************************************************************
161
Updates the lock table when a page is merged to the left. */
164
lock_update_merge_left(
165
/*===================*/
166
page_t* left_page, /* in: left page to which merged */
167
rec_t* orig_pred, /* in: original predecessor of supremum
168
on the left page before merge */
169
page_t* right_page); /* in: merged index page which will be
171
/*****************************************************************
172
Resets the original locks on heir and replaces them with gap type locks
173
inherited from rec. */
176
lock_rec_reset_and_inherit_gap_locks(
177
/*=================================*/
178
rec_t* heir, /* in: heir record */
179
rec_t* rec); /* in: record */
180
/*****************************************************************
181
Updates the lock table when a page is discarded. */
186
rec_t* heir, /* in: record which will inherit the locks */
187
page_t* page); /* in: index page which will be discarded */
188
/*****************************************************************
189
Updates the lock table when a new user record is inserted. */
194
rec_t* rec); /* in: the inserted record */
195
/*****************************************************************
196
Updates the lock table when a record is removed. */
201
rec_t* rec); /* in: the record to be removed */
202
/*************************************************************************
203
Stores on the page infimum record the explicit locks of another record.
204
This function is used to store the lock state of a record when it is
205
updated and the size of the record changes in the update. The record
206
is in such an update moved, perhaps to another page. The infimum record
207
acts as a dummy carrier record, taking care of lock releases while the
208
actual record is being moved. */
211
lock_rec_store_on_page_infimum(
212
/*===========================*/
213
page_t* page, /* in: page containing the record */
214
rec_t* rec); /* in: record whose lock state is stored
215
on the infimum record of the same page; lock
216
bits are reset on the record */
217
/*************************************************************************
218
Restores the state of explicit lock requests on a single record, where the
219
state was stored on the infimum of the page. */
222
lock_rec_restore_from_page_infimum(
223
/*===============================*/
224
rec_t* rec, /* in: record whose lock state is restored */
225
page_t* page); /* in: page (rec is not necessarily on this page)
226
whose infimum stored the lock state; lock bits are
227
reset on the infimum */
228
/*************************************************************************
229
Returns TRUE if there are explicit record locks on a page. */
232
lock_rec_expl_exist_on_page(
233
/*========================*/
234
/* out: TRUE if there are explicit record locks on
236
ulint space, /* in: space id */
237
ulint page_no);/* in: page number */
238
/*************************************************************************
239
Checks if locks of other transactions prevent an immediate insert of
240
a record. If they do, first tests if the query thread should anyway
241
be suspended for some reason; if not, then puts the transaction and
242
the query thread to the lock wait state and inserts a waiting request
243
for a gap x-lock to the lock queue. */
246
lock_rec_insert_check_and_lock(
247
/*===========================*/
248
/* out: DB_SUCCESS, DB_LOCK_WAIT,
249
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
250
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
252
rec_t* rec, /* in: record after which to insert */
253
dict_index_t* index, /* in: index */
254
que_thr_t* thr, /* in: query thread */
255
ibool* inherit);/* out: set to TRUE if the new inserted
256
record maybe should inherit LOCK_GAP type
257
locks from the successor record */
258
/*************************************************************************
259
Checks if locks of other transactions prevent an immediate modify (update,
260
delete mark, or delete unmark) of a clustered index record. If they do,
261
first tests if the query thread should anyway be suspended for some
262
reason; if not, then puts the transaction and the query thread to the
263
lock wait state and inserts a waiting request for a record x-lock to the
267
lock_clust_rec_modify_check_and_lock(
268
/*=================================*/
269
/* out: DB_SUCCESS, DB_LOCK_WAIT,
270
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
271
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
273
rec_t* rec, /* in: record which should be modified */
274
dict_index_t* index, /* in: clustered index */
275
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
276
que_thr_t* thr); /* in: query thread */
277
/*************************************************************************
278
Checks if locks of other transactions prevent an immediate modify
279
(delete mark or delete unmark) of a secondary index record. */
282
lock_sec_rec_modify_check_and_lock(
283
/*===============================*/
284
/* out: DB_SUCCESS, DB_LOCK_WAIT,
285
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
286
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
288
rec_t* rec, /* in: record which should be modified;
289
NOTE: as this is a secondary index, we
290
always have to modify the clustered index
291
record first: see the comment below */
292
dict_index_t* index, /* in: secondary index */
293
que_thr_t* thr); /* in: query thread */
294
/*************************************************************************
295
Like the counterpart for a clustered index below, but now we read a
296
secondary index record. */
299
lock_sec_rec_read_check_and_lock(
300
/*=============================*/
301
/* out: DB_SUCCESS, DB_LOCK_WAIT,
302
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
303
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
305
rec_t* rec, /* in: user record or page supremum record
306
which should be read or passed over by a read
308
dict_index_t* index, /* in: secondary index */
309
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
310
ulint mode, /* in: mode of the lock which the read cursor
311
should set on records: LOCK_S or LOCK_X; the
312
latter is possible in SELECT FOR UPDATE */
313
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
315
que_thr_t* thr); /* in: query thread */
316
/*************************************************************************
317
Checks if locks of other transactions prevent an immediate read, or passing
318
over by a read cursor, of a clustered index record. If they do, first tests
319
if the query thread should anyway be suspended for some reason; if not, then
320
puts the transaction and the query thread to the lock wait state and inserts a
321
waiting request for a record lock to the lock queue. Sets the requested mode
322
lock on the record. */
325
lock_clust_rec_read_check_and_lock(
326
/*===============================*/
327
/* out: DB_SUCCESS, DB_LOCK_WAIT,
328
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
329
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
331
rec_t* rec, /* in: user record or page supremum record
332
which should be read or passed over by a read
334
dict_index_t* index, /* in: clustered index */
335
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
336
ulint mode, /* in: mode of the lock which the read cursor
337
should set on records: LOCK_S or LOCK_X; the
338
latter is possible in SELECT FOR UPDATE */
339
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
341
que_thr_t* thr); /* in: query thread */
342
/*************************************************************************
343
Checks if locks of other transactions prevent an immediate read, or passing
344
over by a read cursor, of a clustered index record. If they do, first tests
345
if the query thread should anyway be suspended for some reason; if not, then
346
puts the transaction and the query thread to the lock wait state and inserts a
347
waiting request for a record lock to the lock queue. Sets the requested mode
348
lock on the record. This is an alternative version of
349
lock_clust_rec_read_check_and_lock() that does not require the parameter
353
lock_clust_rec_read_check_and_lock_alt(
354
/*===================================*/
355
/* out: DB_SUCCESS, DB_LOCK_WAIT,
356
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
357
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
359
rec_t* rec, /* in: user record or page supremum record
360
which should be read or passed over by a read
362
dict_index_t* index, /* in: clustered index */
363
ulint mode, /* in: mode of the lock which the read cursor
364
should set on records: LOCK_S or LOCK_X; the
365
latter is possible in SELECT FOR UPDATE */
366
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
368
que_thr_t* thr); /* in: query thread */
369
/*************************************************************************
370
Checks that a record is seen in a consistent read. */
373
lock_clust_rec_cons_read_sees(
374
/*==========================*/
375
/* out: TRUE if sees, or FALSE if an earlier
376
version of the record should be retrieved */
377
rec_t* rec, /* in: user record which should be read or
378
passed over by a read cursor */
379
dict_index_t* index, /* in: clustered index */
380
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
381
read_view_t* view); /* in: consistent read view */
382
/*************************************************************************
383
Checks that a non-clustered index record is seen in a consistent read. */
386
lock_sec_rec_cons_read_sees(
387
/*========================*/
388
/* out: TRUE if certainly sees, or FALSE if an
389
earlier version of the clustered index record
390
might be needed: NOTE that a non-clustered
391
index page contains so little information on
392
its modifications that also in the case FALSE,
393
the present version of rec may be the right,
394
but we must check this from the clustered
396
rec_t* rec, /* in: user record which should be read or
397
passed over by a read cursor */
398
dict_index_t* index, /* in: non-clustered index */
399
read_view_t* view); /* in: consistent read view */
400
/*************************************************************************
401
Locks the specified database table in the mode given. If the lock cannot
402
be granted immediately, the query thread is put to wait. */
407
/* out: DB_SUCCESS, DB_LOCK_WAIT,
408
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
409
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
411
dict_table_t* table, /* in: database table in dictionary cache */
412
ulint mode, /* in: lock mode */
413
que_thr_t* thr); /* in: query thread */
414
/*************************************************************************
415
Checks if there are any locks set on the table. */
420
/* out: TRUE if there are lock(s) */
421
dict_table_t* table); /* in: database table in dictionary cache */
422
/*****************************************************************
423
Removes a granted record lock of a transaction from the queue and grants
424
locks to other transactions waiting in the queue if they now are entitled
430
trx_t* trx, /* in: transaction that has set a record
432
rec_t* rec, /* in: record */
433
ulint lock_mode); /* in: LOCK_S or LOCK_X */
434
/*************************************************************************
435
Releases a table lock.
436
Releases possible other transactions waiting for this lock. */
441
lock_t* lock); /* in: lock */
442
/*************************************************************************
443
Releases an auto-inc lock a transaction possibly has on a table.
444
Releases possible other transactions waiting for this lock. */
447
lock_table_unlock_auto_inc(
448
/*=======================*/
449
trx_t* trx); /* in: transaction */
450
/*************************************************************************
451
Releases transaction locks, and releases possible other transactions waiting
452
because of these locks. */
455
lock_release_off_kernel(
456
/*====================*/
457
trx_t* trx); /* in: transaction */
458
/*************************************************************************
459
Cancels a waiting lock request and releases possible other transactions
460
waiting behind it. */
463
lock_cancel_waiting_and_release(
464
/*============================*/
465
lock_t* lock); /* in: waiting lock request */
466
/*************************************************************************
467
Resets all locks, both table and record locks, on a table to be dropped.
468
No lock is allowed to be a wait lock. */
471
lock_reset_all_on_table(
472
/*====================*/
473
dict_table_t* table); /* in: table to be dropped */
474
/*************************************************************************
475
Calculates the fold value of a page file address: used in inserting or
476
searching for a lock in the hash table. */
481
/* out: folded value */
482
ulint space, /* in: space */
483
ulint page_no);/* in: page number */
484
/*************************************************************************
485
Calculates the hash value of a page file address: used in inserting or
486
searching for a lock in the hash table. */
491
/* out: hashed value */
492
ulint space, /* in: space */
493
ulint page_no);/* in: page number */
494
/*************************************************************************
495
Gets the source table of an ALTER TABLE transaction. The table must be
496
covered by an IX or IS table lock. */
501
/* out: the source table of transaction,
502
if it is covered by an IX or IS table lock;
503
dest if there is no source table, and
504
NULL if the transaction is locking more than
505
two tables or an inconsistency is found */
506
trx_t* trx, /* in: transaction */
507
dict_table_t* dest, /* in: destination of ALTER TABLE */
508
ulint* mode); /* out: lock mode of the source table */
509
/*************************************************************************
510
Determine if the given table is exclusively "owned" by the given
511
transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
515
lock_is_table_exclusive(
516
/*====================*/
517
/* out: TRUE if table is only locked by trx,
518
with LOCK_IX, and possibly LOCK_AUTO_INC */
519
dict_table_t* table, /* in: table */
520
trx_t* trx); /* in: transaction */
521
/*************************************************************************
522
Checks if a lock request lock1 has to wait for request lock2. */
527
/* out: TRUE if lock1 has to wait for lock2 to be
529
lock_t* lock1, /* in: waiting lock */
530
lock_t* lock2); /* in: another lock; NOTE that it is assumed that this
531
has a lock bit set on the same record as in lock1 if
532
the locks are record locks */
533
/*************************************************************************
534
Checks that a transaction id is sensible, i.e., not in the future. */
537
lock_check_trx_id_sanity(
538
/*=====================*/
539
/* out: TRUE if ok */
540
dulint trx_id, /* in: trx id */
541
rec_t* rec, /* in: user record */
542
dict_index_t* index, /* in: clustered index */
543
const ulint* offsets, /* in: rec_get_offsets(rec, index) */
544
ibool has_kernel_mutex);/* in: TRUE if the caller owns the
546
/*************************************************************************
547
Validates the lock queue on a single record. */
550
lock_rec_queue_validate(
551
/*====================*/
552
/* out: TRUE if ok */
553
rec_t* rec, /* in: record to look at */
554
dict_index_t* index, /* in: index, or NULL if not known */
555
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
556
/*************************************************************************
557
Prints info of a table lock. */
562
FILE* file, /* in: file where to print */
563
lock_t* lock); /* in: table type lock */
564
/*************************************************************************
565
Prints info of a record lock. */
570
FILE* file, /* in: file where to print */
571
lock_t* lock); /* in: record type lock */
572
/*************************************************************************
573
Prints info of locks for all transactions. */
576
lock_print_info_summary(
577
/*====================*/
578
FILE* file); /* in: file where to print */
579
/*************************************************************************
580
Prints info of locks for each transaction. */
583
lock_print_info_all_transactions(
584
/*=============================*/
585
FILE* file); /* in: file where to print */
586
/*************************************************************************
587
Validates the lock queue on a table. */
590
lock_table_queue_validate(
591
/*======================*/
592
/* out: TRUE if ok */
593
dict_table_t* table); /* in: table */
594
/*************************************************************************
595
Validates the record lock queues on a page. */
598
lock_rec_validate_page(
599
/*===================*/
600
/* out: TRUE if ok */
601
ulint space, /* in: space id */
602
ulint page_no);/* in: page number */
603
/*************************************************************************
604
Validates the lock system. */
609
/* out: TRUE if ok */
610
/*************************************************************************
611
Return approximate number or record locks (bits set in the bitmap) for
612
this transaction. Since delete-marked records may be removed, the
613
record count will not be precise. */
616
lock_number_of_rows_locked(
617
/*=======================*/
618
trx_t* trx); /* in: transaction */
620
/* The lock system */
621
extern lock_sys_t* lock_sys;
623
/* Lock modes and types */
625
#define LOCK_NONE 0 /* this flag is used elsewhere to note
627
#define LOCK_IS 2 /* intention shared */
628
#define LOCK_IX 3 /* intention exclusive */
629
#define LOCK_S 4 /* shared */
630
#define LOCK_X 5 /* exclusive */
631
#define LOCK_AUTO_INC 6 /* locks the auto-inc counter of a table
632
in an exclusive mode */
633
#define LOCK_MODE_MASK 0xFUL /* mask used to extract mode from the
634
type_mode field in a lock */
636
#define LOCK_TABLE 16 /* these type values should be so high that */
637
#define LOCK_REC 32 /* they can be ORed to the lock mode */
638
#define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the
639
type_mode field in a lock */
640
/* Waiting lock flag */
641
#define LOCK_WAIT 256 /* this wait bit should be so high that
642
it can be ORed to the lock mode and type;
643
when this bit is set, it means that the
644
lock has not yet been granted, it is just
645
waiting for its turn in the wait queue */
647
#define LOCK_ORDINARY 0 /* this flag denotes an ordinary next-key lock
648
in contrast to LOCK_GAP or LOCK_REC_NOT_GAP */
649
#define LOCK_GAP 512 /* this gap bit should be so high that
650
it can be ORed to the other flags;
651
when this bit is set, it means that the
652
lock holds only on the gap before the record;
653
for instance, an x-lock on the gap does not
654
give permission to modify the record on which
655
the bit is set; locks of this type are created
656
when records are removed from the index chain
658
#define LOCK_REC_NOT_GAP 1024 /* this bit means that the lock is only on
659
the index record and does NOT block inserts
660
to the gap before the index record; this is
661
used in the case when we retrieve a record
662
with a unique key, and is also used in
663
locking plain SELECTs (not part of UPDATE
664
or DELETE) when the user has set the READ
665
COMMITTED isolation level */
666
#define LOCK_INSERT_INTENTION 2048 /* this bit is set when we place a waiting
667
gap type record lock request in order to let
668
an insert of an index record to wait until
669
there are no conflicting locks by other
670
transactions on the gap; note that this flag
671
remains set when the waiting lock is granted,
672
or if the lock is inherited to a neighboring
675
/* When lock bits are reset, the following flags are available: */
676
#define LOCK_RELEASE_WAIT 1
677
#define LOCK_NOT_RELEASE_WAIT 2
679
/* Lock operation struct */
680
typedef struct lock_op_struct lock_op_t;
681
struct lock_op_struct{
682
dict_table_t* table; /* table to be locked */
683
ulint mode; /* lock mode */
686
#define LOCK_OP_START 1
687
#define LOCK_OP_COMPLETE 2
689
/* The lock system struct */
690
struct lock_sys_struct{
691
hash_table_t* rec_hash; /* hash table of the record locks */
694
/* The lock system */
695
extern lock_sys_t* lock_sys;
699
#include "lock0lock.ic"