1
/*****************************************************************************
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15
Place, Suite 330, Boston, MA 02111-1307 USA
17
*****************************************************************************/
19
/**************************************************//**
20
@file lock/lock0lock.c
21
The transaction lock system
23
Created 5/7/1996 Heikki Tuuri
24
*******************************************************/
26
#define LOCK_MODULE_IMPLEMENTATION
28
#include "lock0lock.h"
29
#include "lock0priv.h"
32
#include "lock0lock.ic"
33
#include "lock0priv.ic"
36
#include "ha_prototypes.h"
38
#include "trx0purge.h"
42
/* Restricts the length of search we will do in the waits-for
43
graph of transactions */
44
#define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
46
/* Restricts the recursion depth of the search we will do in the waits-for
47
graph of transactions */
48
#define LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK 200
50
/* When releasing transaction locks, this specifies how often we release
51
the kernel mutex for a moment to give also others access to it */
53
#define LOCK_RELEASE_KERNEL_INTERVAL 1000
55
/* Safety margin when creating a new record lock: this many extra records
56
can be inserted to the page without need to create a lock with a bigger
59
#define LOCK_PAGE_BITMAP_MARGIN 64
61
/* An explicit record lock affects both the record and the gap before it.
62
An implicit x-lock does not affect the gap, it only locks the index
63
record from read or update.
65
If a transaction has modified or inserted an index record, then
66
it owns an implicit x-lock on the record. On a secondary index record,
67
a transaction has an implicit x-lock also if it has modified the
68
clustered index record, the max trx id of the page where the secondary
69
index record resides is >= trx id of the transaction (or database recovery
70
is running), and there are no explicit non-gap lock requests on the
71
secondary index record.
73
This complicated definition for a secondary index comes from the
74
implementation: we want to be able to determine if a secondary index
75
record has an implicit x-lock, just by looking at the present clustered
76
index record, not at the historical versions of the record. The
77
complicated definition can be explained to the user so that there is
78
nondeterminism in the access path when a query is answered: we may,
79
or may not, access the clustered index record and thus may, or may not,
80
bump into an x-lock set there.
82
Different transaction can have conflicting locks set on the gap at the
83
same time. The locks on the gap are purely inhibitive: an insert cannot
84
be made, or a select cursor may have to wait if a different transaction
85
has a conflicting lock on the gap. An x-lock on the gap does not give
86
the right to insert into the gap.
88
An explicit lock can be placed on a user record or the supremum record of
89
a page. The locks on the supremum record are always thought to be of the gap
90
type, though the gap bit is not set. When we perform an update of a record
91
where the size of the record changes, we may temporarily store its explicit
92
locks on the infimum record of the page, though the infimum otherwise never
95
A waiting record lock can also be of the gap type. A waiting lock request
96
can be granted when there is no conflicting mode lock request by another
97
transaction ahead of it in the explicit lock queue.
99
In version 4.0.5 we added yet another explicit lock type: LOCK_REC_NOT_GAP.
100
It only locks the record it is placed on, not the gap before the record.
101
This lock type is necessary to emulate an Oracle-like READ COMMITTED isolation
104
-------------------------------------------------------------------------
105
RULE 1: If there is an implicit x-lock on a record, and there are non-gap
107
lock requests waiting in the queue, then the transaction holding the implicit
108
x-lock also has an explicit non-gap record x-lock. Therefore, as locks are
109
released, we can grant locks to waiting lock requests purely by looking at
110
the explicit lock requests in the queue.
112
RULE 3: Different transactions cannot have conflicting granted non-gap locks
114
on a record at the same time. However, they can have conflicting granted gap
116
RULE 4: If a there is a waiting lock request in a queue, no lock request,
118
gap or not, can be inserted ahead of it in the queue. In record deletes
119
and page splits new gap type locks can be created by the database manager
120
for a transaction, and without rule 4, the waits-for graph of transactions
121
might become cyclic without the database noticing it, as the deadlock check
122
is only performed when a transaction itself requests a lock!
123
-------------------------------------------------------------------------
125
An insert is allowed to a gap if there are no explicit lock requests by
126
other transactions on the next record. It does not matter if these lock
127
requests are granted or waiting, gap bit set or not, with the exception
128
that a gap type request set by another transaction to wait for
129
its turn to do an insert is ignored. On the other hand, an
130
implicit x-lock by another transaction does not prevent an insert, which
131
allows for more concurrency when using an Oracle-style sequence number
132
generator for the primary key with many transactions doing inserts
135
A modify of a record is allowed if the transaction has an x-lock on the
136
record, or if other transactions do not have any non-gap lock requests on the
139
A read of a single user record with a cursor is allowed if the transaction
140
has a non-gap explicit, or an implicit lock on the record, or if the other
141
transactions have no x-lock requests on the record. At a page supremum a
142
read is always allowed.
144
In summary, an implicit lock is seen as a granted x-lock only on the
145
record, not on the gap. An explicit lock with no gap bit set is a lock
146
both on the record and the gap. If the gap bit is set, the lock is only
147
on the gap. Different transaction cannot own conflicting locks on the
148
record at the same time, but they may own conflicting locks on the gap.
149
Granted locks on a record give an access right to the record, but gap type
150
locks just inhibit operations.
152
NOTE: Finding out if some transaction has an implicit x-lock on a secondary
153
index record can be cumbersome. We may have to look at previous versions of
154
the corresponding clustered index record to find out if a delete marked
155
secondary index record was delete marked by an active transaction, not by
158
FACT A: If a transaction has inserted a row, it can delete it any time
159
without need to wait for locks.
161
PROOF: The transaction has an implicit x-lock on every index record inserted
162
for the row, and can thus modify each record without the need to wait. Q.E.D.
164
FACT B: If a transaction has read some result set with a cursor, it can read
165
it again, and retrieves the same result set, if it has not modified the
166
result set in the meantime. Hence, there is no phantom problem. If the
167
biggest record, in the alphabetical order, touched by the cursor is removed,
168
a lock wait may occur, otherwise not.
170
PROOF: When a read cursor proceeds, it sets an s-lock on each user record
171
it passes, and a gap type s-lock on each page supremum. The cursor must
172
wait until it has these locks granted. Then no other transaction can
173
have a granted x-lock on any of the user records, and therefore cannot
174
modify the user records. Neither can any other transaction insert into
175
the gaps which were passed over by the cursor. Page splits and merges,
176
and removal of obsolete versions of records do not affect this, because
177
when a user record or a page supremum is removed, the next record inherits
178
its locks as gap type locks, and therefore blocks inserts to the same gap.
179
Also, if a page supremum is inserted, it inherits its locks from the successor
180
record. When the cursor is positioned again at the start of the result set,
181
the records it will touch on its course are either records it touched
182
during the last pass or new inserted page supremums. It can immediately
183
access all these records, and when it arrives at the biggest record, it
184
notices that the result set is complete. If the biggest record was removed,
185
lock wait can occur because the next record only inherits a gap type lock,
186
and a wait may be needed. Q.E.D. */
188
/* If an index record should be changed or a new inserted, we must check
189
the lock on the record or the next. When a read cursor starts reading,
190
we will set a record level s-lock on each record it passes, except on the
191
initial record on which the cursor is positioned before we start to fetch
192
records. Our index tree search has the convention that the B-tree
193
cursor is positioned BEFORE the first possibly matching record in
194
the search. Optimizations are possible here: if the record is searched
195
on an equality condition to a unique key, we could actually set a special
196
lock on the record, a lock which would not prevent any insert before
197
this record. In the next key locking an x-lock set on a record also
198
prevents inserts just before that record.
199
There are special infimum and supremum records on each page.
200
A supremum record can be locked by a read cursor. This records cannot be
201
updated but the lock prevents insert of a user record to the end of
203
Next key locks will prevent the phantom problem where new rows
204
could appear to SELECT result sets after the select operation has been
205
performed. Prevention of phantoms ensures the serilizability of
207
What should we check if an insert of a new record is wanted?
208
Only the lock on the next record on the same page, because also the
209
supremum record can carry a lock. An s-lock prevents insertion, but
210
what about an x-lock? If it was set by a searched update, then there
211
is implicitly an s-lock, too, and the insert should be prevented.
212
What if our transaction owns an x-lock to the next record, but there is
213
a waiting s-lock request on the next record? If this s-lock was placed
214
by a read cursor moving in the ascending order in the index, we cannot
215
do the insert immediately, because when we finally commit our transaction,
216
the read cursor should see also the new inserted record. So we should
217
move the read cursor backward from the the next record for it to pass over
218
the new inserted record. This move backward may be too cumbersome to
219
implement. If we in this situation just enqueue a second x-lock request
220
for our transaction on the next record, then the deadlock mechanism
221
notices a deadlock between our transaction and the s-lock request
222
transaction. This seems to be an ok solution.
223
We could have the convention that granted explicit record locks,
224
lock the corresponding records from changing, and also lock the gaps
225
before them from inserting. A waiting explicit lock request locks the gap
226
before from inserting. Implicit record x-locks, which we derive from the
227
transaction id in the clustered index record, only lock the record itself
228
from modification, not the gap before it from inserting.
229
How should we store update locks? If the search is done by a unique
230
key, we could just modify the record trx id. Otherwise, we could put a record
231
x-lock on the record. If the update changes ordering fields of the
232
clustered index record, the inserted new record needs no record lock in
233
lock table, the trx id is enough. The same holds for a secondary index
234
record. Searched delete is similar to update.
237
What about waiting lock requests? If a transaction is waiting to make an
238
update to a record which another modified, how does the other transaction
239
know to send the end-lock-wait signal to the waiting transaction? If we have
240
the convention that a transaction may wait for just one lock at a time, how
241
do we preserve it if lock wait ends?
244
Checking the trx id label of a secondary index record. In the case of a
245
modification, not an insert, is this necessary? A secondary index record
246
is modified only by setting or resetting its deleted flag. A secondary index
247
record contains fields to uniquely determine the corresponding clustered
248
index record. A secondary index record is therefore only modified if we
249
also modify the clustered index record, and the trx id checking is done
250
on the clustered index record, before we come to modify the secondary index
251
record. So, in the case of delete marking or unmarking a secondary index
252
record, we do not have to care about trx ids, only the locks in the lock
253
table must be checked. In the case of a select from a secondary index, the
254
trx id is relevant, and in this case we may have to search the clustered
257
PROBLEM: How to update record locks when page is split or merged, or
258
--------------------------------------------------------------------
259
a record is deleted or updated?
260
If the size of fields in a record changes, we perform the update by
261
a delete followed by an insert. How can we retain the locks set or
262
waiting on the record? Because a record lock is indexed in the bitmap
263
by the heap number of the record, when we remove the record from the
264
record list, it is possible still to keep the lock bits. If the page
265
is reorganized, we could make a table of old and new heap numbers,
266
and permute the bitmaps in the locks accordingly. We can add to the
267
table a row telling where the updated record ended. If the update does
268
not require a reorganization of the page, we can simply move the lock
269
bits for the updated record to the position determined by its new heap
270
number (we may have to allocate a new lock, if we run out of the bitmap
272
A more complicated case is the one where the reinsertion of the
273
updated record is done pessimistically, because the structure of the
276
PROBLEM: If a supremum record is removed in a page merge, or a record
277
---------------------------------------------------------------------
278
removed in a purge, what to do to the waiting lock requests? In a split to
279
the right, we just move the lock requests to the new supremum. If a record
280
is removed, we could move the waiting lock request to its inheritor, the
281
next record in the index. But, the next record may already have lock
282
requests on its own queue. A new deadlock check should be made then. Maybe
283
it is easier just to release the waiting transactions. They can then enqueue
284
new lock requests on appropriate records.
286
PROBLEM: When a record is inserted, what locks should it inherit from the
287
-------------------------------------------------------------------------
288
upper neighbor? An insert of a new supremum record in a page split is
289
always possible, but an insert of a new user record requires that the upper
290
neighbor does not have any lock requests by other transactions, granted or
291
waiting, in its lock queue. Solution: We can copy the locks as gap type
292
locks, so that also the waiting locks are transformed to granted gap type
293
locks on the inserted record. */
295
/* LOCK COMPATIBILITY MATRIX
303
* Note that for rows, InnoDB only acquires S or X locks.
304
* For tables, InnoDB normally acquires IS or IX locks.
305
* S or X table locks are only acquired for LOCK TABLES.
306
* Auto-increment (AI) locks are needed because of
307
* statement-level MySQL binlog.
308
* See also lock_mode_compatible().
310
#define LK(a,b) (1 << ((a) * LOCK_NUM + (b)))
311
#define LKS(a,b) LK(a,b) | LK(b,a)
313
/* Define the lock compatibility matrix in a ulint. The first line below
314
defines the diagonal entries. The following lines define the compatibility
315
for LOCK_IX, LOCK_S, and LOCK_AUTO_INC using LKS(), since the matrix
317
#define LOCK_MODE_COMPATIBILITY 0 \
318
| LK(LOCK_IS, LOCK_IS) | LK(LOCK_IX, LOCK_IX) | LK(LOCK_S, LOCK_S) \
319
| LKS(LOCK_IX, LOCK_IS) | LKS(LOCK_IS, LOCK_AUTO_INC) \
320
| LKS(LOCK_S, LOCK_IS) \
321
| LKS(LOCK_AUTO_INC, LOCK_IS) | LKS(LOCK_AUTO_INC, LOCK_IX)
323
/* STRONGER-OR-EQUAL RELATION (mode1=row, mode2=column)
330
* See lock_mode_stronger_or_eq().
333
/* Define the stronger-or-equal lock relation in a ulint. This relation
334
contains all pairs LK(mode1, mode2) where mode1 is stronger than or
336
#define LOCK_MODE_STRONGER_OR_EQ 0 \
337
| LK(LOCK_IS, LOCK_IS) \
338
| LK(LOCK_IX, LOCK_IS) | LK(LOCK_IX, LOCK_IX) \
339
| LK(LOCK_S, LOCK_IS) | LK(LOCK_S, LOCK_S) \
340
| LK(LOCK_AUTO_INC, LOCK_AUTO_INC) \
341
| LK(LOCK_X, LOCK_IS) | LK(LOCK_X, LOCK_IX) | LK(LOCK_X, LOCK_S) \
342
| LK(LOCK_X, LOCK_AUTO_INC) | LK(LOCK_X, LOCK_X)
345
UNIV_INTERN ibool lock_print_waits = FALSE;
347
/*********************************************************************//**
348
Validates the lock system.
349
@return TRUE if ok */
355
/*********************************************************************//**
356
Validates the record lock queues on a page.
357
@return TRUE if ok */
360
lock_rec_validate_page(
361
/*===================*/
362
ulint space, /*!< in: space id */
363
ulint page_no);/*!< in: page number */
365
/* Define the following in order to enable lock_rec_validate_page() checks. */
366
# undef UNIV_DEBUG_LOCK_VALIDATE
367
#endif /* UNIV_DEBUG */
369
/* The lock system */
370
UNIV_INTERN lock_sys_t* lock_sys = NULL;
372
/* We store info on the latest deadlock error to this buffer. InnoDB
373
Monitor will then fetch it and print */
374
UNIV_INTERN ibool lock_deadlock_found = FALSE;
375
UNIV_INTERN FILE* lock_latest_err_file;
377
/* Flags for recursive deadlock search */
378
#define LOCK_VICTIM_IS_START 1
379
#define LOCK_VICTIM_IS_OTHER 2
381
/********************************************************************//**
382
Checks if a lock request results in a deadlock.
383
@return TRUE if a deadlock was detected and we chose trx as a victim;
384
FALSE if no deadlock, or there was a deadlock, but we chose other
385
transaction(s) as victim(s) */
388
lock_deadlock_occurs(
389
/*=================*/
390
lock_t* lock, /*!< in: lock the transaction is requesting */
391
trx_t* trx); /*!< in: transaction */
392
/********************************************************************//**
393
Looks recursively for a deadlock.
394
@return 0 if no deadlock found, LOCK_VICTIM_IS_START if there was a
395
deadlock and we chose 'start' as the victim, LOCK_VICTIM_IS_OTHER if a
396
deadlock was found and we chose some other trx as a victim: we must do
397
the search again in this last case because there may be another
401
lock_deadlock_recursive(
402
/*====================*/
403
trx_t* start, /*!< in: recursion starting point */
404
trx_t* trx, /*!< in: a transaction waiting for a lock */
405
lock_t* wait_lock, /*!< in: the lock trx is waiting to be granted */
406
ulint* cost, /*!< in/out: number of calculation steps thus
407
far: if this exceeds LOCK_MAX_N_STEPS_...
408
we return LOCK_VICTIM_IS_START */
409
ulint depth); /*!< in: recursion depth: if this exceeds
410
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
411
return LOCK_VICTIM_IS_START */
413
/*********************************************************************//**
414
Gets the nth bit of a record lock.
415
@return TRUE if bit set */
418
lock_rec_get_nth_bit(
419
/*=================*/
420
const lock_t* lock, /*!< in: record lock */
421
ulint i) /*!< in: index of the bit */
427
ut_ad(lock_get_type_low(lock) == LOCK_REC);
429
if (i >= lock->un_member.rec_lock.n_bits) {
437
return(1 & ((const byte*) &lock[1])[byte_index] >> bit_index);
440
/*************************************************************************/
442
#define lock_mutex_enter_kernel() mutex_enter(&kernel_mutex)
443
#define lock_mutex_exit_kernel() mutex_exit(&kernel_mutex)
445
/*********************************************************************//**
446
Checks that a transaction id is sensible, i.e., not in the future.
447
@return TRUE if ok */
450
lock_check_trx_id_sanity(
451
/*=====================*/
452
trx_id_t trx_id, /*!< in: trx id */
453
const rec_t* rec, /*!< in: user record */
454
dict_index_t* index, /*!< in: index */
455
const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */
456
ibool has_kernel_mutex)/*!< in: TRUE if the caller owns the
461
ut_ad(rec_offs_validate(rec, index, offsets));
463
if (!has_kernel_mutex) {
464
mutex_enter(&kernel_mutex);
467
/* A sanity check: the trx_id in rec must be smaller than the global
470
if (ut_dulint_cmp(trx_id, trx_sys->max_trx_id) >= 0) {
471
ut_print_timestamp(stderr);
472
fputs(" InnoDB: Error: transaction id associated"
475
rec_print_new(stderr, rec, offsets);
476
fputs("InnoDB: in ", stderr);
477
dict_index_name_print(stderr, NULL, index);
479
"InnoDB: is " TRX_ID_FMT " which is higher than the"
480
" global trx id counter " TRX_ID_FMT "!\n"
481
"InnoDB: The table is corrupt. You have to do"
482
" dump + drop + reimport.\n",
483
TRX_ID_PREP_PRINTF(trx_id),
484
TRX_ID_PREP_PRINTF(trx_sys->max_trx_id));
489
if (!has_kernel_mutex) {
490
mutex_exit(&kernel_mutex);
496
/*********************************************************************//**
497
Checks that a record is seen in a consistent read.
498
@return TRUE if sees, or FALSE if an earlier version of the record
499
should be retrieved */
502
lock_clust_rec_cons_read_sees(
503
/*==========================*/
504
const rec_t* rec, /*!< in: user record which should be read or
505
passed over by a read cursor */
506
dict_index_t* index, /*!< in: clustered index */
507
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
508
read_view_t* view) /*!< in: consistent read view */
512
ut_ad(dict_index_is_clust(index));
513
ut_ad(page_rec_is_user_rec(rec));
514
ut_ad(rec_offs_validate(rec, index, offsets));
516
/* NOTE that we call this function while holding the search
517
system latch. To obey the latching order we must NOT reserve the
518
kernel mutex here! */
520
trx_id = row_get_rec_trx_id(rec, index, offsets);
522
return(read_view_sees_trx_id(view, trx_id));
525
/*********************************************************************//**
526
Checks that a non-clustered index record is seen in a consistent read.
528
NOTE that a non-clustered index page contains so little information on
529
its modifications that also in the case FALSE, the present version of
530
rec may be the right, but we must check this from the clustered index
533
@return TRUE if certainly sees, or FALSE if an earlier version of the
534
clustered index record might be needed */
537
lock_sec_rec_cons_read_sees(
538
/*========================*/
539
const rec_t* rec, /*!< in: user record which
540
should be read or passed over
542
const read_view_t* view) /*!< in: consistent read view */
546
ut_ad(page_rec_is_user_rec(rec));
548
/* NOTE that we might call this function while holding the search
549
system latch. To obey the latching order we must NOT reserve the
550
kernel mutex here! */
552
if (recv_recovery_is_on()) {
557
max_trx_id = page_get_max_trx_id(page_align(rec));
558
ut_ad(!ut_dulint_is_zero(max_trx_id));
560
return(ut_dulint_cmp(max_trx_id, view->up_limit_id) < 0);
563
/*********************************************************************//**
564
Creates the lock system at database start. */
569
ulint n_cells) /*!< in: number of slots in lock hash table */
571
lock_sys = mem_alloc(sizeof(lock_sys_t));
573
lock_sys->rec_hash = hash_create(n_cells);
575
/* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */
577
lock_latest_err_file = os_file_create_tmpfile();
578
ut_a(lock_latest_err_file);
581
/*********************************************************************//**
582
Gets the size of a lock struct.
583
@return size in bytes */
589
return((ulint)sizeof(lock_t));
592
/*********************************************************************//**
593
Gets the mode of a lock.
599
const lock_t* lock) /*!< in: lock */
603
return(lock->type_mode & LOCK_MODE_MASK);
606
/*********************************************************************//**
607
Gets the wait flag of a lock.
608
@return TRUE if waiting */
613
const lock_t* lock) /*!< in: lock */
617
if (UNIV_UNLIKELY(lock->type_mode & LOCK_WAIT)) {
625
/*********************************************************************//**
626
Gets the source table of an ALTER TABLE transaction. The table must be
627
covered by an IX or IS table lock.
628
@return the source table of transaction, if it is covered by an IX or
629
IS table lock; dest if there is no source table, and NULL if the
630
transaction is locking more than two tables or an inconsistency is
636
trx_t* trx, /*!< in: transaction */
637
dict_table_t* dest, /*!< in: destination of ALTER TABLE */
638
enum lock_mode* mode) /*!< out: lock mode of the source table */
646
for (lock = UT_LIST_GET_FIRST(trx->trx_locks);
648
lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
649
lock_table_t* tab_lock;
650
enum lock_mode lock_mode;
651
if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
652
/* We are only interested in table locks. */
655
tab_lock = &lock->un_member.tab_lock;
656
if (dest == tab_lock->table) {
657
/* We are not interested in the destination table. */
660
/* This presumably is the source table. */
661
src = tab_lock->table;
662
if (UT_LIST_GET_LEN(src->locks) != 1
663
|| UT_LIST_GET_FIRST(src->locks) != lock) {
664
/* We only support the case when
665
there is only one lock on this table. */
668
} else if (src != tab_lock->table) {
669
/* The transaction is locking more than
670
two tables (src and dest): abort */
674
/* Check that the source table is locked by
675
LOCK_IX or LOCK_IS. */
676
lock_mode = lock_get_mode(lock);
677
if (lock_mode == LOCK_IX || lock_mode == LOCK_IS) {
678
if (*mode != LOCK_NONE && *mode != lock_mode) {
679
/* There are multiple locks on src. */
687
/* No source table lock found: flag the situation to caller */
694
/*********************************************************************//**
695
Determine if the given table is exclusively "owned" by the given
696
transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
698
@return TRUE if table is only locked by trx, with LOCK_IX, and
699
possibly LOCK_AUTO_INC */
702
lock_is_table_exclusive(
703
/*====================*/
704
dict_table_t* table, /*!< in: table */
705
trx_t* trx) /*!< in: transaction */
713
lock_mutex_enter_kernel();
715
for (lock = UT_LIST_GET_FIRST(table->locks);
717
lock = UT_LIST_GET_NEXT(locks, &lock->un_member.tab_lock)) {
718
if (lock->trx != trx) {
719
/* A lock on the table is held
720
by some other transaction. */
724
if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
725
/* We are interested in table locks only. */
729
switch (lock_get_mode(lock)) {
734
/* It is allowed for trx to hold an
735
auto_increment lock. */
739
/* Other table locks than LOCK_IX are not allowed. */
746
lock_mutex_exit_kernel();
751
/*********************************************************************//**
752
Sets the wait flag of a lock and the back pointer in trx to lock. */
755
lock_set_lock_and_trx_wait(
756
/*=======================*/
757
lock_t* lock, /*!< in: lock */
758
trx_t* trx) /*!< in: trx */
761
ut_ad(trx->wait_lock == NULL);
763
trx->wait_lock = lock;
764
lock->type_mode |= LOCK_WAIT;
767
/**********************************************************************//**
768
The back pointer to a waiting lock request in the transaction is set to NULL
769
and the wait bit in lock type_mode is reset. */
772
lock_reset_lock_and_trx_wait(
773
/*=========================*/
774
lock_t* lock) /*!< in: record lock */
776
ut_ad((lock->trx)->wait_lock == lock);
777
ut_ad(lock_get_wait(lock));
779
/* Reset the back pointer in trx to this waiting lock request */
781
(lock->trx)->wait_lock = NULL;
782
lock->type_mode &= ~LOCK_WAIT;
785
/*********************************************************************//**
786
Gets the gap flag of a record lock.
787
@return TRUE if gap flag set */
792
const lock_t* lock) /*!< in: record lock */
795
ut_ad(lock_get_type_low(lock) == LOCK_REC);
797
if (lock->type_mode & LOCK_GAP) {
805
/*********************************************************************//**
806
Gets the LOCK_REC_NOT_GAP flag of a record lock.
807
@return TRUE if LOCK_REC_NOT_GAP flag set */
810
lock_rec_get_rec_not_gap(
811
/*=====================*/
812
const lock_t* lock) /*!< in: record lock */
815
ut_ad(lock_get_type_low(lock) == LOCK_REC);
817
if (lock->type_mode & LOCK_REC_NOT_GAP) {
825
/*********************************************************************//**
826
Gets the waiting insert flag of a record lock.
827
@return TRUE if gap flag set */
830
lock_rec_get_insert_intention(
831
/*==========================*/
832
const lock_t* lock) /*!< in: record lock */
835
ut_ad(lock_get_type_low(lock) == LOCK_REC);
837
if (lock->type_mode & LOCK_INSERT_INTENTION) {
845
/*********************************************************************//**
846
Calculates if lock mode 1 is stronger or equal to lock mode 2.
847
@return nonzero if mode1 stronger or equal to mode2 */
850
lock_mode_stronger_or_eq(
851
/*=====================*/
852
enum lock_mode mode1, /*!< in: lock mode */
853
enum lock_mode mode2) /*!< in: lock mode */
855
ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX
856
|| mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC);
857
ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX
858
|| mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC);
860
return((LOCK_MODE_STRONGER_OR_EQ) & LK(mode1, mode2));
863
/*********************************************************************//**
864
Calculates if lock mode 1 is compatible with lock mode 2.
865
@return nonzero if mode1 compatible with mode2 */
868
lock_mode_compatible(
869
/*=================*/
870
enum lock_mode mode1, /*!< in: lock mode */
871
enum lock_mode mode2) /*!< in: lock mode */
873
ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX
874
|| mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC);
875
ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX
876
|| mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC);
878
return((LOCK_MODE_COMPATIBILITY) & LK(mode1, mode2));
881
/*********************************************************************//**
882
Checks if a lock request for a new lock has to wait for request lock2.
883
@return TRUE if new lock has to wait for lock2 to be removed */
886
lock_rec_has_to_wait(
887
/*=================*/
888
const trx_t* trx, /*!< in: trx of new lock */
889
ulint type_mode,/*!< in: precise mode of the new lock
890
to set: LOCK_S or LOCK_X, possibly
891
ORed to LOCK_GAP or LOCK_REC_NOT_GAP,
892
LOCK_INSERT_INTENTION */
893
const lock_t* lock2, /*!< in: another record lock; NOTE that
894
it is assumed that this has a lock bit
895
set on the same record as in the new
896
lock we are setting */
897
ibool lock_is_on_supremum) /*!< in: TRUE if we are setting the
898
lock on the 'supremum' record of an
899
index page: we know then that the lock
900
request is really for a 'gap' type lock */
903
ut_ad(lock_get_type_low(lock2) == LOCK_REC);
905
if (trx != lock2->trx
906
&& !lock_mode_compatible(LOCK_MODE_MASK & type_mode,
907
lock_get_mode(lock2))) {
909
/* We have somewhat complex rules when gap type record locks
912
if ((lock_is_on_supremum || (type_mode & LOCK_GAP))
913
&& !(type_mode & LOCK_INSERT_INTENTION)) {
915
/* Gap type locks without LOCK_INSERT_INTENTION flag
916
do not need to wait for anything. This is because
917
different users can have conflicting lock types
923
if (!(type_mode & LOCK_INSERT_INTENTION)
924
&& lock_rec_get_gap(lock2)) {
926
/* Record lock (LOCK_ORDINARY or LOCK_REC_NOT_GAP
927
does not need to wait for a gap type lock */
932
if ((type_mode & LOCK_GAP)
933
&& lock_rec_get_rec_not_gap(lock2)) {
935
/* Lock on gap does not need to wait for
936
a LOCK_REC_NOT_GAP type lock */
941
if (lock_rec_get_insert_intention(lock2)) {
943
/* No lock request needs to wait for an insert
944
intention lock to be removed. This is ok since our
945
rules allow conflicting locks on gaps. This eliminates
946
a spurious deadlock caused by a next-key lock waiting
947
for an insert intention lock; when the insert
948
intention lock was granted, the insert deadlocked on
949
the waiting next-key lock.
951
Also, insert intention locks do not disturb each
963
/*********************************************************************//**
964
Checks if a lock request lock1 has to wait for request lock2.
965
@return TRUE if lock1 has to wait for lock2 to be removed */
970
const lock_t* lock1, /*!< in: waiting lock */
971
const lock_t* lock2) /*!< in: another lock; NOTE that it is
972
assumed that this has a lock bit set
973
on the same record as in lock1 if the
974
locks are record locks */
976
ut_ad(lock1 && lock2);
978
if (lock1->trx != lock2->trx
979
&& !lock_mode_compatible(lock_get_mode(lock1),
980
lock_get_mode(lock2))) {
981
if (lock_get_type_low(lock1) == LOCK_REC) {
982
ut_ad(lock_get_type_low(lock2) == LOCK_REC);
984
/* If this lock request is for a supremum record
985
then the second bit on the lock bitmap is set */
987
return(lock_rec_has_to_wait(lock1->trx,
988
lock1->type_mode, lock2,
989
lock_rec_get_nth_bit(
999
/*============== RECORD LOCK BASIC FUNCTIONS ============================*/
1001
/*********************************************************************//**
1002
Gets the number of bits in a record lock bitmap.
1003
@return number of bits */
1006
lock_rec_get_n_bits(
1007
/*================*/
1008
const lock_t* lock) /*!< in: record lock */
1010
return(lock->un_member.rec_lock.n_bits);
1013
/**********************************************************************//**
1014
Sets the nth bit of a record lock to TRUE. */
1017
lock_rec_set_nth_bit(
1018
/*=================*/
1019
lock_t* lock, /*!< in: record lock */
1020
ulint i) /*!< in: index of the bit */
1026
ut_ad(lock_get_type_low(lock) == LOCK_REC);
1027
ut_ad(i < lock->un_member.rec_lock.n_bits);
1032
((byte*) &lock[1])[byte_index] |= 1 << bit_index;
1035
/**********************************************************************//**
1036
Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
1038
@return bit index == heap number of the record, or ULINT_UNDEFINED if
1042
lock_rec_find_set_bit(
1043
/*==================*/
1044
const lock_t* lock) /*!< in: record lock with at least one bit set */
1048
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
1050
if (lock_rec_get_nth_bit(lock, i)) {
1056
return(ULINT_UNDEFINED);
1059
/**********************************************************************//**
1060
Resets the nth bit of a record lock. */
1063
lock_rec_reset_nth_bit(
1064
/*===================*/
1065
lock_t* lock, /*!< in: record lock */
1066
ulint i) /*!< in: index of the bit which must be set to TRUE
1067
when this function is called */
1073
ut_ad(lock_get_type_low(lock) == LOCK_REC);
1074
ut_ad(i < lock->un_member.rec_lock.n_bits);
1079
((byte*) &lock[1])[byte_index] &= ~(1 << bit_index);
1082
/*********************************************************************//**
1083
Gets the first or next record lock on a page.
1084
@return next lock, NULL if none exists */
1087
lock_rec_get_next_on_page(
1088
/*======================*/
1089
lock_t* lock) /*!< in: a record lock */
1094
ut_ad(mutex_own(&kernel_mutex));
1095
ut_ad(lock_get_type_low(lock) == LOCK_REC);
1097
space = lock->un_member.rec_lock.space;
1098
page_no = lock->un_member.rec_lock.page_no;
1101
lock = HASH_GET_NEXT(hash, lock);
1108
if ((lock->un_member.rec_lock.space == space)
1109
&& (lock->un_member.rec_lock.page_no == page_no)) {
1118
/*********************************************************************//**
1119
Gets the first record lock on a page, where the page is identified by its
1121
@return first lock, NULL if none exists */
1124
lock_rec_get_first_on_page_addr(
1125
/*============================*/
1126
ulint space, /*!< in: space */
1127
ulint page_no)/*!< in: page number */
1131
ut_ad(mutex_own(&kernel_mutex));
1133
lock = HASH_GET_FIRST(lock_sys->rec_hash,
1134
lock_rec_hash(space, page_no));
1136
if ((lock->un_member.rec_lock.space == space)
1137
&& (lock->un_member.rec_lock.page_no == page_no)) {
1142
lock = HASH_GET_NEXT(hash, lock);
1148
/*********************************************************************//**
1149
Returns TRUE if there are explicit record locks on a page.
1150
@return TRUE if there are explicit record locks on the page */
1153
lock_rec_expl_exist_on_page(
1154
/*========================*/
1155
ulint space, /*!< in: space id */
1156
ulint page_no)/*!< in: page number */
1160
mutex_enter(&kernel_mutex);
1162
if (lock_rec_get_first_on_page_addr(space, page_no)) {
1168
mutex_exit(&kernel_mutex);
1173
/*********************************************************************//**
1174
Gets the first record lock on a page, where the page is identified by a
1176
@return first lock, NULL if none exists */
1179
lock_rec_get_first_on_page(
1180
/*=======================*/
1181
const buf_block_t* block) /*!< in: buffer block */
1185
ulint space = buf_block_get_space(block);
1186
ulint page_no = buf_block_get_page_no(block);
1188
ut_ad(mutex_own(&kernel_mutex));
1190
hash = buf_block_get_lock_hash_val(block);
1192
lock = HASH_GET_FIRST(lock_sys->rec_hash, hash);
1195
if ((lock->un_member.rec_lock.space == space)
1196
&& (lock->un_member.rec_lock.page_no == page_no)) {
1201
lock = HASH_GET_NEXT(hash, lock);
1207
/*********************************************************************//**
1208
Gets the next explicit lock request on a record.
1209
@return next lock, NULL if none exists */
1214
ulint heap_no,/*!< in: heap number of the record */
1215
lock_t* lock) /*!< in: lock */
1217
ut_ad(mutex_own(&kernel_mutex));
1220
ut_ad(lock_get_type_low(lock) == LOCK_REC);
1221
lock = lock_rec_get_next_on_page(lock);
1222
} while (lock && !lock_rec_get_nth_bit(lock, heap_no));
1227
/*********************************************************************//**
1228
Gets the first explicit lock request on a record.
1229
@return first lock, NULL if none exists */
1234
const buf_block_t* block, /*!< in: block containing the record */
1235
ulint heap_no)/*!< in: heap number of the record */
1239
ut_ad(mutex_own(&kernel_mutex));
1241
for (lock = lock_rec_get_first_on_page(block); lock;
1242
lock = lock_rec_get_next_on_page(lock)) {
1243
if (lock_rec_get_nth_bit(lock, heap_no)) {
1251
/*********************************************************************//**
1252
Resets the record lock bitmap to zero. NOTE: does not touch the wait_lock
1253
pointer in the transaction! This function is used in lock object creation
1257
lock_rec_bitmap_reset(
1258
/*==================*/
1259
lock_t* lock) /*!< in: record lock */
1263
ut_ad(lock_get_type_low(lock) == LOCK_REC);
1265
/* Reset to zero the bitmap which resides immediately after the lock
1268
n_bytes = lock_rec_get_n_bits(lock) / 8;
1270
ut_ad((lock_rec_get_n_bits(lock) % 8) == 0);
1272
memset(&lock[1], 0, n_bytes);
1275
/*********************************************************************//**
1276
Copies a record lock to heap.
1277
@return copy of lock */
1282
const lock_t* lock, /*!< in: record lock */
1283
mem_heap_t* heap) /*!< in: memory heap */
1287
ut_ad(lock_get_type_low(lock) == LOCK_REC);
1289
size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8;
1291
return(mem_heap_dup(heap, lock, size));
1294
/*********************************************************************//**
1295
Gets the previous record lock set on a record.
1296
@return previous lock on the same record, NULL if none exists */
1301
const lock_t* in_lock,/*!< in: record lock */
1302
ulint heap_no)/*!< in: heap number of the record */
1307
lock_t* found_lock = NULL;
1309
ut_ad(mutex_own(&kernel_mutex));
1310
ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
1312
space = in_lock->un_member.rec_lock.space;
1313
page_no = in_lock->un_member.rec_lock.page_no;
1315
lock = lock_rec_get_first_on_page_addr(space, page_no);
1320
if (lock == in_lock) {
1325
if (lock_rec_get_nth_bit(lock, heap_no)) {
1330
lock = lock_rec_get_next_on_page(lock);
1334
/*============= FUNCTIONS FOR ANALYZING TABLE LOCK QUEUE ================*/
1336
/*********************************************************************//**
1337
Checks if a transaction has the specified table lock, or stronger.
1338
@return lock or NULL */
1343
trx_t* trx, /*!< in: transaction */
1344
dict_table_t* table, /*!< in: table */
1345
enum lock_mode mode) /*!< in: lock mode */
1349
ut_ad(mutex_own(&kernel_mutex));
1351
/* Look for stronger locks the same trx already has on the table */
1353
lock = UT_LIST_GET_LAST(table->locks);
1355
while (lock != NULL) {
1357
if (lock->trx == trx
1358
&& lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) {
1360
/* The same trx already has locked the table in
1361
a mode stronger or equal to the mode given */
1363
ut_ad(!lock_get_wait(lock));
1368
lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
1374
/*============= FUNCTIONS FOR ANALYZING RECORD LOCK QUEUE ================*/
1376
/*********************************************************************//**
1377
Checks if a transaction has a GRANTED explicit lock on rec stronger or equal
1379
@return lock or NULL */
1384
ulint precise_mode,/*!< in: LOCK_S or LOCK_X
1385
possibly ORed to LOCK_GAP or
1386
LOCK_REC_NOT_GAP, for a
1387
supremum record we regard this
1388
always a gap type request */
1389
const buf_block_t* block, /*!< in: buffer block containing
1391
ulint heap_no,/*!< in: heap number of the record */
1392
trx_t* trx) /*!< in: transaction */
1396
ut_ad(mutex_own(&kernel_mutex));
1397
ut_ad((precise_mode & LOCK_MODE_MASK) == LOCK_S
1398
|| (precise_mode & LOCK_MODE_MASK) == LOCK_X);
1399
ut_ad(!(precise_mode & LOCK_INSERT_INTENTION));
1401
lock = lock_rec_get_first(block, heap_no);
1404
if (lock->trx == trx
1405
&& lock_mode_stronger_or_eq(lock_get_mode(lock),
1406
precise_mode & LOCK_MODE_MASK)
1407
&& !lock_get_wait(lock)
1408
&& (!lock_rec_get_rec_not_gap(lock)
1409
|| (precise_mode & LOCK_REC_NOT_GAP)
1410
|| heap_no == PAGE_HEAP_NO_SUPREMUM)
1411
&& (!lock_rec_get_gap(lock)
1412
|| (precise_mode & LOCK_GAP)
1413
|| heap_no == PAGE_HEAP_NO_SUPREMUM)
1414
&& (!lock_rec_get_insert_intention(lock))) {
1419
lock = lock_rec_get_next(heap_no, lock);
1426
/*********************************************************************//**
1427
Checks if some other transaction has a lock request in the queue.
1428
@return lock or NULL */
1431
lock_rec_other_has_expl_req(
1432
/*========================*/
1433
enum lock_mode mode, /*!< in: LOCK_S or LOCK_X */
1434
ulint gap, /*!< in: LOCK_GAP if also gap
1435
locks are taken into account,
1437
ulint wait, /*!< in: LOCK_WAIT if also
1438
waiting locks are taken into
1439
account, or 0 if not */
1440
const buf_block_t* block, /*!< in: buffer block containing
1442
ulint heap_no,/*!< in: heap number of the record */
1443
const trx_t* trx) /*!< in: transaction, or NULL if
1444
requests by all transactions
1445
are taken into account */
1449
ut_ad(mutex_own(&kernel_mutex));
1450
ut_ad(mode == LOCK_X || mode == LOCK_S);
1451
ut_ad(gap == 0 || gap == LOCK_GAP);
1452
ut_ad(wait == 0 || wait == LOCK_WAIT);
1454
lock = lock_rec_get_first(block, heap_no);
1457
if (lock->trx != trx
1459
|| !(lock_rec_get_gap(lock)
1460
|| heap_no == PAGE_HEAP_NO_SUPREMUM))
1461
&& (wait || !lock_get_wait(lock))
1462
&& lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) {
1467
lock = lock_rec_get_next(heap_no, lock);
1472
#endif /* UNIV_DEBUG */
1474
/*********************************************************************//**
1475
Checks if some other transaction has a conflicting explicit lock request
1476
in the queue, so that we have to wait.
1477
@return lock or NULL */
1480
lock_rec_other_has_conflicting(
1481
/*===========================*/
1482
enum lock_mode mode, /*!< in: LOCK_S or LOCK_X,
1483
possibly ORed to LOCK_GAP or
1485
LOCK_INSERT_INTENTION */
1486
const buf_block_t* block, /*!< in: buffer block containing
1488
ulint heap_no,/*!< in: heap number of the record */
1489
trx_t* trx) /*!< in: our transaction */
1493
ut_ad(mutex_own(&kernel_mutex));
1495
lock = lock_rec_get_first(block, heap_no);
1497
if (UNIV_LIKELY_NULL(lock)) {
1498
if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
1501
if (lock_rec_has_to_wait(trx, mode, lock,
1506
lock = lock_rec_get_next(heap_no, lock);
1511
if (lock_rec_has_to_wait(trx, mode, lock,
1516
lock = lock_rec_get_next(heap_no, lock);
1524
/*********************************************************************//**
1525
Looks for a suitable type record lock struct by the same trx on the same page.
1526
This can be used to save space when a new record lock should be set on a page:
1527
no new struct is needed, if a suitable old is found.
1528
@return lock or NULL */
1531
lock_rec_find_similar_on_page(
1532
/*==========================*/
1533
ulint type_mode, /*!< in: lock type_mode field */
1534
ulint heap_no, /*!< in: heap number of the record */
1535
lock_t* lock, /*!< in: lock_rec_get_first_on_page() */
1536
const trx_t* trx) /*!< in: transaction */
1538
ut_ad(mutex_own(&kernel_mutex));
1540
while (lock != NULL) {
1541
if (lock->trx == trx
1542
&& lock->type_mode == type_mode
1543
&& lock_rec_get_n_bits(lock) > heap_no) {
1548
lock = lock_rec_get_next_on_page(lock);
1554
/*********************************************************************//**
1555
Checks if some transaction has an implicit x-lock on a record in a secondary
1557
@return transaction which has the x-lock, or NULL */
1560
lock_sec_rec_some_has_impl_off_kernel(
1561
/*==================================*/
1562
const rec_t* rec, /*!< in: user record */
1563
dict_index_t* index, /*!< in: secondary index */
1564
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
1566
const page_t* page = page_align(rec);
1568
ut_ad(mutex_own(&kernel_mutex));
1569
ut_ad(!dict_index_is_clust(index));
1570
ut_ad(page_rec_is_user_rec(rec));
1571
ut_ad(rec_offs_validate(rec, index, offsets));
1573
/* Some transaction may have an implicit x-lock on the record only
1574
if the max trx id for the page >= min trx id for the trx list, or
1575
database recovery is running. We do not write the changes of a page
1576
max trx id to the log, and therefore during recovery, this value
1577
for a page may be incorrect. */
1579
if (!(ut_dulint_cmp(page_get_max_trx_id(page),
1580
trx_list_get_min_trx_id()) >= 0)
1581
&& !recv_recovery_is_on()) {
1586
/* Ok, in this case it is possible that some transaction has an
1587
implicit x-lock. We have to look in the clustered index. */
1589
if (!lock_check_trx_id_sanity(page_get_max_trx_id(page),
1590
rec, index, offsets, TRUE)) {
1591
buf_page_print(page, 0);
1593
/* The page is corrupt: try to avoid a crash by returning
1598
return(row_vers_impl_x_locked_off_kernel(rec, index, offsets));
1601
/*********************************************************************//**
1602
Return approximate number or record locks (bits set in the bitmap) for
1603
this transaction. Since delete-marked records may be removed, the
1604
record count will not be precise. */
1607
lock_number_of_rows_locked(
1608
/*=======================*/
1609
trx_t* trx) /*!< in: transaction */
1612
ulint n_records = 0;
1616
lock = UT_LIST_GET_FIRST(trx->trx_locks);
1619
if (lock_get_type_low(lock) == LOCK_REC) {
1620
n_bits = lock_rec_get_n_bits(lock);
1622
for (n_bit = 0; n_bit < n_bits; n_bit++) {
1623
if (lock_rec_get_nth_bit(lock, n_bit)) {
1629
lock = UT_LIST_GET_NEXT(trx_locks, lock);
1635
/*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/
1637
/*********************************************************************//**
1638
Creates a new record lock and inserts it to the lock queue. Does NOT check
1639
for deadlocks or lock compatibility!
1640
@return created lock */
1645
ulint type_mode,/*!< in: lock mode and wait
1646
flag, type is ignored and
1647
replaced by LOCK_REC */
1648
const buf_block_t* block, /*!< in: buffer block containing
1650
ulint heap_no,/*!< in: heap number of the record */
1651
dict_index_t* index, /*!< in: index of record */
1652
trx_t* trx) /*!< in: transaction */
1661
ut_ad(mutex_own(&kernel_mutex));
1663
space = buf_block_get_space(block);
1664
page_no = buf_block_get_page_no(block);
1665
page = block->frame;
1667
ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
1669
/* If rec is the supremum record, then we reset the gap and
1670
LOCK_REC_NOT_GAP bits, as all locks on the supremum are
1671
automatically of the gap type */
1673
if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
1674
ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
1676
type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
1679
/* Make lock bitmap bigger by a safety margin */
1680
n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN;
1681
n_bytes = 1 + n_bits / 8;
1683
lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes);
1685
UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
1689
lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
1690
lock->index = index;
1692
lock->un_member.rec_lock.space = space;
1693
lock->un_member.rec_lock.page_no = page_no;
1694
lock->un_member.rec_lock.n_bits = n_bytes * 8;
1696
/* Reset to zero the bitmap which resides immediately after the
1699
lock_rec_bitmap_reset(lock);
1701
/* Set the bit corresponding to rec */
1702
lock_rec_set_nth_bit(lock, heap_no);
1704
HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
1705
lock_rec_fold(space, page_no), lock);
1706
if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
1708
lock_set_lock_and_trx_wait(lock, trx);
1714
/*********************************************************************//**
1715
Enqueues a waiting request for a lock which cannot be granted immediately.
1716
Checks for deadlocks.
1717
@return DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED, or
1718
DB_SUCCESS; DB_SUCCESS means that there was a deadlock, but another
1719
transaction was chosen as a victim, and we got the lock immediately:
1720
no need to wait then */
1723
lock_rec_enqueue_waiting(
1724
/*=====================*/
1725
ulint type_mode,/*!< in: lock mode this
1726
transaction is requesting:
1727
LOCK_S or LOCK_X, possibly
1728
ORed with LOCK_GAP or
1729
LOCK_REC_NOT_GAP, ORed with
1730
LOCK_INSERT_INTENTION if this
1731
waiting lock request is set
1732
when performing an insert of
1734
const buf_block_t* block, /*!< in: buffer block containing
1736
ulint heap_no,/*!< in: heap number of the record */
1737
dict_index_t* index, /*!< in: index of record */
1738
que_thr_t* thr) /*!< in: query thread */
1743
ut_ad(mutex_own(&kernel_mutex));
1745
/* Test if there already is some other reason to suspend thread:
1746
we do not enqueue a lock request if the query thread should be
1749
if (UNIV_UNLIKELY(que_thr_stop(thr))) {
1753
return(DB_QUE_THR_SUSPENDED);
1756
trx = thr_get_trx(thr);
1758
switch (trx_get_dict_operation(trx)) {
1759
case TRX_DICT_OP_NONE:
1761
case TRX_DICT_OP_TABLE:
1762
case TRX_DICT_OP_INDEX:
1763
ut_print_timestamp(stderr);
1764
fputs(" InnoDB: Error: a record lock wait happens"
1765
" in a dictionary operation!\n"
1766
"InnoDB: ", stderr);
1767
dict_index_name_print(stderr, trx, index);
1769
"InnoDB: Submit a detailed bug report"
1770
" to http://bugs.mysql.com\n",
1774
/* Enqueue the lock request that will wait to be granted */
1775
lock = lock_rec_create(type_mode | LOCK_WAIT,
1776
block, heap_no, index, trx);
1778
/* Check if a deadlock occurs: if yes, remove the lock request and
1779
return an error code */
1781
if (UNIV_UNLIKELY(lock_deadlock_occurs(lock, trx))) {
1783
lock_reset_lock_and_trx_wait(lock);
1784
lock_rec_reset_nth_bit(lock, heap_no);
1786
return(DB_DEADLOCK);
1789
/* If there was a deadlock but we chose another transaction as a
1790
victim, it is possible that we already have the lock now granted! */
1792
if (trx->wait_lock == NULL) {
1797
trx->que_state = TRX_QUE_LOCK_WAIT;
1798
trx->was_chosen_as_deadlock_victim = FALSE;
1799
trx->wait_started = time(NULL);
1801
ut_a(que_thr_stop(thr));
1804
if (lock_print_waits) {
1805
fprintf(stderr, "Lock wait for trx %lu in index ",
1806
(ulong) ut_dulint_get_low(trx->id));
1807
ut_print_name(stderr, trx, FALSE, index->name);
1809
#endif /* UNIV_DEBUG */
1811
return(DB_LOCK_WAIT);
1814
/*********************************************************************//**
1815
Adds a record lock request in the record queue. The request is normally
1816
added as the last in the queue, but if there are no waiting lock requests
1817
on the record, and the request to be added is not a waiting request, we
1818
can reuse a suitable record lock object already existing on the same page,
1819
just setting the appropriate bit in its bitmap. This is a low-level function
1820
which does NOT check for deadlocks or lock compatibility!
1821
@return lock where the bit was set */
1824
lock_rec_add_to_queue(
1825
/*==================*/
1826
ulint type_mode,/*!< in: lock mode, wait, gap
1827
etc. flags; type is ignored
1828
and replaced by LOCK_REC */
1829
const buf_block_t* block, /*!< in: buffer block containing
1831
ulint heap_no,/*!< in: heap number of the record */
1832
dict_index_t* index, /*!< in: index of record */
1833
trx_t* trx) /*!< in: transaction */
1837
ut_ad(mutex_own(&kernel_mutex));
1839
switch (type_mode & LOCK_MODE_MASK) {
1847
if (!(type_mode & (LOCK_WAIT | LOCK_GAP))) {
1848
enum lock_mode mode = (type_mode & LOCK_MODE_MASK) == LOCK_S
1852
= lock_rec_other_has_expl_req(mode, 0, LOCK_WAIT,
1853
block, heap_no, trx);
1856
#endif /* UNIV_DEBUG */
1858
type_mode |= LOCK_REC;
1860
/* If rec is the supremum record, then we can reset the gap bit, as
1861
all locks on the supremum are automatically of the gap type, and we
1862
try to avoid unnecessary memory consumption of a new record lock
1863
struct for a gap type lock */
1865
if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
1866
ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
1868
/* There should never be LOCK_REC_NOT_GAP on a supremum
1869
record, but let us play safe */
1871
type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);
1874
/* Look for a waiting lock request on the same record or on a gap */
1876
lock = lock_rec_get_first_on_page(block);
1878
while (lock != NULL) {
1879
if (lock_get_wait(lock)
1880
&& (lock_rec_get_nth_bit(lock, heap_no))) {
1882
goto somebody_waits;
1885
lock = lock_rec_get_next_on_page(lock);
1888
if (UNIV_LIKELY(!(type_mode & LOCK_WAIT))) {
1890
/* Look for a similar record lock on the same page:
1891
if one is found and there are no waiting lock requests,
1892
we can just set the bit */
1894
lock = lock_rec_find_similar_on_page(
1896
lock_rec_get_first_on_page(block), trx);
1900
lock_rec_set_nth_bit(lock, heap_no);
1907
return(lock_rec_create(type_mode, block, heap_no, index, trx));
1910
/*********************************************************************//**
1911
This is a fast routine for locking a record in the most common cases:
1912
there are no explicit locks on the page, or there is just one lock, owned
1913
by this transaction, and of the right type_mode. This is a low-level function
1914
which does NOT look at implicit locks! Checks lock compatibility within
1915
explicit locks. This function sets a normal next-key lock, or in the case of
1916
a page supremum record, a gap type lock.
1917
@return TRUE if locking succeeded */
1922
ibool impl, /*!< in: if TRUE, no lock is set
1923
if no wait is necessary: we
1924
assume that the caller will
1925
set an implicit lock */
1926
ulint mode, /*!< in: lock mode: LOCK_X or
1927
LOCK_S possibly ORed to either
1928
LOCK_GAP or LOCK_REC_NOT_GAP */
1929
const buf_block_t* block, /*!< in: buffer block containing
1931
ulint heap_no,/*!< in: heap number of record */
1932
dict_index_t* index, /*!< in: index of record */
1933
que_thr_t* thr) /*!< in: query thread */
1938
ut_ad(mutex_own(&kernel_mutex));
1939
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
1940
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
1941
ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
1942
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
1943
ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
1944
|| (LOCK_MODE_MASK & mode) == LOCK_X);
1945
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
1946
|| mode - (LOCK_MODE_MASK & mode) == 0
1947
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
1949
lock = lock_rec_get_first_on_page(block);
1951
trx = thr_get_trx(thr);
1955
lock_rec_create(mode, block, heap_no, index, trx);
1961
if (lock_rec_get_next_on_page(lock)) {
1966
if (lock->trx != trx
1967
|| lock->type_mode != (mode | LOCK_REC)
1968
|| lock_rec_get_n_bits(lock) <= heap_no) {
1974
/* If the nth bit of the record lock is already set then we
1975
do not set a new lock bit, otherwise we do set */
1977
if (!lock_rec_get_nth_bit(lock, heap_no)) {
1978
lock_rec_set_nth_bit(lock, heap_no);
1985
/*********************************************************************//**
1986
This is the general, and slower, routine for locking a record. This is a
1987
low-level function which does NOT look at implicit locks! Checks lock
1988
compatibility within explicit locks. This function sets a normal next-key
1989
lock, or in the case of a page supremum record, a gap type lock.
1990
@return DB_SUCCESS, DB_LOCK_WAIT, or error code */
1995
ibool impl, /*!< in: if TRUE, no lock is set
1996
if no wait is necessary: we
1997
assume that the caller will
1998
set an implicit lock */
1999
ulint mode, /*!< in: lock mode: LOCK_X or
2000
LOCK_S possibly ORed to either
2001
LOCK_GAP or LOCK_REC_NOT_GAP */
2002
const buf_block_t* block, /*!< in: buffer block containing
2004
ulint heap_no,/*!< in: heap number of record */
2005
dict_index_t* index, /*!< in: index of record */
2006
que_thr_t* thr) /*!< in: query thread */
2011
ut_ad(mutex_own(&kernel_mutex));
2012
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2013
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
2014
ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
2015
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
2016
ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
2017
|| (LOCK_MODE_MASK & mode) == LOCK_X);
2018
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
2019
|| mode - (LOCK_MODE_MASK & mode) == 0
2020
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
2022
trx = thr_get_trx(thr);
2024
if (lock_rec_has_expl(mode, block, heap_no, trx)) {
2025
/* The trx already has a strong enough lock on rec: do
2029
} else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) {
2031
/* If another transaction has a non-gap conflicting request in
2032
the queue, as this transaction does not have a lock strong
2033
enough already granted on the record, we have to wait. */
2035
err = lock_rec_enqueue_waiting(mode, block, heap_no,
2039
/* Set the requested lock on the record */
2041
lock_rec_add_to_queue(LOCK_REC | mode, block,
2042
heap_no, index, trx);
2051
/*********************************************************************//**
2052
Tries to lock the specified record in the mode requested. If not immediately
2053
possible, enqueues a waiting lock request. This is a low-level function
2054
which does NOT look at implicit locks! Checks lock compatibility within
2055
explicit locks. This function sets a normal next-key lock, or in the case
2056
of a page supremum record, a gap type lock.
2057
@return DB_SUCCESS, DB_LOCK_WAIT, or error code */
2062
ibool impl, /*!< in: if TRUE, no lock is set
2063
if no wait is necessary: we
2064
assume that the caller will
2065
set an implicit lock */
2066
ulint mode, /*!< in: lock mode: LOCK_X or
2067
LOCK_S possibly ORed to either
2068
LOCK_GAP or LOCK_REC_NOT_GAP */
2069
const buf_block_t* block, /*!< in: buffer block containing
2071
ulint heap_no,/*!< in: heap number of record */
2072
dict_index_t* index, /*!< in: index of record */
2073
que_thr_t* thr) /*!< in: query thread */
2077
ut_ad(mutex_own(&kernel_mutex));
2078
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2079
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
2080
ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
2081
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
2082
ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
2083
|| (LOCK_MODE_MASK & mode) == LOCK_X);
2084
ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
2085
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
2086
|| mode - (LOCK_MODE_MASK & mode) == 0);
2088
if (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
2090
/* We try a simplified and faster subroutine for the most
2095
err = lock_rec_lock_slow(impl, mode, block,
2096
heap_no, index, thr);
2102
/*********************************************************************//**
2103
Checks if a waiting record lock request still has to wait in a queue.
2104
@return TRUE if still has to wait */
2107
lock_rec_has_to_wait_in_queue(
2108
/*==========================*/
2109
lock_t* wait_lock) /*!< in: waiting record lock */
2116
ut_ad(mutex_own(&kernel_mutex));
2117
ut_ad(lock_get_wait(wait_lock));
2118
ut_ad(lock_get_type_low(wait_lock) == LOCK_REC);
2120
space = wait_lock->un_member.rec_lock.space;
2121
page_no = wait_lock->un_member.rec_lock.page_no;
2122
heap_no = lock_rec_find_set_bit(wait_lock);
2124
lock = lock_rec_get_first_on_page_addr(space, page_no);
2126
while (lock != wait_lock) {
2128
if (lock_rec_get_nth_bit(lock, heap_no)
2129
&& lock_has_to_wait(wait_lock, lock)) {
2134
lock = lock_rec_get_next_on_page(lock);
2140
/*************************************************************//**
2141
Grants a lock to a waiting lock request and releases the waiting
2147
lock_t* lock) /*!< in/out: waiting lock request */
2149
ut_ad(mutex_own(&kernel_mutex));
2151
lock_reset_lock_and_trx_wait(lock);
2153
if (lock_get_mode(lock) == LOCK_AUTO_INC) {
2154
trx_t* trx = lock->trx;
2155
dict_table_t* table = lock->un_member.tab_lock.table;
2157
if (table->autoinc_trx == trx) {
2159
"InnoDB: Error: trx already had"
2160
" an AUTO-INC lock!\n");
2162
table->autoinc_trx = trx;
2164
ib_vector_push(trx->autoinc_locks, lock);
2169
if (lock_print_waits) {
2170
fprintf(stderr, "Lock wait for trx %lu ends\n",
2171
(ulong) ut_dulint_get_low(lock->trx->id));
2173
#endif /* UNIV_DEBUG */
2175
/* If we are resolving a deadlock by choosing another transaction
2176
as a victim, then our original transaction may not be in the
2177
TRX_QUE_LOCK_WAIT state, and there is no need to end the lock wait
2180
if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) {
2181
trx_end_lock_wait(lock->trx);
2185
/*************************************************************//**
2186
Cancels a waiting record lock request and releases the waiting transaction
2187
that requested it. NOTE: does NOT check if waiting lock requests behind this
2188
one can now be granted! */
2193
lock_t* lock) /*!< in: waiting record lock request */
2195
ut_ad(mutex_own(&kernel_mutex));
2196
ut_ad(lock_get_type_low(lock) == LOCK_REC);
2198
/* Reset the bit (there can be only one set bit) in the lock bitmap */
2199
lock_rec_reset_nth_bit(lock, lock_rec_find_set_bit(lock));
2201
/* Reset the wait flag and the back pointer to lock in trx */
2203
lock_reset_lock_and_trx_wait(lock);
2205
/* The following function releases the trx from lock wait */
2207
trx_end_lock_wait(lock->trx);
2210
/*************************************************************//**
2211
Removes a record lock request, waiting or granted, from the queue and
2212
grants locks to other transactions in the queue if they now are entitled
2213
to a lock. NOTE: all record locks contained in in_lock are removed. */
2216
lock_rec_dequeue_from_page(
2217
/*=======================*/
2218
lock_t* in_lock)/*!< in: record lock object: all record locks which
2219
are contained in this lock object are removed;
2220
transactions waiting behind will get their lock
2221
requests granted, if they are now qualified to it */
2228
ut_ad(mutex_own(&kernel_mutex));
2229
ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
2233
space = in_lock->un_member.rec_lock.space;
2234
page_no = in_lock->un_member.rec_lock.page_no;
2236
HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
2237
lock_rec_fold(space, page_no), in_lock);
2239
UT_LIST_REMOVE(trx_locks, trx->trx_locks, in_lock);
2241
/* Check if waiting locks in the queue can now be granted: grant
2242
locks if there are no conflicting locks ahead. */
2244
lock = lock_rec_get_first_on_page_addr(space, page_no);
2246
while (lock != NULL) {
2247
if (lock_get_wait(lock)
2248
&& !lock_rec_has_to_wait_in_queue(lock)) {
2250
/* Grant the lock */
2254
lock = lock_rec_get_next_on_page(lock);
2258
/*************************************************************//**
2259
Removes a record lock request, waiting or granted, from the queue. */
2264
lock_t* in_lock)/*!< in: record lock object: all record locks which
2265
are contained in this lock object are removed */
2271
ut_ad(mutex_own(&kernel_mutex));
2272
ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
2276
space = in_lock->un_member.rec_lock.space;
2277
page_no = in_lock->un_member.rec_lock.page_no;
2279
HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
2280
lock_rec_fold(space, page_no), in_lock);
2282
UT_LIST_REMOVE(trx_locks, trx->trx_locks, in_lock);
2285
/*************************************************************//**
2286
Removes record lock objects set on an index page which is discarded. This
2287
function does not move locks, or check for waiting locks, therefore the
2288
lock bitmaps must already be reset when this function is called. */
2291
lock_rec_free_all_from_discard_page(
2292
/*================================*/
2293
const buf_block_t* block) /*!< in: page to be discarded */
2300
ut_ad(mutex_own(&kernel_mutex));
2302
space = buf_block_get_space(block);
2303
page_no = buf_block_get_page_no(block);
2305
lock = lock_rec_get_first_on_page_addr(space, page_no);
2307
while (lock != NULL) {
2308
ut_ad(lock_rec_find_set_bit(lock) == ULINT_UNDEFINED);
2309
ut_ad(!lock_get_wait(lock));
2311
next_lock = lock_rec_get_next_on_page(lock);
2313
lock_rec_discard(lock);
2319
/*============= RECORD LOCK MOVING AND INHERITING ===================*/
2321
/*************************************************************//**
2322
Resets the lock bits for a single record. Releases transactions waiting for
2323
lock requests here. */
2326
lock_rec_reset_and_release_wait(
2327
/*============================*/
2328
const buf_block_t* block, /*!< in: buffer block containing
2330
ulint heap_no)/*!< in: heap number of record */
2334
ut_ad(mutex_own(&kernel_mutex));
2336
lock = lock_rec_get_first(block, heap_no);
2338
while (lock != NULL) {
2339
if (lock_get_wait(lock)) {
2340
lock_rec_cancel(lock);
2342
lock_rec_reset_nth_bit(lock, heap_no);
2345
lock = lock_rec_get_next(heap_no, lock);
2349
/*************************************************************//**
2350
Makes a record to inherit the locks (except LOCK_INSERT_INTENTION type)
2351
of another record as gap type locks, but does not reset the lock bits of
2352
the other record. Also waiting lock requests on rec are inherited as
2353
GRANTED gap locks. */
2356
lock_rec_inherit_to_gap(
2357
/*====================*/
2358
const buf_block_t* heir_block, /*!< in: block containing the
2359
record which inherits */
2360
const buf_block_t* block, /*!< in: block containing the
2361
record from which inherited;
2362
does NOT reset the locks on
2364
ulint heir_heap_no, /*!< in: heap_no of the
2365
inheriting record */
2366
ulint heap_no) /*!< in: heap_no of the
2371
ut_ad(mutex_own(&kernel_mutex));
2373
lock = lock_rec_get_first(block, heap_no);
2375
/* If srv_locks_unsafe_for_binlog is TRUE or session is using
2376
READ COMMITTED isolation level, we do not want locks set
2377
by an UPDATE or a DELETE to be inherited as gap type locks. But we
2378
DO want S-locks set by a consistency constraint to be inherited also
2381
while (lock != NULL) {
2382
if (!lock_rec_get_insert_intention(lock)
2383
&& !((srv_locks_unsafe_for_binlog
2384
|| lock->trx->isolation_level
2385
== TRX_ISO_READ_COMMITTED)
2386
&& lock_get_mode(lock) == LOCK_X)) {
2388
lock_rec_add_to_queue(LOCK_REC | LOCK_GAP
2389
| lock_get_mode(lock),
2390
heir_block, heir_heap_no,
2391
lock->index, lock->trx);
2394
lock = lock_rec_get_next(heap_no, lock);
2398
/*************************************************************//**
2399
Makes a record to inherit the gap locks (except LOCK_INSERT_INTENTION type)
2400
of another record as gap type locks, but does not reset the lock bits of the
2401
other record. Also waiting lock requests are inherited as GRANTED gap locks. */
2404
lock_rec_inherit_to_gap_if_gap_lock(
2405
/*================================*/
2406
const buf_block_t* block, /*!< in: buffer block */
2407
ulint heir_heap_no, /*!< in: heap_no of
2408
record which inherits */
2409
ulint heap_no) /*!< in: heap_no of record
2410
from which inherited;
2411
does NOT reset the locks
2416
ut_ad(mutex_own(&kernel_mutex));
2418
lock = lock_rec_get_first(block, heap_no);
2420
while (lock != NULL) {
2421
if (!lock_rec_get_insert_intention(lock)
2422
&& (heap_no == PAGE_HEAP_NO_SUPREMUM
2423
|| !lock_rec_get_rec_not_gap(lock))) {
2425
lock_rec_add_to_queue(LOCK_REC | LOCK_GAP
2426
| lock_get_mode(lock),
2427
block, heir_heap_no,
2428
lock->index, lock->trx);
2431
lock = lock_rec_get_next(heap_no, lock);
2435
/*************************************************************//**
2436
Moves the locks of a record to another record and resets the lock bits of
2437
the donating record. */
2442
const buf_block_t* receiver, /*!< in: buffer block containing
2443
the receiving record */
2444
const buf_block_t* donator, /*!< in: buffer block containing
2445
the donating record */
2446
ulint receiver_heap_no,/*!< in: heap_no of the record
2447
which gets the locks; there
2448
must be no lock requests
2450
ulint donator_heap_no)/*!< in: heap_no of the record
2451
which gives the locks */
2455
ut_ad(mutex_own(&kernel_mutex));
2457
lock = lock_rec_get_first(donator, donator_heap_no);
2459
ut_ad(lock_rec_get_first(receiver, receiver_heap_no) == NULL);
2461
while (lock != NULL) {
2462
const ulint type_mode = lock->type_mode;
2464
lock_rec_reset_nth_bit(lock, donator_heap_no);
2466
if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
2467
lock_reset_lock_and_trx_wait(lock);
2470
/* Note that we FIRST reset the bit, and then set the lock:
2471
the function works also if donator == receiver */
2473
lock_rec_add_to_queue(type_mode, receiver, receiver_heap_no,
2474
lock->index, lock->trx);
2475
lock = lock_rec_get_next(donator_heap_no, lock);
2478
ut_ad(lock_rec_get_first(donator, donator_heap_no) == NULL);
2481
/*************************************************************//**
2482
Updates the lock table when we have reorganized a page. NOTE: we copy
2483
also the locks set on the infimum of the page; the infimum may carry
2484
locks if an update of a record is occurring on the page, and its locks
2485
were temporarily stored on the infimum. */
2488
lock_move_reorganize_page(
2489
/*======================*/
2490
const buf_block_t* block, /*!< in: old index page, now
2492
const buf_block_t* oblock) /*!< in: copy of the old, not
2496
UT_LIST_BASE_NODE_T(lock_t) old_locks;
2497
mem_heap_t* heap = NULL;
2500
lock_mutex_enter_kernel();
2502
lock = lock_rec_get_first_on_page(block);
2505
lock_mutex_exit_kernel();
2510
heap = mem_heap_create(256);
2512
/* Copy first all the locks on the page to heap and reset the
2513
bitmaps in the original locks; chain the copies of the locks
2514
using the trx_locks field in them. */
2516
UT_LIST_INIT(old_locks);
2519
/* Make a copy of the lock */
2520
lock_t* old_lock = lock_rec_copy(lock, heap);
2522
UT_LIST_ADD_LAST(trx_locks, old_locks, old_lock);
2524
/* Reset bitmap of lock */
2525
lock_rec_bitmap_reset(lock);
2527
if (lock_get_wait(lock)) {
2528
lock_reset_lock_and_trx_wait(lock);
2531
lock = lock_rec_get_next_on_page(lock);
2532
} while (lock != NULL);
2534
comp = page_is_comp(block->frame);
2535
ut_ad(comp == page_is_comp(oblock->frame));
2537
for (lock = UT_LIST_GET_FIRST(old_locks); lock;
2538
lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
2539
/* NOTE: we copy also the locks set on the infimum and
2540
supremum of the page; the infimum may carry locks if an
2541
update of a record is occurring on the page, and its locks
2542
were temporarily stored on the infimum */
2546
page_cur_set_before_first(block, &cur1);
2547
page_cur_set_before_first(oblock, &cur2);
2549
/* Set locks according to old locks */
2554
ut_ad(comp || !memcmp(page_cur_get_rec(&cur1),
2555
page_cur_get_rec(&cur2),
2556
rec_get_data_size_old(
2559
if (UNIV_LIKELY(comp)) {
2560
old_heap_no = rec_get_heap_no_new(
2561
page_cur_get_rec(&cur2));
2562
new_heap_no = rec_get_heap_no_new(
2563
page_cur_get_rec(&cur1));
2565
old_heap_no = rec_get_heap_no_old(
2566
page_cur_get_rec(&cur2));
2567
new_heap_no = rec_get_heap_no_old(
2568
page_cur_get_rec(&cur1));
2571
if (lock_rec_get_nth_bit(lock, old_heap_no)) {
2573
/* Clear the bit in old_lock. */
2574
ut_d(lock_rec_reset_nth_bit(lock,
2577
/* NOTE that the old lock bitmap could be too
2578
small for the new heap number! */
2580
lock_rec_add_to_queue(lock->type_mode, block,
2582
lock->index, lock->trx);
2584
/* if (new_heap_no == PAGE_HEAP_NO_SUPREMUM
2585
&& lock_get_wait(lock)) {
2587
"---\n--\n!!!Lock reorg: supr type %lu\n",
2593
(new_heap_no == PAGE_HEAP_NO_SUPREMUM)) {
2595
ut_ad(old_heap_no == PAGE_HEAP_NO_SUPREMUM);
2599
page_cur_move_to_next(&cur1);
2600
page_cur_move_to_next(&cur2);
2605
ulint i = lock_rec_find_set_bit(lock);
2607
/* Check that all locks were moved. */
2608
if (UNIV_UNLIKELY(i != ULINT_UNDEFINED)) {
2610
"lock_move_reorganize_page():"
2611
" %lu not moved in %p\n",
2612
(ulong) i, (void*) lock);
2616
#endif /* UNIV_DEBUG */
2619
lock_mutex_exit_kernel();
2621
mem_heap_free(heap);
2623
#ifdef UNIV_DEBUG_LOCK_VALIDATE
2624
ut_ad(lock_rec_validate_page(buf_block_get_space(block),
2625
buf_block_get_page_no(block)));
2629
/*************************************************************//**
2630
Moves the explicit locks on user records to another page if a record
2631
list end is moved to another page. */
2634
lock_move_rec_list_end(
2635
/*===================*/
2636
const buf_block_t* new_block, /*!< in: index page to move to */
2637
const buf_block_t* block, /*!< in: index page */
2638
const rec_t* rec) /*!< in: record on page: this
2639
is the first record moved */
2642
const ulint comp = page_rec_is_comp(rec);
2644
lock_mutex_enter_kernel();
2646
/* Note: when we move locks from record to record, waiting locks
2647
and possible granted gap type locks behind them are enqueued in
2648
the original order, because new elements are inserted to a hash
2649
table to the end of the hash chain, and lock_rec_add_to_queue
2650
does not reuse locks if there are waiters in the queue. */
2652
for (lock = lock_rec_get_first_on_page(block); lock;
2653
lock = lock_rec_get_next_on_page(lock)) {
2656
const ulint type_mode = lock->type_mode;
2658
page_cur_position(rec, block, &cur1);
2660
if (page_cur_is_before_first(&cur1)) {
2661
page_cur_move_to_next(&cur1);
2664
page_cur_set_before_first(new_block, &cur2);
2665
page_cur_move_to_next(&cur2);
2667
/* Copy lock requests on user records to new page and
2668
reset the lock bits on the old */
2670
while (!page_cur_is_after_last(&cur1)) {
2674
heap_no = rec_get_heap_no_new(
2675
page_cur_get_rec(&cur1));
2677
heap_no = rec_get_heap_no_old(
2678
page_cur_get_rec(&cur1));
2679
ut_ad(!memcmp(page_cur_get_rec(&cur1),
2680
page_cur_get_rec(&cur2),
2681
rec_get_data_size_old(
2682
page_cur_get_rec(&cur2))));
2685
if (lock_rec_get_nth_bit(lock, heap_no)) {
2686
lock_rec_reset_nth_bit(lock, heap_no);
2688
if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
2689
lock_reset_lock_and_trx_wait(lock);
2693
heap_no = rec_get_heap_no_new(
2694
page_cur_get_rec(&cur2));
2696
heap_no = rec_get_heap_no_old(
2697
page_cur_get_rec(&cur2));
2700
lock_rec_add_to_queue(type_mode,
2702
lock->index, lock->trx);
2705
page_cur_move_to_next(&cur1);
2706
page_cur_move_to_next(&cur2);
2710
lock_mutex_exit_kernel();
2712
#ifdef UNIV_DEBUG_LOCK_VALIDATE
2713
ut_ad(lock_rec_validate_page(buf_block_get_space(block),
2714
buf_block_get_page_no(block)));
2715
ut_ad(lock_rec_validate_page(buf_block_get_space(new_block),
2716
buf_block_get_page_no(new_block)));
2720
/*************************************************************//**
2721
Moves the explicit locks on user records to another page if a record
2722
list start is moved to another page. */
2725
lock_move_rec_list_start(
2726
/*=====================*/
2727
const buf_block_t* new_block, /*!< in: index page to move to */
2728
const buf_block_t* block, /*!< in: index page */
2729
const rec_t* rec, /*!< in: record on page:
2731
record NOT copied */
2732
const rec_t* old_end) /*!< in: old
2739
const ulint comp = page_rec_is_comp(rec);
2741
ut_ad(block->frame == page_align(rec));
2742
ut_ad(new_block->frame == page_align(old_end));
2744
lock_mutex_enter_kernel();
2746
for (lock = lock_rec_get_first_on_page(block); lock;
2747
lock = lock_rec_get_next_on_page(lock)) {
2750
const ulint type_mode = lock->type_mode;
2752
page_cur_set_before_first(block, &cur1);
2753
page_cur_move_to_next(&cur1);
2755
page_cur_position(old_end, new_block, &cur2);
2756
page_cur_move_to_next(&cur2);
2758
/* Copy lock requests on user records to new page and
2759
reset the lock bits on the old */
2761
while (page_cur_get_rec(&cur1) != rec) {
2765
heap_no = rec_get_heap_no_new(
2766
page_cur_get_rec(&cur1));
2768
heap_no = rec_get_heap_no_old(
2769
page_cur_get_rec(&cur1));
2770
ut_ad(!memcmp(page_cur_get_rec(&cur1),
2771
page_cur_get_rec(&cur2),
2772
rec_get_data_size_old(
2777
if (lock_rec_get_nth_bit(lock, heap_no)) {
2778
lock_rec_reset_nth_bit(lock, heap_no);
2780
if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
2781
lock_reset_lock_and_trx_wait(lock);
2785
heap_no = rec_get_heap_no_new(
2786
page_cur_get_rec(&cur2));
2788
heap_no = rec_get_heap_no_old(
2789
page_cur_get_rec(&cur2));
2792
lock_rec_add_to_queue(type_mode,
2794
lock->index, lock->trx);
2797
page_cur_move_to_next(&cur1);
2798
page_cur_move_to_next(&cur2);
2802
if (page_rec_is_supremum(rec)) {
2805
for (i = PAGE_HEAP_NO_USER_LOW;
2806
i < lock_rec_get_n_bits(lock); i++) {
2808
(lock_rec_get_nth_bit(lock, i))) {
2811
"lock_move_rec_list_start():"
2812
" %lu not moved in %p\n",
2813
(ulong) i, (void*) lock);
2818
#endif /* UNIV_DEBUG */
2821
lock_mutex_exit_kernel();
2823
#ifdef UNIV_DEBUG_LOCK_VALIDATE
2824
ut_ad(lock_rec_validate_page(buf_block_get_space(block),
2825
buf_block_get_page_no(block)));
2829
/*************************************************************//**
2830
Updates the lock table when a page is split to the right. */
2833
lock_update_split_right(
2834
/*====================*/
2835
const buf_block_t* right_block, /*!< in: right page */
2836
const buf_block_t* left_block) /*!< in: left page */
2838
ulint heap_no = lock_get_min_heap_no(right_block);
2840
lock_mutex_enter_kernel();
2842
/* Move the locks on the supremum of the left page to the supremum
2843
of the right page */
2845
lock_rec_move(right_block, left_block,
2846
PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
2848
/* Inherit the locks to the supremum of left page from the successor
2849
of the infimum on right page */
2851
lock_rec_inherit_to_gap(left_block, right_block,
2852
PAGE_HEAP_NO_SUPREMUM, heap_no);
2854
lock_mutex_exit_kernel();
2857
/*************************************************************//**
2858
Updates the lock table when a page is merged to the right. */
2861
lock_update_merge_right(
2862
/*====================*/
2863
const buf_block_t* right_block, /*!< in: right page to
2865
const rec_t* orig_succ, /*!< in: original
2866
successor of infimum
2869
const buf_block_t* left_block) /*!< in: merged index
2873
lock_mutex_enter_kernel();
2875
/* Inherit the locks from the supremum of the left page to the
2876
original successor of infimum on the right page, to which the left
2879
lock_rec_inherit_to_gap(right_block, left_block,
2880
page_rec_get_heap_no(orig_succ),
2881
PAGE_HEAP_NO_SUPREMUM);
2883
/* Reset the locks on the supremum of the left page, releasing
2884
waiting transactions */
2886
lock_rec_reset_and_release_wait(left_block,
2887
PAGE_HEAP_NO_SUPREMUM);
2889
lock_rec_free_all_from_discard_page(left_block);
2891
lock_mutex_exit_kernel();
2894
/*************************************************************//**
2895
Updates the lock table when the root page is copied to another in
2896
btr_root_raise_and_insert. Note that we leave lock structs on the
2897
root page, even though they do not make sense on other than leaf
2898
pages: the reason is that in a pessimistic update the infimum record
2899
of the root page will act as a dummy carrier of the locks of the record
2903
lock_update_root_raise(
2904
/*===================*/
2905
const buf_block_t* block, /*!< in: index page to which copied */
2906
const buf_block_t* root) /*!< in: root page */
2908
lock_mutex_enter_kernel();
2910
/* Move the locks on the supremum of the root to the supremum
2913
lock_rec_move(block, root,
2914
PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
2915
lock_mutex_exit_kernel();
2918
/*************************************************************//**
2919
Updates the lock table when a page is copied to another and the original page
2920
is removed from the chain of leaf pages, except if page is the root! */
2923
lock_update_copy_and_discard(
2924
/*=========================*/
2925
const buf_block_t* new_block, /*!< in: index page to
2927
const buf_block_t* block) /*!< in: index page;
2930
lock_mutex_enter_kernel();
2932
/* Move the locks on the supremum of the old page to the supremum
2935
lock_rec_move(new_block, block,
2936
PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
2937
lock_rec_free_all_from_discard_page(block);
2939
lock_mutex_exit_kernel();
2942
/*************************************************************//**
2943
Updates the lock table when a page is split to the left. */
2946
lock_update_split_left(
2947
/*===================*/
2948
const buf_block_t* right_block, /*!< in: right page */
2949
const buf_block_t* left_block) /*!< in: left page */
2951
ulint heap_no = lock_get_min_heap_no(right_block);
2953
lock_mutex_enter_kernel();
2955
/* Inherit the locks to the supremum of the left page from the
2956
successor of the infimum on the right page */
2958
lock_rec_inherit_to_gap(left_block, right_block,
2959
PAGE_HEAP_NO_SUPREMUM, heap_no);
2961
lock_mutex_exit_kernel();
2964
/*************************************************************//**
2965
Updates the lock table when a page is merged to the left. */
2968
lock_update_merge_left(
2969
/*===================*/
2970
const buf_block_t* left_block, /*!< in: left page to
2972
const rec_t* orig_pred, /*!< in: original predecessor
2973
of supremum on the left page
2975
const buf_block_t* right_block) /*!< in: merged index page
2976
which will be discarded */
2978
const rec_t* left_next_rec;
2980
ut_ad(left_block->frame == page_align(orig_pred));
2982
lock_mutex_enter_kernel();
2984
left_next_rec = page_rec_get_next_const(orig_pred);
2986
if (!page_rec_is_supremum(left_next_rec)) {
2988
/* Inherit the locks on the supremum of the left page to the
2989
first record which was moved from the right page */
2991
lock_rec_inherit_to_gap(left_block, left_block,
2992
page_rec_get_heap_no(left_next_rec),
2993
PAGE_HEAP_NO_SUPREMUM);
2995
/* Reset the locks on the supremum of the left page,
2996
releasing waiting transactions */
2998
lock_rec_reset_and_release_wait(left_block,
2999
PAGE_HEAP_NO_SUPREMUM);
3002
/* Move the locks from the supremum of right page to the supremum
3005
lock_rec_move(left_block, right_block,
3006
PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
3008
lock_rec_free_all_from_discard_page(right_block);
3010
lock_mutex_exit_kernel();
3013
/*************************************************************//**
3014
Resets the original locks on heir and replaces them with gap type locks
3015
inherited from rec. */
3018
lock_rec_reset_and_inherit_gap_locks(
3019
/*=================================*/
3020
const buf_block_t* heir_block, /*!< in: block containing the
3021
record which inherits */
3022
const buf_block_t* block, /*!< in: block containing the
3023
record from which inherited;
3024
does NOT reset the locks on
3026
ulint heir_heap_no, /*!< in: heap_no of the
3027
inheriting record */
3028
ulint heap_no) /*!< in: heap_no of the
3031
mutex_enter(&kernel_mutex);
3033
lock_rec_reset_and_release_wait(heir_block, heir_heap_no);
3035
lock_rec_inherit_to_gap(heir_block, block, heir_heap_no, heap_no);
3037
mutex_exit(&kernel_mutex);
3040
/*************************************************************//**
3041
Updates the lock table when a page is discarded. */
3044
lock_update_discard(
3045
/*================*/
3046
const buf_block_t* heir_block, /*!< in: index page
3047
which will inherit the locks */
3048
ulint heir_heap_no, /*!< in: heap_no of the record
3049
which will inherit the locks */
3050
const buf_block_t* block) /*!< in: index page
3051
which will be discarded */
3053
const page_t* page = block->frame;
3057
lock_mutex_enter_kernel();
3059
if (!lock_rec_get_first_on_page(block)) {
3060
/* No locks exist on page, nothing to do */
3062
lock_mutex_exit_kernel();
3067
/* Inherit all the locks on the page to the record and reset all
3068
the locks on the page */
3070
if (page_is_comp(page)) {
3071
rec = page + PAGE_NEW_INFIMUM;
3074
heap_no = rec_get_heap_no_new(rec);
3076
lock_rec_inherit_to_gap(heir_block, block,
3077
heir_heap_no, heap_no);
3079
lock_rec_reset_and_release_wait(block, heap_no);
3081
rec = page + rec_get_next_offs(rec, TRUE);
3082
} while (heap_no != PAGE_HEAP_NO_SUPREMUM);
3084
rec = page + PAGE_OLD_INFIMUM;
3087
heap_no = rec_get_heap_no_old(rec);
3089
lock_rec_inherit_to_gap(heir_block, block,
3090
heir_heap_no, heap_no);
3092
lock_rec_reset_and_release_wait(block, heap_no);
3094
rec = page + rec_get_next_offs(rec, FALSE);
3095
} while (heap_no != PAGE_HEAP_NO_SUPREMUM);
3098
lock_rec_free_all_from_discard_page(block);
3100
lock_mutex_exit_kernel();
3103
/*************************************************************//**
3104
Updates the lock table when a new user record is inserted. */
3109
const buf_block_t* block, /*!< in: buffer block containing rec */
3110
const rec_t* rec) /*!< in: the inserted record */
3112
ulint receiver_heap_no;
3113
ulint donator_heap_no;
3115
ut_ad(block->frame == page_align(rec));
3117
/* Inherit the gap-locking locks for rec, in gap mode, from the next
3120
if (page_rec_is_comp(rec)) {
3121
receiver_heap_no = rec_get_heap_no_new(rec);
3122
donator_heap_no = rec_get_heap_no_new(
3123
page_rec_get_next_low(rec, TRUE));
3125
receiver_heap_no = rec_get_heap_no_old(rec);
3126
donator_heap_no = rec_get_heap_no_old(
3127
page_rec_get_next_low(rec, FALSE));
3130
lock_mutex_enter_kernel();
3131
lock_rec_inherit_to_gap_if_gap_lock(block,
3132
receiver_heap_no, donator_heap_no);
3133
lock_mutex_exit_kernel();
3136
/*************************************************************//**
3137
Updates the lock table when a record is removed. */
3142
const buf_block_t* block, /*!< in: buffer block containing rec */
3143
const rec_t* rec) /*!< in: the record to be removed */
3145
const page_t* page = block->frame;
3149
ut_ad(page == page_align(rec));
3151
if (page_is_comp(page)) {
3152
heap_no = rec_get_heap_no_new(rec);
3153
next_heap_no = rec_get_heap_no_new(page
3154
+ rec_get_next_offs(rec,
3157
heap_no = rec_get_heap_no_old(rec);
3158
next_heap_no = rec_get_heap_no_old(page
3159
+ rec_get_next_offs(rec,
3163
lock_mutex_enter_kernel();
3165
/* Let the next record inherit the locks from rec, in gap mode */
3167
lock_rec_inherit_to_gap(block, block, next_heap_no, heap_no);
3169
/* Reset the lock bits on rec and release waiting transactions */
3171
lock_rec_reset_and_release_wait(block, heap_no);
3173
lock_mutex_exit_kernel();
3176
/*********************************************************************//**
3177
Stores on the page infimum record the explicit locks of another record.
3178
This function is used to store the lock state of a record when it is
3179
updated and the size of the record changes in the update. The record
3180
is moved in such an update, perhaps to another page. The infimum record
3181
acts as a dummy carrier record, taking care of lock releases while the
3182
actual record is being moved. */
3185
lock_rec_store_on_page_infimum(
3186
/*===========================*/
3187
const buf_block_t* block, /*!< in: buffer block containing rec */
3188
const rec_t* rec) /*!< in: record whose lock state
3189
is stored on the infimum
3190
record of the same page; lock
3191
bits are reset on the
3194
ulint heap_no = page_rec_get_heap_no(rec);
3196
ut_ad(block->frame == page_align(rec));
3198
lock_mutex_enter_kernel();
3200
lock_rec_move(block, block, PAGE_HEAP_NO_INFIMUM, heap_no);
3202
lock_mutex_exit_kernel();
3205
/*********************************************************************//**
3206
Restores the state of explicit lock requests on a single record, where the
3207
state was stored on the infimum of the page. */
3210
lock_rec_restore_from_page_infimum(
3211
/*===============================*/
3212
const buf_block_t* block, /*!< in: buffer block containing rec */
3213
const rec_t* rec, /*!< in: record whose lock state
3215
const buf_block_t* donator)/*!< in: page (rec is not
3216
necessarily on this page)
3217
whose infimum stored the lock
3218
state; lock bits are reset on
3221
ulint heap_no = page_rec_get_heap_no(rec);
3223
lock_mutex_enter_kernel();
3225
lock_rec_move(block, donator, heap_no, PAGE_HEAP_NO_INFIMUM);
3227
lock_mutex_exit_kernel();
3230
/*=========== DEADLOCK CHECKING ======================================*/
3232
/********************************************************************//**
3233
Checks if a lock request results in a deadlock.
3234
@return TRUE if a deadlock was detected and we chose trx as a victim;
3235
FALSE if no deadlock, or there was a deadlock, but we chose other
3236
transaction(s) as victim(s) */
3239
lock_deadlock_occurs(
3240
/*=================*/
3241
lock_t* lock, /*!< in: lock the transaction is requesting */
3242
trx_t* trx) /*!< in: transaction */
3244
dict_table_t* table;
3245
dict_index_t* index;
3252
ut_ad(mutex_own(&kernel_mutex));
3254
/* We check that adding this trx to the waits-for graph
3255
does not produce a cycle. First mark all active transactions
3258
mark_trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
3261
mark_trx->deadlock_mark = 0;
3262
mark_trx = UT_LIST_GET_NEXT(trx_list, mark_trx);
3265
ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0);
3267
if (ret == LOCK_VICTIM_IS_OTHER) {
3268
/* We chose some other trx as a victim: retry if there still
3274
if (UNIV_UNLIKELY(ret == LOCK_VICTIM_IS_START)) {
3275
if (lock_get_type_low(lock) & LOCK_TABLE) {
3276
table = lock->un_member.tab_lock.table;
3279
index = lock->index;
3280
table = index->table;
3283
lock_deadlock_found = TRUE;
3285
fputs("*** WE ROLL BACK TRANSACTION (2)\n",
3286
lock_latest_err_file);
3294
/********************************************************************//**
3295
Looks recursively for a deadlock.
3296
@return 0 if no deadlock found, LOCK_VICTIM_IS_START if there was a
3297
deadlock and we chose 'start' as the victim, LOCK_VICTIM_IS_OTHER if a
3298
deadlock was found and we chose some other trx as a victim: we must do
3299
the search again in this last case because there may be another
3303
lock_deadlock_recursive(
3304
/*====================*/
3305
trx_t* start, /*!< in: recursion starting point */
3306
trx_t* trx, /*!< in: a transaction waiting for a lock */
3307
lock_t* wait_lock, /*!< in: the lock trx is waiting to be granted */
3308
ulint* cost, /*!< in/out: number of calculation steps thus
3309
far: if this exceeds LOCK_MAX_N_STEPS_...
3310
we return LOCK_VICTIM_IS_START */
3311
ulint depth) /*!< in: recursion depth: if this exceeds
3312
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
3313
return LOCK_VICTIM_IS_START */
3316
ulint bit_no = ULINT_UNDEFINED;
3323
ut_ad(mutex_own(&kernel_mutex));
3325
if (trx->deadlock_mark == 1) {
3326
/* We have already exhaustively searched the subtree starting
3336
if (lock_get_type_low(wait_lock) == LOCK_REC) {
3338
bit_no = lock_rec_find_set_bit(wait_lock);
3340
ut_a(bit_no != ULINT_UNDEFINED);
3343
/* Look at the locks ahead of wait_lock in the lock queue */
3346
if (lock_get_type_low(lock) & LOCK_TABLE) {
3348
lock = UT_LIST_GET_PREV(un_member.tab_lock.locks,
3351
ut_ad(lock_get_type_low(lock) == LOCK_REC);
3352
ut_a(bit_no != ULINT_UNDEFINED);
3354
lock = (lock_t*) lock_rec_get_prev(lock, bit_no);
3358
/* We can mark this subtree as searched */
3359
trx->deadlock_mark = 1;
3364
if (lock_has_to_wait(wait_lock, lock)) {
3367
= depth > LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK
3368
|| *cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK;
3370
lock_trx = lock->trx;
3372
if (lock_trx == start || too_far) {
3374
/* We came back to the recursion starting
3375
point: a deadlock detected; or we have
3376
searched the waits-for graph too long */
3378
FILE* ef = lock_latest_err_file;
3381
ut_print_timestamp(ef);
3383
fputs("\n*** (1) TRANSACTION:\n", ef);
3385
trx_print(ef, wait_lock->trx, 3000);
3387
fputs("*** (1) WAITING FOR THIS LOCK"
3388
" TO BE GRANTED:\n", ef);
3390
if (lock_get_type_low(wait_lock) == LOCK_REC) {
3391
lock_rec_print(ef, wait_lock);
3393
lock_table_print(ef, wait_lock);
3396
fputs("*** (2) TRANSACTION:\n", ef);
3398
trx_print(ef, lock->trx, 3000);
3400
fputs("*** (2) HOLDS THE LOCK(S):\n", ef);
3402
if (lock_get_type_low(lock) == LOCK_REC) {
3403
lock_rec_print(ef, lock);
3405
lock_table_print(ef, lock);
3408
fputs("*** (2) WAITING FOR THIS LOCK"
3409
" TO BE GRANTED:\n", ef);
3411
if (lock_get_type_low(start->wait_lock)
3413
lock_rec_print(ef, start->wait_lock);
3415
lock_table_print(ef, start->wait_lock);
3418
if (lock_print_waits) {
3419
fputs("Deadlock detected"
3420
" or too long search\n",
3423
#endif /* UNIV_DEBUG */
3426
fputs("TOO DEEP OR LONG SEARCH"
3427
" IN THE LOCK TABLE"
3428
" WAITS-FOR GRAPH\n", ef);
3430
return(LOCK_VICTIM_IS_START);
3433
if (trx_weight_cmp(wait_lock->trx,
3435
/* Our recursion starting point
3436
transaction is 'smaller', let us
3437
choose 'start' as the victim and roll
3440
return(LOCK_VICTIM_IS_START);
3443
lock_deadlock_found = TRUE;
3445
/* Let us choose the transaction of wait_lock
3446
as a victim to try to avoid deadlocking our
3447
recursion starting point transaction */
3449
fputs("*** WE ROLL BACK TRANSACTION (1)\n",
3452
wait_lock->trx->was_chosen_as_deadlock_victim
3455
lock_cancel_waiting_and_release(wait_lock);
3457
/* Since trx and wait_lock are no longer
3458
in the waits-for graph, we can return FALSE;
3459
note that our selective algorithm can choose
3460
several transactions as victims, but still
3461
we may end up rolling back also the recursion
3462
starting point transaction! */
3464
return(LOCK_VICTIM_IS_OTHER);
3467
if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) {
3469
/* Another trx ahead has requested lock in an
3470
incompatible mode, and is itself waiting for
3473
ret = lock_deadlock_recursive(
3475
lock_trx->wait_lock, cost, depth + 1);
3482
}/* end of the 'for (;;)'-loop */
3485
/*========================= TABLE LOCKS ==============================*/
3487
/*********************************************************************//**
3488
Creates a table lock object and adds it as the last in the lock queue
3489
of the table. Does NOT check for deadlocks or lock compatibility.
3490
@return own: new lock object */
3495
dict_table_t* table, /*!< in: database table in dictionary cache */
3496
ulint type_mode,/*!< in: lock mode possibly ORed with
3498
trx_t* trx) /*!< in: trx */
3502
ut_ad(table && trx);
3503
ut_ad(mutex_own(&kernel_mutex));
3505
if ((type_mode & LOCK_MODE_MASK) == LOCK_AUTO_INC) {
3506
++table->n_waiting_or_granted_auto_inc_locks;
3509
/* For AUTOINC locking we reuse the lock instance only if
3510
there is no wait involved else we allocate the waiting lock
3511
from the transaction lock heap. */
3512
if (type_mode == LOCK_AUTO_INC) {
3514
lock = table->autoinc_lock;
3516
table->autoinc_trx = trx;
3518
ib_vector_push(trx->autoinc_locks, lock);
3520
lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t));
3523
UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
3525
lock->type_mode = type_mode | LOCK_TABLE;
3528
lock->un_member.tab_lock.table = table;
3530
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
3532
if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
3534
lock_set_lock_and_trx_wait(lock, trx);
3540
/*************************************************************//**
3541
Removes a table lock request from the queue and the trx list of locks;
3542
this is a low-level function which does NOT check if waiting requests
3543
can now be granted. */
3546
lock_table_remove_low(
3547
/*==================*/
3548
lock_t* lock) /*!< in: table lock */
3551
dict_table_t* table;
3553
ut_ad(mutex_own(&kernel_mutex));
3556
table = lock->un_member.tab_lock.table;
3558
/* Remove the table from the transaction's AUTOINC vector, if
3559
the lock that is being release is an AUTOINC lock. */
3560
if (lock_get_mode(lock) == LOCK_AUTO_INC) {
3562
/* The table's AUTOINC lock can get transferred to
3563
another transaction before we get here. */
3564
if (table->autoinc_trx == trx) {
3565
table->autoinc_trx = NULL;
3568
/* The locks must be freed in the reverse order from
3569
the one in which they were acquired. This is to avoid
3570
traversing the AUTOINC lock vector unnecessarily.
3572
We only store locks that were granted in the
3573
trx->autoinc_locks vector (see lock_table_create()
3574
and lock_grant()). Therefore it can be empty and we
3575
need to check for that. */
3577
if (!ib_vector_is_empty(trx->autoinc_locks)) {
3578
lock_t* autoinc_lock;
3580
autoinc_lock = ib_vector_pop(trx->autoinc_locks);
3581
ut_a(autoinc_lock == lock);
3584
ut_a(table->n_waiting_or_granted_auto_inc_locks > 0);
3585
--table->n_waiting_or_granted_auto_inc_locks;
3588
UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock);
3589
UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock);
3592
/*********************************************************************//**
3593
Enqueues a waiting request for a table lock which cannot be granted
3594
immediately. Checks for deadlocks.
3595
@return DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED, or
3596
DB_SUCCESS; DB_SUCCESS means that there was a deadlock, but another
3597
transaction was chosen as a victim, and we got the lock immediately:
3598
no need to wait then */
3601
lock_table_enqueue_waiting(
3602
/*=======================*/
3603
ulint mode, /*!< in: lock mode this transaction is
3605
dict_table_t* table, /*!< in: table */
3606
que_thr_t* thr) /*!< in: query thread */
3611
ut_ad(mutex_own(&kernel_mutex));
3613
/* Test if there already is some other reason to suspend thread:
3614
we do not enqueue a lock request if the query thread should be
3617
if (que_thr_stop(thr)) {
3620
return(DB_QUE_THR_SUSPENDED);
3623
trx = thr_get_trx(thr);
3625
switch (trx_get_dict_operation(trx)) {
3626
case TRX_DICT_OP_NONE:
3628
case TRX_DICT_OP_TABLE:
3629
case TRX_DICT_OP_INDEX:
3630
ut_print_timestamp(stderr);
3631
fputs(" InnoDB: Error: a table lock wait happens"
3632
" in a dictionary operation!\n"
3633
"InnoDB: Table name ", stderr);
3634
ut_print_name(stderr, trx, TRUE, table->name);
3636
"InnoDB: Submit a detailed bug report"
3637
" to http://bugs.mysql.com\n",
3641
/* Enqueue the lock request that will wait to be granted */
3643
lock = lock_table_create(table, mode | LOCK_WAIT, trx);
3645
/* Check if a deadlock occurs: if yes, remove the lock request and
3646
return an error code */
3648
if (lock_deadlock_occurs(lock, trx)) {
3650
lock_reset_lock_and_trx_wait(lock);
3651
lock_table_remove_low(lock);
3653
return(DB_DEADLOCK);
3656
if (trx->wait_lock == NULL) {
3657
/* Deadlock resolution chose another transaction as a victim,
3658
and we accidentally got our lock granted! */
3663
trx->que_state = TRX_QUE_LOCK_WAIT;
3664
trx->was_chosen_as_deadlock_victim = FALSE;
3665
trx->wait_started = time(NULL);
3667
ut_a(que_thr_stop(thr));
3669
return(DB_LOCK_WAIT);
3672
/*********************************************************************//**
3673
Checks if other transactions have an incompatible mode lock request in
3677
lock_table_other_has_incompatible(
3678
/*==============================*/
3679
trx_t* trx, /*!< in: transaction, or NULL if all
3680
transactions should be included */
3681
ulint wait, /*!< in: LOCK_WAIT if also waiting locks are
3682
taken into account, or 0 if not */
3683
dict_table_t* table, /*!< in: table */
3684
enum lock_mode mode) /*!< in: lock mode */
3688
ut_ad(mutex_own(&kernel_mutex));
3690
lock = UT_LIST_GET_LAST(table->locks);
3692
while (lock != NULL) {
3694
if ((lock->trx != trx)
3695
&& (!lock_mode_compatible(lock_get_mode(lock), mode))
3696
&& (wait || !(lock_get_wait(lock)))) {
3701
lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
3707
/*********************************************************************//**
3708
Locks the specified database table in the mode given. If the lock cannot
3709
be granted immediately, the query thread is put to wait.
3710
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
3715
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG bit is set,
3717
dict_table_t* table, /*!< in: database table in dictionary cache */
3718
enum lock_mode mode, /*!< in: lock mode */
3719
que_thr_t* thr) /*!< in: query thread */
3724
ut_ad(table && thr);
3726
if (flags & BTR_NO_LOCKING_FLAG) {
3733
trx = thr_get_trx(thr);
3735
lock_mutex_enter_kernel();
3737
/* Look for stronger locks the same trx already has on the table */
3739
if (lock_table_has(trx, table, mode)) {
3741
lock_mutex_exit_kernel();
3746
/* We have to check if the new lock is compatible with any locks
3747
other transactions have in the table lock queue. */
3749
if (lock_table_other_has_incompatible(trx, LOCK_WAIT, table, mode)) {
3751
/* Another trx has a request on the table in an incompatible
3752
mode: this trx may have to wait */
3754
err = lock_table_enqueue_waiting(mode | flags, table, thr);
3756
lock_mutex_exit_kernel();
3761
lock_table_create(table, mode | flags, trx);
3763
ut_a(!flags || mode == LOCK_S || mode == LOCK_X);
3765
lock_mutex_exit_kernel();
3770
/*********************************************************************//**
3771
Checks if a waiting table lock request still has to wait in a queue.
3772
@return TRUE if still has to wait */
3775
lock_table_has_to_wait_in_queue(
3776
/*============================*/
3777
lock_t* wait_lock) /*!< in: waiting table lock */
3779
dict_table_t* table;
3782
ut_ad(mutex_own(&kernel_mutex));
3783
ut_ad(lock_get_wait(wait_lock));
3785
table = wait_lock->un_member.tab_lock.table;
3787
lock = UT_LIST_GET_FIRST(table->locks);
3789
while (lock != wait_lock) {
3791
if (lock_has_to_wait(wait_lock, lock)) {
3796
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock);
3802
/*************************************************************//**
3803
Removes a table lock request, waiting or granted, from the queue and grants
3804
locks to other transactions in the queue, if they now are entitled to a
3810
lock_t* in_lock)/*!< in: table lock object; transactions waiting
3811
behind will get their lock requests granted, if
3812
they are now qualified to it */
3816
ut_ad(mutex_own(&kernel_mutex));
3817
ut_a(lock_get_type_low(in_lock) == LOCK_TABLE);
3819
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
3821
lock_table_remove_low(in_lock);
3823
/* Check if waiting locks in the queue can now be granted: grant
3824
locks if there are no conflicting locks ahead. */
3826
while (lock != NULL) {
3828
if (lock_get_wait(lock)
3829
&& !lock_table_has_to_wait_in_queue(lock)) {
3831
/* Grant the lock */
3835
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock);
3839
/*=========================== LOCK RELEASE ==============================*/
3841
/*************************************************************//**
3842
Removes a granted record lock of a transaction from the queue and grants
3843
locks to other transactions waiting in the queue if they now are entitled
3849
trx_t* trx, /*!< in: transaction that has
3850
set a record lock */
3851
const buf_block_t* block, /*!< in: buffer block containing rec */
3852
const rec_t* rec, /*!< in: record */
3853
enum lock_mode lock_mode)/*!< in: LOCK_S or LOCK_X */
3856
lock_t* release_lock = NULL;
3860
ut_ad(block->frame == page_align(rec));
3862
heap_no = page_rec_get_heap_no(rec);
3864
mutex_enter(&kernel_mutex);
3866
lock = lock_rec_get_first(block, heap_no);
3868
/* Find the last lock with the same lock_mode and transaction
3871
while (lock != NULL) {
3872
if (lock->trx == trx && lock_get_mode(lock) == lock_mode) {
3873
release_lock = lock;
3874
ut_a(!lock_get_wait(lock));
3877
lock = lock_rec_get_next(heap_no, lock);
3880
/* If a record lock is found, release the record lock */
3882
if (UNIV_LIKELY(release_lock != NULL)) {
3883
lock_rec_reset_nth_bit(release_lock, heap_no);
3885
mutex_exit(&kernel_mutex);
3886
ut_print_timestamp(stderr);
3888
" InnoDB: Error: unlock row could not"
3889
" find a %lu mode lock on the record\n",
3895
/* Check if we can now grant waiting lock requests */
3897
lock = lock_rec_get_first(block, heap_no);
3899
while (lock != NULL) {
3900
if (lock_get_wait(lock)
3901
&& !lock_rec_has_to_wait_in_queue(lock)) {
3903
/* Grant the lock */
3907
lock = lock_rec_get_next(heap_no, lock);
3910
mutex_exit(&kernel_mutex);
3913
/*********************************************************************//**
3914
Releases transaction locks, and releases possible other transactions waiting
3915
because of these locks. */
3918
lock_release_off_kernel(
3919
/*====================*/
3920
trx_t* trx) /*!< in: transaction */
3922
dict_table_t* table;
3926
ut_ad(mutex_own(&kernel_mutex));
3928
lock = UT_LIST_GET_LAST(trx->trx_locks);
3932
while (lock != NULL) {
3936
if (lock_get_type_low(lock) == LOCK_REC) {
3938
lock_rec_dequeue_from_page(lock);
3940
ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
3942
if (lock_get_mode(lock) != LOCK_IS
3943
&& !ut_dulint_is_zero(trx->undo_no)) {
3945
/* The trx may have modified the table. We
3946
block the use of the MySQL query cache for
3947
all currently active transactions. */
3949
table = lock->un_member.tab_lock.table;
3951
table->query_cache_inv_trx_id
3952
= trx_sys->max_trx_id;
3955
lock_table_dequeue(lock);
3958
if (count == LOCK_RELEASE_KERNEL_INTERVAL) {
3959
/* Release the kernel mutex for a while, so that we
3960
do not monopolize it */
3962
lock_mutex_exit_kernel();
3964
lock_mutex_enter_kernel();
3969
lock = UT_LIST_GET_LAST(trx->trx_locks);
3972
ut_a(ib_vector_size(trx->autoinc_locks) == 0);
3974
mem_heap_empty(trx->lock_heap);
3977
/*********************************************************************//**
3978
Cancels a waiting lock request and releases possible other transactions
3979
waiting behind it. */
3982
lock_cancel_waiting_and_release(
3983
/*============================*/
3984
lock_t* lock) /*!< in: waiting lock request */
3986
ut_ad(mutex_own(&kernel_mutex));
3988
if (lock_get_type_low(lock) == LOCK_REC) {
3990
lock_rec_dequeue_from_page(lock);
3992
ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
3994
if (lock->trx->autoinc_locks != NULL) {
3995
/* Release the transaction's AUTOINC locks/ */
3996
lock_release_autoinc_locks(lock->trx);
3999
lock_table_dequeue(lock);
4002
/* Reset the wait flag and the back pointer to lock in trx */
4004
lock_reset_lock_and_trx_wait(lock);
4006
/* The following function releases the trx from lock wait */
4008
trx_end_lock_wait(lock->trx);
4011
/* True if a lock mode is S or X */
4012
#define IS_LOCK_S_OR_X(lock) \
4013
(lock_get_mode(lock) == LOCK_S \
4014
|| lock_get_mode(lock) == LOCK_X)
4017
/*********************************************************************//**
4018
Removes locks of a transaction on a table to be dropped.
4019
If remove_also_table_sx_locks is TRUE then table-level S and X locks are
4020
also removed in addition to other table-level and record-level locks.
4021
No lock, that is going to be removed, is allowed to be a wait lock. */
4024
lock_remove_all_on_table_for_trx(
4025
/*=============================*/
4026
dict_table_t* table, /*!< in: table to be dropped */
4027
trx_t* trx, /*!< in: a transaction */
4028
ibool remove_also_table_sx_locks)/*!< in: also removes
4029
table S and X locks */
4034
ut_ad(mutex_own(&kernel_mutex));
4036
lock = UT_LIST_GET_LAST(trx->trx_locks);
4038
while (lock != NULL) {
4039
prev_lock = UT_LIST_GET_PREV(trx_locks, lock);
4041
if (lock_get_type_low(lock) == LOCK_REC
4042
&& lock->index->table == table) {
4043
ut_a(!lock_get_wait(lock));
4045
lock_rec_discard(lock);
4046
} else if (lock_get_type_low(lock) & LOCK_TABLE
4047
&& lock->un_member.tab_lock.table == table
4048
&& (remove_also_table_sx_locks
4049
|| !IS_LOCK_S_OR_X(lock))) {
4051
ut_a(!lock_get_wait(lock));
4053
lock_table_remove_low(lock);
4060
/*********************************************************************//**
4061
Removes locks on a table to be dropped or truncated.
4062
If remove_also_table_sx_locks is TRUE then table-level S and X locks are
4063
also removed in addition to other table-level and record-level locks.
4064
No lock, that is going to be removed, is allowed to be a wait lock. */
4067
lock_remove_all_on_table(
4068
/*=====================*/
4069
dict_table_t* table, /*!< in: table to be dropped
4071
ibool remove_also_table_sx_locks)/*!< in: also removes
4072
table S and X locks */
4077
mutex_enter(&kernel_mutex);
4079
lock = UT_LIST_GET_FIRST(table->locks);
4081
while (lock != NULL) {
4083
prev_lock = UT_LIST_GET_PREV(un_member.tab_lock.locks,
4086
/* If we should remove all locks (remove_also_table_sx_locks
4087
is TRUE), or if the lock is not table-level S or X lock,
4088
then check we are not going to remove a wait lock. */
4089
if (remove_also_table_sx_locks
4090
|| !(lock_get_type(lock) == LOCK_TABLE
4091
&& IS_LOCK_S_OR_X(lock))) {
4093
ut_a(!lock_get_wait(lock));
4096
lock_remove_all_on_table_for_trx(table, lock->trx,
4097
remove_also_table_sx_locks);
4099
if (prev_lock == NULL) {
4100
if (lock == UT_LIST_GET_FIRST(table->locks)) {
4101
/* lock was not removed, pick its successor */
4102
lock = UT_LIST_GET_NEXT(
4103
un_member.tab_lock.locks, lock);
4105
/* lock was removed, pick the first one */
4106
lock = UT_LIST_GET_FIRST(table->locks);
4108
} else if (UT_LIST_GET_NEXT(un_member.tab_lock.locks,
4109
prev_lock) != lock) {
4110
/* If lock was removed by
4111
lock_remove_all_on_table_for_trx() then pick the
4112
successor of prev_lock ... */
4113
lock = UT_LIST_GET_NEXT(
4114
un_member.tab_lock.locks, prev_lock);
4116
/* ... otherwise pick the successor of lock. */
4117
lock = UT_LIST_GET_NEXT(
4118
un_member.tab_lock.locks, lock);
4122
mutex_exit(&kernel_mutex);
4125
/*===================== VALIDATION AND DEBUGGING ====================*/
4127
/*********************************************************************//**
4128
Prints info of a table lock. */
4133
FILE* file, /*!< in: file where to print */
4134
const lock_t* lock) /*!< in: table type lock */
4136
ut_ad(mutex_own(&kernel_mutex));
4137
ut_a(lock_get_type_low(lock) == LOCK_TABLE);
4139
fputs("TABLE LOCK table ", file);
4140
ut_print_name(file, lock->trx, TRUE,
4141
lock->un_member.tab_lock.table->name);
4142
fprintf(file, " trx id " TRX_ID_FMT,
4143
TRX_ID_PREP_PRINTF(lock->trx->id));
4145
if (lock_get_mode(lock) == LOCK_S) {
4146
fputs(" lock mode S", file);
4147
} else if (lock_get_mode(lock) == LOCK_X) {
4148
fputs(" lock mode X", file);
4149
} else if (lock_get_mode(lock) == LOCK_IS) {
4150
fputs(" lock mode IS", file);
4151
} else if (lock_get_mode(lock) == LOCK_IX) {
4152
fputs(" lock mode IX", file);
4153
} else if (lock_get_mode(lock) == LOCK_AUTO_INC) {
4154
fputs(" lock mode AUTO-INC", file);
4156
fprintf(file, " unknown lock mode %lu",
4157
(ulong) lock_get_mode(lock));
4160
if (lock_get_wait(lock)) {
4161
fputs(" waiting", file);
4167
/*********************************************************************//**
4168
Prints info of a record lock. */
4173
FILE* file, /*!< in: file where to print */
4174
const lock_t* lock) /*!< in: record type lock */
4176
const buf_block_t* block;
4181
mem_heap_t* heap = NULL;
4182
ulint offsets_[REC_OFFS_NORMAL_SIZE];
4183
ulint* offsets = offsets_;
4184
rec_offs_init(offsets_);
4186
ut_ad(mutex_own(&kernel_mutex));
4187
ut_a(lock_get_type_low(lock) == LOCK_REC);
4189
space = lock->un_member.rec_lock.space;
4190
page_no = lock->un_member.rec_lock.page_no;
4192
fprintf(file, "RECORD LOCKS space id %lu page no %lu n bits %lu ",
4193
(ulong) space, (ulong) page_no,
4194
(ulong) lock_rec_get_n_bits(lock));
4195
dict_index_name_print(file, lock->trx, lock->index);
4196
fprintf(file, " trx id " TRX_ID_FMT,
4197
TRX_ID_PREP_PRINTF(lock->trx->id));
4199
if (lock_get_mode(lock) == LOCK_S) {
4200
fputs(" lock mode S", file);
4201
} else if (lock_get_mode(lock) == LOCK_X) {
4202
fputs(" lock_mode X", file);
4207
if (lock_rec_get_gap(lock)) {
4208
fputs(" locks gap before rec", file);
4211
if (lock_rec_get_rec_not_gap(lock)) {
4212
fputs(" locks rec but not gap", file);
4215
if (lock_rec_get_insert_intention(lock)) {
4216
fputs(" insert intention", file);
4219
if (lock_get_wait(lock)) {
4220
fputs(" waiting", file);
4227
block = buf_page_try_get(space, page_no, &mtr);
4230
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
4232
if (lock_rec_get_nth_bit(lock, i)) {
4235
= page_find_rec_with_heap_no(
4236
buf_block_get_frame(block), i);
4237
offsets = rec_get_offsets(
4238
rec, lock->index, offsets,
4239
ULINT_UNDEFINED, &heap);
4241
fprintf(file, "Record lock, heap no %lu ",
4243
rec_print_new(file, rec, offsets);
4248
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
4249
fprintf(file, "Record lock, heap no %lu\n", (ulong) i);
4254
if (UNIV_LIKELY_NULL(heap)) {
4255
mem_heap_free(heap);
4260
/* Print the number of lock structs from lock_print_info_summary() only
4261
in non-production builds for performance reasons, see
4262
http://bugs.mysql.com/36942 */
4263
#define PRINT_NUM_OF_LOCK_STRUCTS
4264
#endif /* UNIV_DEBUG */
4266
#ifdef PRINT_NUM_OF_LOCK_STRUCTS
4267
/*********************************************************************//**
4268
Calculates the number of record lock structs in the record lock hash table.
4269
@return number of record locks */
4272
lock_get_n_rec_locks(void)
4273
/*======================*/
4279
ut_ad(mutex_own(&kernel_mutex));
4281
for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
4283
lock = HASH_GET_FIRST(lock_sys->rec_hash, i);
4288
lock = HASH_GET_NEXT(hash, lock);
4294
#endif /* PRINT_NUM_OF_LOCK_STRUCTS */
4296
/*********************************************************************//**
4297
Prints info of locks for all transactions. */
4300
lock_print_info_summary(
4301
/*====================*/
4302
FILE* file) /*!< in: file where to print */
4304
/* We must protect the MySQL thd->query field with a MySQL mutex, and
4305
because the MySQL mutex must be reserved before the kernel_mutex of
4306
InnoDB, we call innobase_mysql_prepare_print_arbitrary_thd() here. */
4308
innobase_mysql_prepare_print_arbitrary_thd();
4309
lock_mutex_enter_kernel();
4311
if (lock_deadlock_found) {
4312
fputs("------------------------\n"
4313
"LATEST DETECTED DEADLOCK\n"
4314
"------------------------\n", file);
4316
ut_copy_file(file, lock_latest_err_file);
4319
fputs("------------\n"
4321
"------------\n", file);
4323
fprintf(file, "Trx id counter " TRX_ID_FMT "\n",
4324
TRX_ID_PREP_PRINTF(trx_sys->max_trx_id));
4327
"Purge done for trx's n:o < " TRX_ID_FMT
4328
" undo n:o < " TRX_ID_FMT "\n",
4329
TRX_ID_PREP_PRINTF(purge_sys->purge_trx_no),
4330
TRX_ID_PREP_PRINTF(purge_sys->purge_undo_no));
4333
"History list length %lu\n",
4334
(ulong) trx_sys->rseg_history_len);
4336
#ifdef PRINT_NUM_OF_LOCK_STRUCTS
4338
"Total number of lock structs in row lock hash table %lu\n",
4339
(ulong) lock_get_n_rec_locks());
4340
#endif /* PRINT_NUM_OF_LOCK_STRUCTS */
4343
/*********************************************************************//**
4344
Prints info of locks for each transaction. */
4347
lock_print_info_all_transactions(
4348
/*=============================*/
4349
FILE* file) /*!< in: file where to print */
4352
ibool load_page_first = TRUE;
4359
fprintf(file, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
4361
/* First print info on non-active transactions */
4363
trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
4366
if (trx->conc_state == TRX_NOT_STARTED) {
4368
trx_print(file, trx, 600);
4371
trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
4375
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
4379
/* Since we temporarily release the kernel mutex when
4380
reading a database page in below, variable trx may be
4381
obsolete now and we must loop through the trx list to
4382
get probably the same trx, or some other trx. */
4384
while (trx && (i < nth_trx)) {
4385
trx = UT_LIST_GET_NEXT(trx_list, trx);
4390
lock_mutex_exit_kernel();
4391
innobase_mysql_end_print_arbitrary_thd();
4393
ut_ad(lock_validate());
4398
if (nth_lock == 0) {
4400
trx_print(file, trx, 600);
4402
if (trx->read_view) {
4404
"Trx read view will not see trx with"
4405
" id >= " TRX_ID_FMT
4406
", sees < " TRX_ID_FMT "\n",
4408
trx->read_view->low_limit_id),
4410
trx->read_view->up_limit_id));
4413
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
4415
"------- TRX HAS BEEN WAITING %lu SEC"
4416
" FOR THIS LOCK TO BE GRANTED:\n",
4417
(ulong) difftime(time(NULL),
4418
trx->wait_started));
4420
if (lock_get_type_low(trx->wait_lock) == LOCK_REC) {
4421
lock_rec_print(file, trx->wait_lock);
4423
lock_table_print(file, trx->wait_lock);
4426
fputs("------------------\n", file);
4430
if (!srv_print_innodb_lock_monitor) {
4437
/* Look at the note about the trx loop above why we loop here:
4438
lock may be an obsolete pointer now. */
4440
lock = UT_LIST_GET_FIRST(trx->trx_locks);
4442
while (lock && (i < nth_lock)) {
4443
lock = UT_LIST_GET_NEXT(trx_locks, lock);
4454
if (lock_get_type_low(lock) == LOCK_REC) {
4455
if (load_page_first) {
4456
ulint space = lock->un_member.rec_lock.space;
4457
ulint zip_size= fil_space_get_zip_size(space);
4458
ulint page_no = lock->un_member.rec_lock.page_no;
4460
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
4462
/* It is a single table tablespace and
4463
the .ibd file is missing (TRUNCATE
4464
TABLE probably stole the locks): just
4465
print the lock without attempting to
4466
load the page in the buffer pool. */
4468
fprintf(file, "RECORD LOCKS on"
4469
" non-existing space %lu\n",
4474
lock_mutex_exit_kernel();
4475
innobase_mysql_end_print_arbitrary_thd();
4479
buf_page_get_with_no_latch(space, zip_size,
4484
load_page_first = FALSE;
4486
innobase_mysql_prepare_print_arbitrary_thd();
4487
lock_mutex_enter_kernel();
4493
lock_rec_print(file, lock);
4495
ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
4497
lock_table_print(file, lock);
4500
load_page_first = TRUE;
4504
if (nth_lock >= 10) {
4505
fputs("10 LOCKS PRINTED FOR THIS TRX:"
4506
" SUPPRESSING FURTHER PRINTS\n",
4519
/*********************************************************************//**
4520
Validates the lock queue on a table.
4521
@return TRUE if ok */
4524
lock_table_queue_validate(
4525
/*======================*/
4526
dict_table_t* table) /*!< in: table */
4530
ut_ad(mutex_own(&kernel_mutex));
4532
lock = UT_LIST_GET_FIRST(table->locks);
4535
ut_a(((lock->trx)->conc_state == TRX_ACTIVE)
4536
|| ((lock->trx)->conc_state == TRX_PREPARED)
4537
|| ((lock->trx)->conc_state == TRX_COMMITTED_IN_MEMORY));
4539
if (!lock_get_wait(lock)) {
4541
ut_a(!lock_table_other_has_incompatible(
4542
lock->trx, 0, table,
4543
lock_get_mode(lock)));
4546
ut_a(lock_table_has_to_wait_in_queue(lock));
4549
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock);
4555
/*********************************************************************//**
4556
Validates the lock queue on a single record.
4557
@return TRUE if ok */
4560
lock_rec_queue_validate(
4561
/*====================*/
4562
const buf_block_t* block, /*!< in: buffer block containing rec */
4563
const rec_t* rec, /*!< in: record to look at */
4564
dict_index_t* index, /*!< in: index, or NULL if not known */
4565
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
4572
ut_a(block->frame == page_align(rec));
4573
ut_ad(rec_offs_validate(rec, index, offsets));
4574
ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
4576
heap_no = page_rec_get_heap_no(rec);
4578
lock_mutex_enter_kernel();
4580
if (!page_rec_is_user_rec(rec)) {
4582
lock = lock_rec_get_first(block, heap_no);
4585
switch(lock->trx->conc_state) {
4588
case TRX_COMMITTED_IN_MEMORY:
4594
ut_a(trx_in_trx_list(lock->trx));
4596
if (lock_get_wait(lock)) {
4597
ut_a(lock_rec_has_to_wait_in_queue(lock));
4601
ut_a(lock->index == index);
4604
lock = lock_rec_get_next(heap_no, lock);
4607
lock_mutex_exit_kernel();
4613
else if (dict_index_is_clust(index)) {
4615
impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
4618
&& lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
4619
block, heap_no, impl_trx)) {
4621
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
4622
block, heap_no, impl_trx));
4626
/* The kernel mutex may get released temporarily in the
4627
next function call: we have to release lock table mutex
4628
to obey the latching order */
4630
impl_trx = lock_sec_rec_some_has_impl_off_kernel(
4631
rec, index, offsets);
4634
&& lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
4635
block, heap_no, impl_trx)) {
4637
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
4638
block, heap_no, impl_trx));
4642
lock = lock_rec_get_first(block, heap_no);
4645
ut_a(lock->trx->conc_state == TRX_ACTIVE
4646
|| lock->trx->conc_state == TRX_PREPARED
4647
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
4648
ut_a(trx_in_trx_list(lock->trx));
4651
ut_a(lock->index == index);
4654
if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) {
4656
enum lock_mode mode;
4658
if (lock_get_mode(lock) == LOCK_S) {
4663
ut_a(!lock_rec_other_has_expl_req(
4664
mode, 0, 0, block, heap_no, lock->trx));
4666
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
4668
ut_a(lock_rec_has_to_wait_in_queue(lock));
4671
lock = lock_rec_get_next(heap_no, lock);
4674
lock_mutex_exit_kernel();
4679
/*********************************************************************//**
4680
Validates the record lock queues on a page.
4681
@return TRUE if ok */
4684
lock_rec_validate_page(
4685
/*===================*/
4686
ulint space, /*!< in: space id */
4687
ulint page_no)/*!< in: page number */
4689
dict_index_t* index;
4699
mem_heap_t* heap = NULL;
4700
ulint offsets_[REC_OFFS_NORMAL_SIZE];
4701
ulint* offsets = offsets_;
4702
rec_offs_init(offsets_);
4704
ut_ad(!mutex_own(&kernel_mutex));
4708
zip_size = fil_space_get_zip_size(space);
4709
ut_ad(zip_size != ULINT_UNDEFINED);
4710
block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, &mtr);
4711
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
4713
page = block->frame;
4715
lock_mutex_enter_kernel();
4717
lock = lock_rec_get_first_on_page_addr(space, page_no);
4723
for (i = 0; i < nth_lock; i++) {
4725
lock = lock_rec_get_next_on_page(lock);
4732
ut_a(trx_in_trx_list(lock->trx));
4733
ut_a(lock->trx->conc_state == TRX_ACTIVE
4734
|| lock->trx->conc_state == TRX_PREPARED
4735
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
4737
for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) {
4739
if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
4741
index = lock->index;
4742
rec = page_find_rec_with_heap_no(page, i);
4744
offsets = rec_get_offsets(rec, index, offsets,
4745
ULINT_UNDEFINED, &heap);
4748
"Validating %lu %lu\n",
4749
(ulong) space, (ulong) page_no);
4751
lock_mutex_exit_kernel();
4753
lock_rec_queue_validate(block, rec, index, offsets);
4755
lock_mutex_enter_kernel();
4769
lock_mutex_exit_kernel();
4773
if (UNIV_LIKELY_NULL(heap)) {
4774
mem_heap_free(heap);
4779
/*********************************************************************//**
4780
Validates the lock system.
4781
@return TRUE if ok */
4794
lock_mutex_enter_kernel();
4796
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
4799
lock = UT_LIST_GET_FIRST(trx->trx_locks);
4802
if (lock_get_type_low(lock) & LOCK_TABLE) {
4804
lock_table_queue_validate(
4805
lock->un_member.tab_lock.table);
4808
lock = UT_LIST_GET_NEXT(trx_locks, lock);
4811
trx = UT_LIST_GET_NEXT(trx_list, trx);
4814
for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
4816
limit = ut_dulint_zero;
4819
lock = HASH_GET_FIRST(lock_sys->rec_hash, i);
4822
ut_a(trx_in_trx_list(lock->trx));
4824
space = lock->un_member.rec_lock.space;
4825
page_no = lock->un_member.rec_lock.page_no;
4828
ut_dulint_create(space, page_no),
4833
lock = HASH_GET_NEXT(hash, lock);
4841
lock_mutex_exit_kernel();
4843
lock_rec_validate_page(space, page_no);
4845
lock_mutex_enter_kernel();
4847
limit = ut_dulint_create(space, page_no + 1);
4851
lock_mutex_exit_kernel();
4855
#endif /* UNIV_DEBUG */
4856
/*============ RECORD LOCK CHECKS FOR ROW OPERATIONS ====================*/
4858
/*********************************************************************//**
4859
Checks if locks of other transactions prevent an immediate insert of
4860
a record. If they do, first tests if the query thread should anyway
4861
be suspended for some reason; if not, then puts the transaction and
4862
the query thread to the lock wait state and inserts a waiting request
4863
for a gap x-lock to the lock queue.
4864
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
4867
lock_rec_insert_check_and_lock(
4868
/*===========================*/
4869
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG bit is
4870
set, does nothing */
4871
const rec_t* rec, /*!< in: record after which to insert */
4872
buf_block_t* block, /*!< in/out: buffer block of rec */
4873
dict_index_t* index, /*!< in: index */
4874
que_thr_t* thr, /*!< in: query thread */
4875
mtr_t* mtr, /*!< in/out: mini-transaction */
4876
ibool* inherit)/*!< out: set to TRUE if the new
4877
inserted record maybe should inherit
4878
LOCK_GAP type locks from the successor
4881
const rec_t* next_rec;
4885
ulint next_rec_heap_no;
4887
ut_ad(block->frame == page_align(rec));
4889
if (flags & BTR_NO_LOCKING_FLAG) {
4894
trx = thr_get_trx(thr);
4895
next_rec = page_rec_get_next_const(rec);
4896
next_rec_heap_no = page_rec_get_heap_no(next_rec);
4898
lock_mutex_enter_kernel();
4900
/* When inserting a record into an index, the table must be at
4901
least IX-locked or we must be building an index, in which case
4902
the table must be at least S-locked. */
4903
ut_ad(lock_table_has(trx, index->table, LOCK_IX)
4904
|| (*index->name == TEMP_INDEX_PREFIX
4905
&& lock_table_has(trx, index->table, LOCK_S)));
4907
lock = lock_rec_get_first(block, next_rec_heap_no);
4909
if (UNIV_LIKELY(lock == NULL)) {
4910
/* We optimize CPU time usage in the simplest case */
4912
lock_mutex_exit_kernel();
4914
if (!dict_index_is_clust(index)) {
4915
/* Update the page max trx id field */
4916
page_update_max_trx_id(block,
4917
buf_block_get_page_zip(block),
4928
/* If another transaction has an explicit lock request which locks
4929
the gap, waiting or granted, on the successor, the insert has to wait.
4931
An exception is the case where the lock by the another transaction
4932
is a gap type lock which it placed to wait for its turn to insert. We
4933
do not consider that kind of a lock conflicting with our insert. This
4934
eliminates an unnecessary deadlock which resulted when 2 transactions
4935
had to wait for their insert. Both had waiting gap type lock requests
4936
on the successor, which produced an unnecessary deadlock. */
4938
if (lock_rec_other_has_conflicting(
4939
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
4940
block, next_rec_heap_no, trx)) {
4942
/* Note that we may get DB_SUCCESS also here! */
4943
err = lock_rec_enqueue_waiting(LOCK_X | LOCK_GAP
4944
| LOCK_INSERT_INTENTION,
4945
block, next_rec_heap_no,
4951
lock_mutex_exit_kernel();
4953
if ((err == DB_SUCCESS) && !dict_index_is_clust(index)) {
4954
/* Update the page max trx id field */
4955
page_update_max_trx_id(block,
4956
buf_block_get_page_zip(block),
4962
mem_heap_t* heap = NULL;
4963
ulint offsets_[REC_OFFS_NORMAL_SIZE];
4964
const ulint* offsets;
4965
rec_offs_init(offsets_);
4967
offsets = rec_get_offsets(next_rec, index, offsets_,
4968
ULINT_UNDEFINED, &heap);
4969
ut_ad(lock_rec_queue_validate(block,
4970
next_rec, index, offsets));
4971
if (UNIV_LIKELY_NULL(heap)) {
4972
mem_heap_free(heap);
4975
#endif /* UNIV_DEBUG */
4980
/*********************************************************************//**
4981
If a transaction has an implicit x-lock on a record, but no explicit x-lock
4982
set on the record, sets one for it. NOTE that in the case of a secondary
4983
index, the kernel mutex may get temporarily released. */
4986
lock_rec_convert_impl_to_expl(
4987
/*==========================*/
4988
const buf_block_t* block, /*!< in: buffer block of rec */
4989
const rec_t* rec, /*!< in: user record on page */
4990
dict_index_t* index, /*!< in: index of record */
4991
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
4995
ut_ad(mutex_own(&kernel_mutex));
4996
ut_ad(page_rec_is_user_rec(rec));
4997
ut_ad(rec_offs_validate(rec, index, offsets));
4998
ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
5000
if (dict_index_is_clust(index)) {
5001
impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
5003
impl_trx = lock_sec_rec_some_has_impl_off_kernel(
5004
rec, index, offsets);
5008
ulint heap_no = page_rec_get_heap_no(rec);
5010
/* If the transaction has no explicit x-lock set on the
5011
record, set one for it */
5013
if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, block,
5014
heap_no, impl_trx)) {
5016
lock_rec_add_to_queue(
5017
LOCK_REC | LOCK_X | LOCK_REC_NOT_GAP,
5018
block, heap_no, index, impl_trx);
5023
/*********************************************************************//**
5024
Checks if locks of other transactions prevent an immediate modify (update,
5025
delete mark, or delete unmark) of a clustered index record. If they do,
5026
first tests if the query thread should anyway be suspended for some
5027
reason; if not, then puts the transaction and the query thread to the
5028
lock wait state and inserts a waiting request for a record x-lock to the
5030
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5033
lock_clust_rec_modify_check_and_lock(
5034
/*=================================*/
5035
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
5036
bit is set, does nothing */
5037
const buf_block_t* block, /*!< in: buffer block of rec */
5038
const rec_t* rec, /*!< in: record which should be
5040
dict_index_t* index, /*!< in: clustered index */
5041
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
5042
que_thr_t* thr) /*!< in: query thread */
5047
ut_ad(rec_offs_validate(rec, index, offsets));
5048
ut_ad(dict_index_is_clust(index));
5049
ut_ad(block->frame == page_align(rec));
5051
if (flags & BTR_NO_LOCKING_FLAG) {
5056
heap_no = rec_offs_comp(offsets)
5057
? rec_get_heap_no_new(rec)
5058
: rec_get_heap_no_old(rec);
5060
lock_mutex_enter_kernel();
5062
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
5064
/* If a transaction has no explicit x-lock set on the record, set one
5067
lock_rec_convert_impl_to_expl(block, rec, index, offsets);
5069
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
5070
block, heap_no, index, thr);
5072
lock_mutex_exit_kernel();
5074
ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5079
/*********************************************************************//**
5080
Checks if locks of other transactions prevent an immediate modify (delete
5081
mark or delete unmark) of a secondary index record.
5082
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5085
lock_sec_rec_modify_check_and_lock(
5086
/*===============================*/
5087
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
5088
bit is set, does nothing */
5089
buf_block_t* block, /*!< in/out: buffer block of rec */
5090
const rec_t* rec, /*!< in: record which should be
5091
modified; NOTE: as this is a secondary
5092
index, we always have to modify the
5093
clustered index record first: see the
5095
dict_index_t* index, /*!< in: secondary index */
5096
que_thr_t* thr, /*!< in: query thread */
5097
mtr_t* mtr) /*!< in/out: mini-transaction */
5102
ut_ad(!dict_index_is_clust(index));
5103
ut_ad(block->frame == page_align(rec));
5105
if (flags & BTR_NO_LOCKING_FLAG) {
5110
heap_no = page_rec_get_heap_no(rec);
5112
/* Another transaction cannot have an implicit lock on the record,
5113
because when we come here, we already have modified the clustered
5114
index record, and this would not have been possible if another active
5115
transaction had modified this secondary index record. */
5117
lock_mutex_enter_kernel();
5119
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
5121
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
5122
block, heap_no, index, thr);
5124
lock_mutex_exit_kernel();
5128
mem_heap_t* heap = NULL;
5129
ulint offsets_[REC_OFFS_NORMAL_SIZE];
5130
const ulint* offsets;
5131
rec_offs_init(offsets_);
5133
offsets = rec_get_offsets(rec, index, offsets_,
5134
ULINT_UNDEFINED, &heap);
5135
ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5136
if (UNIV_LIKELY_NULL(heap)) {
5137
mem_heap_free(heap);
5140
#endif /* UNIV_DEBUG */
5142
if (err == DB_SUCCESS) {
5143
/* Update the page max trx id field */
5144
page_update_max_trx_id(block,
5145
buf_block_get_page_zip(block),
5146
thr_get_trx(thr)->id, mtr);
5152
/*********************************************************************//**
5153
Like the counterpart for a clustered index below, but now we read a
5154
secondary index record.
5155
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5158
lock_sec_rec_read_check_and_lock(
5159
/*=============================*/
5160
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
5161
bit is set, does nothing */
5162
const buf_block_t* block, /*!< in: buffer block of rec */
5163
const rec_t* rec, /*!< in: user record or page
5164
supremum record which should
5165
be read or passed over by a
5167
dict_index_t* index, /*!< in: secondary index */
5168
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
5169
enum lock_mode mode, /*!< in: mode of the lock which
5170
the read cursor should set on
5171
records: LOCK_S or LOCK_X; the
5172
latter is possible in
5173
SELECT FOR UPDATE */
5174
ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
5176
que_thr_t* thr) /*!< in: query thread */
5181
ut_ad(!dict_index_is_clust(index));
5182
ut_ad(block->frame == page_align(rec));
5183
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
5184
ut_ad(rec_offs_validate(rec, index, offsets));
5185
ut_ad(mode == LOCK_X || mode == LOCK_S);
5187
if (flags & BTR_NO_LOCKING_FLAG) {
5192
heap_no = page_rec_get_heap_no(rec);
5194
lock_mutex_enter_kernel();
5196
ut_ad(mode != LOCK_X
5197
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
5198
ut_ad(mode != LOCK_S
5199
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
5201
/* Some transaction may have an implicit x-lock on the record only
5202
if the max trx id for the page >= min trx id for the trx list or a
5203
database recovery is running. */
5205
if (((ut_dulint_cmp(page_get_max_trx_id(block->frame),
5206
trx_list_get_min_trx_id()) >= 0)
5207
|| recv_recovery_is_on())
5208
&& !page_rec_is_supremum(rec)) {
5210
lock_rec_convert_impl_to_expl(block, rec, index, offsets);
5213
err = lock_rec_lock(FALSE, mode | gap_mode,
5214
block, heap_no, index, thr);
5216
lock_mutex_exit_kernel();
5218
ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5223
/*********************************************************************//**
5224
Checks if locks of other transactions prevent an immediate read, or passing
5225
over by a read cursor, of a clustered index record. If they do, first tests
5226
if the query thread should anyway be suspended for some reason; if not, then
5227
puts the transaction and the query thread to the lock wait state and inserts a
5228
waiting request for a record lock to the lock queue. Sets the requested mode
5230
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5233
lock_clust_rec_read_check_and_lock(
5234
/*===============================*/
5235
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
5236
bit is set, does nothing */
5237
const buf_block_t* block, /*!< in: buffer block of rec */
5238
const rec_t* rec, /*!< in: user record or page
5239
supremum record which should
5240
be read or passed over by a
5242
dict_index_t* index, /*!< in: clustered index */
5243
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
5244
enum lock_mode mode, /*!< in: mode of the lock which
5245
the read cursor should set on
5246
records: LOCK_S or LOCK_X; the
5247
latter is possible in
5248
SELECT FOR UPDATE */
5249
ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
5251
que_thr_t* thr) /*!< in: query thread */
5256
ut_ad(dict_index_is_clust(index));
5257
ut_ad(block->frame == page_align(rec));
5258
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
5259
ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP
5260
|| gap_mode == LOCK_REC_NOT_GAP);
5261
ut_ad(rec_offs_validate(rec, index, offsets));
5263
if (flags & BTR_NO_LOCKING_FLAG) {
5268
heap_no = page_rec_get_heap_no(rec);
5270
lock_mutex_enter_kernel();
5272
ut_ad(mode != LOCK_X
5273
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
5274
ut_ad(mode != LOCK_S
5275
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
5277
if (UNIV_LIKELY(heap_no != PAGE_HEAP_NO_SUPREMUM)) {
5279
lock_rec_convert_impl_to_expl(block, rec, index, offsets);
5282
err = lock_rec_lock(FALSE, mode | gap_mode,
5283
block, heap_no, index, thr);
5285
lock_mutex_exit_kernel();
5287
ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5291
/*********************************************************************//**
5292
Checks if locks of other transactions prevent an immediate read, or passing
5293
over by a read cursor, of a clustered index record. If they do, first tests
5294
if the query thread should anyway be suspended for some reason; if not, then
5295
puts the transaction and the query thread to the lock wait state and inserts a
5296
waiting request for a record lock to the lock queue. Sets the requested mode
5297
lock on the record. This is an alternative version of
5298
lock_clust_rec_read_check_and_lock() that does not require the parameter
5300
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5303
lock_clust_rec_read_check_and_lock_alt(
5304
/*===================================*/
5305
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
5306
bit is set, does nothing */
5307
const buf_block_t* block, /*!< in: buffer block of rec */
5308
const rec_t* rec, /*!< in: user record or page
5309
supremum record which should
5310
be read or passed over by a
5312
dict_index_t* index, /*!< in: clustered index */
5313
enum lock_mode mode, /*!< in: mode of the lock which
5314
the read cursor should set on
5315
records: LOCK_S or LOCK_X; the
5316
latter is possible in
5317
SELECT FOR UPDATE */
5318
ulint gap_mode,/*!< in: LOCK_ORDINARY, LOCK_GAP, or
5320
que_thr_t* thr) /*!< in: query thread */
5322
mem_heap_t* tmp_heap = NULL;
5323
ulint offsets_[REC_OFFS_NORMAL_SIZE];
5324
ulint* offsets = offsets_;
5326
rec_offs_init(offsets_);
5328
offsets = rec_get_offsets(rec, index, offsets,
5329
ULINT_UNDEFINED, &tmp_heap);
5330
ret = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
5331
offsets, mode, gap_mode, thr);
5333
mem_heap_free(tmp_heap);
5338
/*******************************************************************//**
5339
Release the last lock from the transaction's autoinc locks. */
5342
lock_release_autoinc_last_lock(
5343
/*===========================*/
5344
ib_vector_t* autoinc_locks) /*!< in/out: vector of AUTOINC locks */
5349
ut_ad(mutex_own(&kernel_mutex));
5350
ut_a(!ib_vector_is_empty(autoinc_locks));
5352
/* The lock to be release must be the last lock acquired. */
5353
last = ib_vector_size(autoinc_locks) - 1;
5354
lock = ib_vector_get(autoinc_locks, last);
5356
/* Should have only AUTOINC locks in the vector. */
5357
ut_a(lock_get_mode(lock) == LOCK_AUTO_INC);
5358
ut_a(lock_get_type(lock) == LOCK_TABLE);
5360
ut_a(lock->un_member.tab_lock.table != NULL);
5362
/* This will remove the lock from the trx autoinc_locks too. */
5363
lock_table_dequeue(lock);
5366
/*******************************************************************//**
5367
Release all the transaction's autoinc locks. */
5370
lock_release_autoinc_locks(
5371
/*=======================*/
5372
trx_t* trx) /*!< in/out: transaction */
5374
ut_ad(mutex_own(&kernel_mutex));
5376
ut_a(trx->autoinc_locks != NULL);
5378
/* We release the locks in the reverse order. This is to
5379
avoid searching the vector for the element to delete at
5380
the lower level. See (lock_table_remove_low()) for details. */
5381
while (!ib_vector_is_empty(trx->autoinc_locks)) {
5383
/* lock_table_remove_low() will also remove the lock from
5384
the transaction's autoinc_locks vector. */
5385
lock_release_autoinc_last_lock(trx->autoinc_locks);
5388
/* Should release all locks. */
5389
ut_a(ib_vector_is_empty(trx->autoinc_locks));
5392
/*******************************************************************//**
5393
Gets the type of a lock. Non-inline version for using outside of the
5395
@return LOCK_TABLE or LOCK_REC */
5400
const lock_t* lock) /*!< in: lock */
5402
return(lock_get_type_low(lock));
5405
/*******************************************************************//**
5406
Gets the id of the transaction owning a lock.
5407
@return transaction id */
5412
const lock_t* lock) /*!< in: lock */
5414
return(trx_get_id(lock->trx));
5417
/*******************************************************************//**
5418
Gets the mode of a lock in a human readable string.
5419
The string should not be free()'d or modified.
5420
@return lock mode */
5425
const lock_t* lock) /*!< in: lock */
5429
is_gap_lock = lock_get_type_low(lock) == LOCK_REC
5430
&& lock_rec_get_gap(lock);
5432
switch (lock_get_mode(lock)) {
5464
/*******************************************************************//**
5465
Gets the type of a lock in a human readable string.
5466
The string should not be free()'d or modified.
5467
@return lock type */
5472
const lock_t* lock) /*!< in: lock */
5474
switch (lock_get_type_low(lock)) {
5484
/*******************************************************************//**
5485
Gets the table on which the lock is.
5491
const lock_t* lock) /*!< in: lock */
5493
switch (lock_get_type_low(lock)) {
5495
return(lock->index->table);
5497
return(lock->un_member.tab_lock.table);
5504
/*******************************************************************//**
5505
Gets the id of the table on which the lock is.
5506
@return id of the table */
5511
const lock_t* lock) /*!< in: lock */
5513
dict_table_t* table;
5515
table = lock_get_table(lock);
5517
return((ullint)ut_conv_dulint_to_longlong(table->id));
5520
/*******************************************************************//**
5521
Gets the name of the table on which the lock is.
5522
The string should not be free()'d or modified.
5523
@return name of the table */
5526
lock_get_table_name(
5527
/*================*/
5528
const lock_t* lock) /*!< in: lock */
5530
dict_table_t* table;
5532
table = lock_get_table(lock);
5534
return(table->name);
5537
/*******************************************************************//**
5538
For a record lock, gets the index on which the lock is.
5544
const lock_t* lock) /*!< in: lock */
5546
ut_a(lock_get_type_low(lock) == LOCK_REC);
5548
return(lock->index);
5551
/*******************************************************************//**
5552
For a record lock, gets the name of the index on which the lock is.
5553
The string should not be free()'d or modified.
5554
@return name of the index */
5557
lock_rec_get_index_name(
5558
/*====================*/
5559
const lock_t* lock) /*!< in: lock */
5561
ut_a(lock_get_type_low(lock) == LOCK_REC);
5563
return(lock->index->name);
5566
/*******************************************************************//**
5567
For a record lock, gets the tablespace number on which the lock is.
5568
@return tablespace number */
5571
lock_rec_get_space_id(
5572
/*==================*/
5573
const lock_t* lock) /*!< in: lock */
5575
ut_a(lock_get_type_low(lock) == LOCK_REC);
5577
return(lock->un_member.rec_lock.space);
5580
/*******************************************************************//**
5581
For a record lock, gets the page number on which the lock is.
5582
@return page number */
5585
lock_rec_get_page_no(
5586
/*=================*/
5587
const lock_t* lock) /*!< in: lock */
5589
ut_a(lock_get_type_low(lock) == LOCK_REC);
5591
return(lock->un_member.rec_lock.page_no);