16
16
#include "lock0priv.ic"
19
#include "ha_prototypes.h"
20
19
#include "usr0sess.h"
21
20
#include "trx0purge.h"
22
21
#include "dict0mem.h"
23
22
#include "trx0sys.h"
25
/* 2 function prototypes copied from ha_innodb.cc: */
27
/*****************************************************************
28
If you want to print a thd that is not associated with the current thread,
29
you must call this function before reserving the InnoDB kernel_mutex, to
30
protect MySQL from setting thd->query NULL. If you print a thd of the current
31
thread, we know that MySQL cannot modify thd->query, and it is not necessary
32
to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
34
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
38
innobase_mysql_prepare_print_arbitrary_thd(void);
39
/*============================================*/
41
/*****************************************************************
42
Relases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
43
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
47
innobase_mysql_end_print_arbitrary_thd(void);
48
/*========================================*/
25
50
/* Restricts the length of search we will do in the waits-for
26
51
graph of transactions */
27
52
#define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
290
315
* statement-level MySQL binlog.
291
316
* See also lock_mode_compatible().
293
#define LK(a,b) (1 << ((a) * LOCK_NUM + (b)))
294
#define LKS(a,b) LK(a,b) | LK(b,a)
296
/* Define the lock compatibility matrix in a ulint. The first line below
297
defines the diagonal entries. The following lines define the compatibility
298
for LOCK_IX, LOCK_S, and LOCK_AUTO_INC using LKS(), since the matrix
300
#define LOCK_MODE_COMPATIBILITY 0 \
301
| LK(LOCK_IS, LOCK_IS) | LK(LOCK_IX, LOCK_IX) | LK(LOCK_S, LOCK_S) \
302
| LKS(LOCK_IX, LOCK_IS) | LKS(LOCK_IS, LOCK_AUTO_INC) \
303
| LKS(LOCK_S, LOCK_IS) \
304
| LKS(LOCK_AUTO_INC, LOCK_IS) | LKS(LOCK_AUTO_INC, LOCK_IX)
306
/* STRONGER-OR-EQUAL RELATION (mode1=row, mode2=column)
313
* See lock_mode_stronger_or_eq().
316
/* Define the stronger-or-equal lock relation in a ulint. This relation
317
contains all pairs LK(mode1, mode2) where mode1 is stronger than or
319
#define LOCK_MODE_STRONGER_OR_EQ 0 \
320
| LK(LOCK_IS, LOCK_IS) \
321
| LK(LOCK_IX, LOCK_IS) | LK(LOCK_IX, LOCK_IX) \
322
| LK(LOCK_S, LOCK_IS) | LK(LOCK_S, LOCK_S) \
323
| LK(LOCK_AUTO_INC, LOCK_AUTO_INC) \
324
| LK(LOCK_X, LOCK_IS) | LK(LOCK_X, LOCK_IX) | LK(LOCK_X, LOCK_S) \
325
| LK(LOCK_X, LOCK_AUTO_INC) | LK(LOCK_X, LOCK_X)
327
319
#ifdef UNIV_DEBUG
328
UNIV_INTERN ibool lock_print_waits = FALSE;
330
/*************************************************************************
331
Validates the lock system. */
336
/* out: TRUE if ok */
338
/*************************************************************************
339
Validates the record lock queues on a page. */
342
lock_rec_validate_page(
343
/*===================*/
344
/* out: TRUE if ok */
345
ulint space, /* in: space id */
346
ulint page_no);/* in: page number */
348
/* Define the following in order to enable lock_rec_validate_page() checks. */
349
# undef UNIV_DEBUG_LOCK_VALIDATE
320
ibool lock_print_waits = FALSE;
350
321
#endif /* UNIV_DEBUG */
352
323
/* The lock system */
353
UNIV_INTERN lock_sys_t* lock_sys = NULL;
324
lock_sys_t* lock_sys = NULL;
355
326
/* We store info on the latest deadlock error to this buffer. InnoDB
356
327
Monitor will then fetch it and print */
357
UNIV_INTERN ibool lock_deadlock_found = FALSE;
358
UNIV_INTERN FILE* lock_latest_err_file;
328
ibool lock_deadlock_found = FALSE;
329
FILE* lock_latest_err_file;
360
331
/* Flags for recursive deadlock search */
361
332
#define LOCK_VICTIM_IS_START 1
512
488
/*************************************************************************
513
489
Checks that a non-clustered index record is seen in a consistent read. */
516
492
lock_sec_rec_cons_read_sees(
517
493
/*========================*/
518
/* out: TRUE if certainly
519
sees, or FALSE if an earlier
520
version of the clustered index
521
record might be needed: NOTE
522
that a non-clustered index
523
page contains so little
525
modifications that also in the
526
case FALSE, the present
527
version of rec may be the
528
right, but we must check this
529
from the clustered index
531
const rec_t* rec, /* in: user record which
532
should be read or passed over
534
const read_view_t* view) /* in: consistent read view */
494
/* out: TRUE if certainly sees, or FALSE if an
495
earlier version of the clustered index record
496
might be needed: NOTE that a non-clustered
497
index page contains so little information on
498
its modifications that also in the case FALSE,
499
the present version of rec may be the right,
500
but we must check this from the clustered
502
rec_t* rec, /* in: user record which should be read or
503
passed over by a read cursor */
504
dict_index_t* index, /* in: non-clustered index */
505
read_view_t* view) /* in: consistent read view */
536
507
dulint max_trx_id;
511
ut_ad(!(index->type & DICT_CLUSTERED));
538
512
ut_ad(page_rec_is_user_rec(rec));
540
514
/* NOTE that we might call this function while holding the search
829
811
/*************************************************************************
830
812
Calculates if lock mode 1 is stronger or equal to lock mode 2. */
833
815
lock_mode_stronger_or_eq(
834
816
/*=====================*/
836
if mode1 stronger or equal to mode2 */
837
enum lock_mode mode1, /* in: lock mode */
838
enum lock_mode mode2) /* in: lock mode */
817
/* out: TRUE if mode1 stronger or equal to mode2 */
818
ulint mode1, /* in: lock mode */
819
ulint mode2) /* in: lock mode */
840
821
ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX
841
822
|| mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC);
842
823
ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX
843
824
|| mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC);
845
return((LOCK_MODE_STRONGER_OR_EQ) & LK(mode1, mode2));
825
if (mode1 == LOCK_X) {
829
} else if (mode1 == LOCK_AUTO_INC && mode2 == LOCK_AUTO_INC) {
833
} else if (mode1 == LOCK_S
834
&& (mode2 == LOCK_S || mode2 == LOCK_IS)) {
837
} else if (mode1 == LOCK_IS && mode2 == LOCK_IS) {
841
} else if (mode1 == LOCK_IX && (mode2 == LOCK_IX
842
|| mode2 == LOCK_IS)) {
848
849
/*************************************************************************
849
850
Calculates if lock mode 1 is compatible with lock mode 2. */
852
853
lock_mode_compatible(
853
854
/*=================*/
854
/* out: nonzero if mode1 compatible with mode2 */
855
enum lock_mode mode1, /* in: lock mode */
856
enum lock_mode mode2) /* in: lock mode */
855
/* out: TRUE if mode1 compatible with mode2 */
856
ulint mode1, /* in: lock mode */
857
ulint mode2) /* in: lock mode */
858
859
ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX
859
860
|| mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC);
860
861
ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX
861
862
|| mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC);
863
return((LOCK_MODE_COMPATIBILITY) & LK(mode1, mode2));
864
if (mode1 == LOCK_S && (mode2 == LOCK_IS || mode2 == LOCK_S)) {
868
} else if (mode1 == LOCK_X) {
872
} else if (mode1 == LOCK_AUTO_INC && (mode2 == LOCK_IS
873
|| mode2 == LOCK_IX)) {
876
} else if (mode1 == LOCK_IS && (mode2 == LOCK_IS
878
|| mode2 == LOCK_AUTO_INC
879
|| mode2 == LOCK_S)) {
882
} else if (mode1 == LOCK_IX && (mode2 == LOCK_IS
883
|| mode2 == LOCK_AUTO_INC
884
|| mode2 == LOCK_IX)) {
866
891
/*************************************************************************
870
895
lock_rec_has_to_wait(
871
896
/*=================*/
872
/* out: TRUE if new lock has to wait
873
for lock2 to be removed */
874
const trx_t* trx, /* in: trx of new lock */
875
ulint type_mode,/* in: precise mode of the new lock
876
to set: LOCK_S or LOCK_X, possibly
877
ORed to LOCK_GAP or LOCK_REC_NOT_GAP,
878
LOCK_INSERT_INTENTION */
879
const lock_t* lock2, /* in: another record lock; NOTE that
880
it is assumed that this has a lock bit
881
set on the same record as in the new
882
lock we are setting */
883
ibool lock_is_on_supremum) /* in: TRUE if we are setting the
884
lock on the 'supremum' record of an
885
index page: we know then that the lock
886
request is really for a 'gap' type lock */
897
/* out: TRUE if new lock has to wait for lock2 to be
899
trx_t* trx, /* in: trx of new lock */
900
ulint type_mode,/* in: precise mode of the new lock to set:
901
LOCK_S or LOCK_X, possibly ORed to
902
LOCK_GAP or LOCK_REC_NOT_GAP, LOCK_INSERT_INTENTION */
903
lock_t* lock2, /* in: another record lock; NOTE that it is assumed
904
that this has a lock bit set on the same record as
905
in the new lock we are setting */
906
ibool lock_is_on_supremum) /* in: TRUE if we are setting the lock
907
on the 'supremum' record of an index
908
page: we know then that the lock request
909
is really for a 'gap' type lock */
888
911
ut_ad(trx && lock2);
889
ut_ad(lock_get_type_low(lock2) == LOCK_REC);
912
ut_ad(lock_get_type(lock2) == LOCK_REC);
891
914
if (trx != lock2->trx
892
915
&& !lock_mode_compatible(LOCK_MODE_MASK & type_mode,
949
972
/*************************************************************************
950
973
Checks if a lock request lock1 has to wait for request lock2. */
953
976
lock_has_to_wait(
954
977
/*=============*/
955
/* out: TRUE if lock1 has to wait for
956
lock2 to be removed */
957
const lock_t* lock1, /* in: waiting lock */
958
const lock_t* lock2) /* in: another lock; NOTE that it is
959
assumed that this has a lock bit set
960
on the same record as in lock1 if the
961
locks are record locks */
978
/* out: TRUE if lock1 has to wait for lock2 to be
980
lock_t* lock1, /* in: waiting lock */
981
lock_t* lock2) /* in: another lock; NOTE that it is assumed that this
982
has a lock bit set on the same record as in lock1 if
983
the locks are record locks */
963
985
ut_ad(lock1 && lock2);
965
987
if (lock1->trx != lock2->trx
966
988
&& !lock_mode_compatible(lock_get_mode(lock1),
967
989
lock_get_mode(lock2))) {
968
if (lock_get_type_low(lock1) == LOCK_REC) {
969
ut_ad(lock_get_type_low(lock2) == LOCK_REC);
990
if (lock_get_type(lock1) == LOCK_REC) {
991
ut_ad(lock_get_type(lock2) == LOCK_REC);
971
993
/* If this lock request is for a supremum record
972
994
then the second bit on the lock bitmap is set */
1271
1327
/* out: copy of lock */
1272
const lock_t* lock, /* in: record lock */
1328
lock_t* lock, /* in: record lock */
1273
1329
mem_heap_t* heap) /* in: memory heap */
1277
ut_ad(lock_get_type_low(lock) == LOCK_REC);
1334
ut_ad(lock_get_type(lock) == LOCK_REC);
1279
1336
size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8;
1281
return(mem_heap_dup(heap, lock, size));
1338
dupl_lock = mem_heap_alloc(heap, size);
1340
ut_memcpy(dupl_lock, lock, size);
1284
1345
/*************************************************************************
1285
1346
Gets the previous record lock set on a record. */
1288
1349
lock_rec_get_prev(
1289
1350
/*==============*/
1290
/* out: previous lock on the same
1291
record, NULL if none exists */
1292
const lock_t* in_lock,/* in: record lock */
1293
ulint heap_no)/* in: heap number of the record */
1351
/* out: previous lock on the same record, NULL if
1353
lock_t* in_lock,/* in: record lock */
1354
ulint heap_no)/* in: heap number of the record */
1398
1456
&& !lock_get_wait(lock)
1399
1457
&& (!lock_rec_get_rec_not_gap(lock)
1400
1458
|| (precise_mode & LOCK_REC_NOT_GAP)
1401
|| heap_no == PAGE_HEAP_NO_SUPREMUM)
1459
|| page_rec_is_supremum(rec))
1402
1460
&& (!lock_rec_get_gap(lock)
1403
1461
|| (precise_mode & LOCK_GAP)
1404
|| heap_no == PAGE_HEAP_NO_SUPREMUM)
1462
|| page_rec_is_supremum(rec))
1405
1463
&& (!lock_rec_get_insert_intention(lock))) {
1410
lock = lock_rec_get_next(heap_no, lock);
1468
lock = lock_rec_get_next(rec, lock);
1417
# ifndef UNIV_HOTBACKUP
1474
#ifndef UNIV_HOTBACKUP
1418
1475
/*************************************************************************
1419
1476
Checks if some other transaction has a lock request in the queue. */
1422
1479
lock_rec_other_has_expl_req(
1423
1480
/*========================*/
1424
/* out: lock or NULL */
1425
enum lock_mode mode, /* in: LOCK_S or LOCK_X */
1426
ulint gap, /* in: LOCK_GAP if also gap
1427
locks are taken into account,
1429
ulint wait, /* in: LOCK_WAIT if also
1430
waiting locks are taken into
1431
account, or 0 if not */
1432
const buf_block_t* block, /* in: buffer block containing
1434
ulint heap_no,/* in: heap number of the record */
1435
const trx_t* trx) /* in: transaction, or NULL if
1436
requests by all transactions
1437
are taken into account */
1481
/* out: lock or NULL */
1482
ulint mode, /* in: LOCK_S or LOCK_X */
1483
ulint gap, /* in: LOCK_GAP if also gap locks are taken
1484
into account, or 0 if not */
1485
ulint wait, /* in: LOCK_WAIT if also waiting locks are
1486
taken into account, or 0 if not */
1487
rec_t* rec, /* in: record to look at */
1488
trx_t* trx) /* in: transaction, or NULL if requests by all
1489
transactions are taken into account */
1472
1523
lock_rec_other_has_conflicting(
1473
1524
/*===========================*/
1474
/* out: lock or NULL */
1475
enum lock_mode mode, /* in: LOCK_S or LOCK_X,
1476
possibly ORed to LOCK_GAP or
1478
LOCK_INSERT_INTENTION */
1479
const buf_block_t* block, /* in: buffer block containing
1481
ulint heap_no,/* in: heap number of the record */
1482
trx_t* trx) /* in: our transaction */
1525
/* out: lock or NULL */
1526
ulint mode, /* in: LOCK_S or LOCK_X,
1527
possibly ORed to LOCK_GAP or LOC_REC_NOT_GAP,
1528
LOCK_INSERT_INTENTION */
1529
rec_t* rec, /* in: record to look at */
1530
trx_t* trx) /* in: our transaction */
1486
1534
ut_ad(mutex_own(&kernel_mutex));
1488
lock = lock_rec_get_first(block, heap_no);
1490
if (UNIV_LIKELY_NULL(lock)) {
1491
if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
1494
if (lock_rec_has_to_wait(trx, mode, lock,
1499
lock = lock_rec_get_next(heap_no, lock);
1504
if (lock_rec_has_to_wait(trx, mode, lock,
1509
lock = lock_rec_get_next(heap_no, lock);
1536
lock = lock_rec_get_first(rec);
1539
if (lock_rec_has_to_wait(trx, mode, lock,
1540
page_rec_is_supremum(rec))) {
1545
lock = lock_rec_get_next(rec, lock);
1547
1586
/*************************************************************************
1548
1587
Checks if some transaction has an implicit x-lock on a record in a secondary
1552
1591
lock_sec_rec_some_has_impl_off_kernel(
1553
1592
/*==================================*/
1554
1593
/* out: transaction which has the x-lock, or
1556
const rec_t* rec, /* in: user record */
1595
rec_t* rec, /* in: user record */
1557
1596
dict_index_t* index, /* in: secondary index */
1558
1597
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
1560
const page_t* page = page_align(rec);
1562
1601
ut_ad(mutex_own(&kernel_mutex));
1563
ut_ad(!dict_index_is_clust(index));
1602
ut_ad(!(index->type & DICT_CLUSTERED));
1564
1603
ut_ad(page_rec_is_user_rec(rec));
1565
1604
ut_ad(rec_offs_validate(rec, index, offsets));
1606
page = buf_frame_align(rec);
1567
1608
/* Some transaction may have an implicit x-lock on the record only
1568
1609
if the max trx id for the page >= min trx id for the trx list, or
1569
1610
database recovery is running. We do not write the changes of a page
1636
1677
lock_rec_create(
1637
1678
/*============*/
1638
/* out: created lock */
1639
ulint type_mode,/* in: lock mode and wait
1640
flag, type is ignored and
1641
replaced by LOCK_REC */
1642
const buf_block_t* block, /* in: buffer block containing
1644
ulint heap_no,/* in: heap number of the record */
1645
dict_index_t* index, /* in: index of record */
1646
trx_t* trx) /* in: transaction */
1679
/* out: created lock */
1680
ulint type_mode,/* in: lock mode and wait flag, type is
1681
ignored and replaced by LOCK_REC */
1682
rec_t* rec, /* in: record on page */
1683
dict_index_t* index, /* in: index of record */
1684
trx_t* trx) /* in: transaction */
1655
1694
ut_ad(mutex_own(&kernel_mutex));
1657
space = buf_block_get_space(block);
1658
page_no = buf_block_get_page_no(block);
1659
page = block->frame;
1696
page = buf_frame_align(rec);
1697
space = buf_frame_get_space_id(page);
1698
page_no = buf_frame_get_page_no(page);
1699
heap_no = rec_get_heap_no(rec, page_is_comp(page));
1661
1701
ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
1713
1753
lock_rec_enqueue_waiting(
1714
1754
/*=====================*/
1715
/* out: DB_LOCK_WAIT,
1717
DB_QUE_THR_SUSPENDED, or
1718
DB_SUCCESS; DB_SUCCESS means
1719
that there was a deadlock, but
1720
another transaction was chosen
1721
as a victim, and we got the
1722
lock immediately: no need to
1724
ulint type_mode,/* in: lock mode this
1725
transaction is requesting:
1726
LOCK_S or LOCK_X, possibly
1727
ORed with LOCK_GAP or
1728
LOCK_REC_NOT_GAP, ORed with
1729
LOCK_INSERT_INTENTION if this
1730
waiting lock request is set
1731
when performing an insert of
1733
const buf_block_t* block, /* in: buffer block containing
1735
ulint heap_no,/* in: heap number of the record */
1736
dict_index_t* index, /* in: index of record */
1737
que_thr_t* thr) /* in: query thread */
1755
/* out: DB_LOCK_WAIT, DB_DEADLOCK, or
1756
DB_QUE_THR_SUSPENDED, or DB_SUCCESS;
1757
DB_SUCCESS means that there was a deadlock,
1758
but another transaction was chosen as a
1759
victim, and we got the lock immediately:
1760
no need to wait then */
1761
ulint type_mode,/* in: lock mode this transaction is
1762
requesting: LOCK_S or LOCK_X, possibly ORed
1763
with LOCK_GAP or LOCK_REC_NOT_GAP, ORed
1764
with LOCK_INSERT_INTENTION if this waiting
1765
lock request is set when performing an
1766
insert of an index record */
1767
rec_t* rec, /* in: record */
1768
dict_index_t* index, /* in: index of record */
1769
que_thr_t* thr) /* in: query thread */
1822
1850
lock_rec_add_to_queue(
1823
1851
/*==================*/
1824
/* out: lock where the bit was set */
1825
ulint type_mode,/* in: lock mode, wait, gap
1826
etc. flags; type is ignored
1827
and replaced by LOCK_REC */
1828
const buf_block_t* block, /* in: buffer block containing
1830
ulint heap_no,/* in: heap number of the record */
1831
dict_index_t* index, /* in: index of record */
1832
trx_t* trx) /* in: transaction */
1852
/* out: lock where the bit was set */
1853
ulint type_mode,/* in: lock mode, wait, gap etc. flags;
1854
type is ignored and replaced by LOCK_REC */
1855
rec_t* rec, /* in: record on page */
1856
dict_index_t* index, /* in: index of record */
1857
trx_t* trx) /* in: transaction */
1860
lock_t* similar_lock = NULL;
1862
ibool somebody_waits = FALSE;
1836
1864
ut_ad(mutex_own(&kernel_mutex));
1838
switch (type_mode & LOCK_MODE_MASK) {
1846
if (!(type_mode & (LOCK_WAIT | LOCK_GAP))) {
1847
enum lock_mode mode = (type_mode & LOCK_MODE_MASK) == LOCK_S
1851
= lock_rec_other_has_expl_req(mode, 0, LOCK_WAIT,
1852
block, heap_no, trx);
1855
#endif /* UNIV_DEBUG */
1857
type_mode |= LOCK_REC;
1865
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
1866
|| ((type_mode & LOCK_MODE_MASK) != LOCK_S)
1867
|| !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT,
1869
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
1870
|| ((type_mode & LOCK_MODE_MASK) != LOCK_X)
1871
|| !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
1874
type_mode = type_mode | LOCK_REC;
1859
1876
/* If rec is the supremum record, then we can reset the gap bit, as
1860
1877
all locks on the supremum are automatically of the gap type, and we
1861
1878
try to avoid unnecessary memory consumption of a new record lock
1862
1879
struct for a gap type lock */
1864
if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
1881
if (page_rec_is_supremum(rec)) {
1865
1882
ut_ad(!(type_mode & LOCK_REC_NOT_GAP));
1867
1884
/* There should never be LOCK_REC_NOT_GAP on a supremum
1873
1890
/* Look for a waiting lock request on the same record or on a gap */
1875
lock = lock_rec_get_first_on_page(block);
1892
heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
1893
lock = lock_rec_get_first_on_page(rec);
1877
1895
while (lock != NULL) {
1878
1896
if (lock_get_wait(lock)
1879
1897
&& (lock_rec_get_nth_bit(lock, heap_no))) {
1881
goto somebody_waits;
1899
somebody_waits = TRUE;
1884
1902
lock = lock_rec_get_next_on_page(lock);
1887
if (UNIV_LIKELY(!(type_mode & LOCK_WAIT))) {
1889
/* Look for a similar record lock on the same page:
1890
if one is found and there are no waiting lock requests,
1891
we can just set the bit */
1893
lock = lock_rec_find_similar_on_page(
1895
lock_rec_get_first_on_page(block), trx);
1899
lock_rec_set_nth_bit(lock, heap_no);
1905
/* Look for a similar record lock on the same page: if one is found
1906
and there are no waiting lock requests, we can just set the bit */
1908
similar_lock = lock_rec_find_similar_on_page(type_mode, rec, trx);
1910
if (similar_lock && !somebody_waits && !(type_mode & LOCK_WAIT)) {
1912
lock_rec_set_nth_bit(similar_lock, heap_no);
1914
return(similar_lock);
1906
return(lock_rec_create(type_mode, block, heap_no, index, trx));
1917
return(lock_rec_create(type_mode, rec, index, trx));
1909
1920
/*************************************************************************
1918
1929
lock_rec_lock_fast(
1919
1930
/*===============*/
1920
/* out: TRUE if locking succeeded */
1921
ibool impl, /* in: if TRUE, no lock is set
1922
if no wait is necessary: we
1923
assume that the caller will
1924
set an implicit lock */
1925
ulint mode, /* in: lock mode: LOCK_X or
1926
LOCK_S possibly ORed to either
1927
LOCK_GAP or LOCK_REC_NOT_GAP */
1928
const buf_block_t* block, /* in: buffer block containing
1930
ulint heap_no,/* in: heap number of record */
1931
dict_index_t* index, /* in: index of record */
1932
que_thr_t* thr) /* in: query thread */
1931
/* out: TRUE if locking succeeded */
1932
ibool impl, /* in: if TRUE, no lock is set if no wait
1933
is necessary: we assume that the caller will
1934
set an implicit lock */
1935
ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
1936
ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
1937
rec_t* rec, /* in: record */
1938
dict_index_t* index, /* in: index of record */
1939
que_thr_t* thr) /* in: query thread */
1937
1945
ut_ad(mutex_own(&kernel_mutex));
2002
2012
lock_rec_lock_slow(
2003
2013
/*===============*/
2005
DB_LOCK_WAIT, or error code */
2006
ibool impl, /* in: if TRUE, no lock is set
2007
if no wait is necessary: we
2008
assume that the caller will
2009
set an implicit lock */
2010
ulint mode, /* in: lock mode: LOCK_X or
2011
LOCK_S possibly ORed to either
2012
LOCK_GAP or LOCK_REC_NOT_GAP */
2013
const buf_block_t* block, /* in: buffer block containing
2015
ulint heap_no,/* in: heap number of record */
2016
dict_index_t* index, /* in: index of record */
2017
que_thr_t* thr) /* in: query thread */
2014
/* out: DB_SUCCESS, DB_LOCK_WAIT, or error
2016
ibool impl, /* in: if TRUE, no lock is set if no wait is
2017
necessary: we assume that the caller will set
2019
ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
2020
ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
2021
rec_t* rec, /* in: record */
2022
dict_index_t* index, /* in: index of record */
2023
que_thr_t* thr) /* in: query thread */
2033
2039
trx = thr_get_trx(thr);
2035
if (lock_rec_has_expl(mode, block, heap_no, trx)) {
2041
if (lock_rec_has_expl(mode, rec, trx)) {
2036
2042
/* The trx already has a strong enough lock on rec: do
2039
2045
err = DB_SUCCESS;
2040
} else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) {
2046
} else if (lock_rec_other_has_conflicting(mode, rec, trx)) {
2042
2048
/* If another transaction has a non-gap conflicting request in
2043
2049
the queue, as this transaction does not have a lock strong
2044
2050
enough already granted on the record, we have to wait. */
2046
err = lock_rec_enqueue_waiting(mode, block, heap_no,
2052
err = lock_rec_enqueue_waiting(mode, rec, index, thr);
2049
2054
if (srv_locks_unsafe_for_binlog
2050
2055
|| trx->isolation_level == TRX_ISO_READ_COMMITTED) {
2083
DB_LOCK_WAIT, or error code */
2084
ibool impl, /* in: if TRUE, no lock is set
2085
if no wait is necessary: we
2086
assume that the caller will
2087
set an implicit lock */
2088
ulint mode, /* in: lock mode: LOCK_X or
2089
LOCK_S possibly ORed to either
2090
LOCK_GAP or LOCK_REC_NOT_GAP */
2091
const buf_block_t* block, /* in: buffer block containing
2093
ulint heap_no,/* in: heap number of record */
2094
dict_index_t* index, /* in: index of record */
2095
que_thr_t* thr) /* in: query thread */
2087
/* out: DB_SUCCESS, DB_LOCK_WAIT, or error
2089
ibool impl, /* in: if TRUE, no lock is set if no wait is
2090
necessary: we assume that the caller will set
2092
ulint mode, /* in: lock mode: LOCK_X or LOCK_S possibly
2093
ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */
2094
rec_t* rec, /* in: record */
2095
dict_index_t* index, /* in: index of record */
2096
que_thr_t* thr) /* in: query thread */
2425
2418
lock_rec_inherit_to_gap_if_gap_lock(
2426
2419
/*================================*/
2427
const buf_block_t* block, /* in: buffer block */
2428
ulint heir_heap_no, /* in: heap_no of
2429
record which inherits */
2430
ulint heap_no) /* in: heap_no of record
2431
from which inherited;
2432
does NOT reset the locks
2420
rec_t* heir, /* in: record which inherits */
2421
rec_t* rec) /* in: record from which inherited; does NOT reset
2422
the locks on this record */
2437
2426
ut_ad(mutex_own(&kernel_mutex));
2439
lock = lock_rec_get_first(block, heap_no);
2428
lock = lock_rec_get_first(rec);
2441
2430
while (lock != NULL) {
2442
2431
if (!lock_rec_get_insert_intention(lock)
2443
&& (heap_no == PAGE_HEAP_NO_SUPREMUM
2432
&& (page_rec_is_supremum(rec)
2444
2433
|| !lock_rec_get_rec_not_gap(lock))) {
2446
lock_rec_add_to_queue(LOCK_REC | LOCK_GAP
2447
| lock_get_mode(lock),
2448
block, heir_heap_no,
2449
lock->index, lock->trx);
2435
lock_rec_add_to_queue(LOCK_REC | lock_get_mode(lock)
2437
heir, lock->index, lock->trx);
2452
lock = lock_rec_get_next(heap_no, lock);
2440
lock = lock_rec_get_next(rec, lock);
2463
const buf_block_t* receiver, /* in: buffer block containing
2464
the receiving record */
2465
const buf_block_t* donator, /* in: buffer block containing
2466
the donating record */
2467
ulint receiver_heap_no,/* in: heap_no of the record
2468
which gets the locks; there
2469
must be no lock requests
2471
ulint donator_heap_no)/* in: heap_no of the record
2472
which gives the locks */
2451
rec_t* receiver, /* in: record which gets locks; this record
2452
must have no lock requests on it! */
2453
rec_t* donator, /* in: record which gives locks */
2454
ulint comp) /* in: nonzero=compact page format */
2476
2460
ut_ad(mutex_own(&kernel_mutex));
2478
lock = lock_rec_get_first(donator, donator_heap_no);
2480
ut_ad(lock_rec_get_first(receiver, receiver_heap_no) == NULL);
2462
heap_no = rec_get_heap_no(donator, comp);
2464
lock = lock_rec_get_first(donator);
2466
ut_ad(lock_rec_get_first(receiver) == NULL);
2482
2468
while (lock != NULL) {
2483
const ulint type_mode = lock->type_mode;
2485
lock_rec_reset_nth_bit(lock, donator_heap_no);
2487
if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
2469
type_mode = lock->type_mode;
2471
lock_rec_reset_nth_bit(lock, heap_no);
2473
if (lock_get_wait(lock)) {
2488
2474
lock_reset_lock_and_trx_wait(lock);
2491
2477
/* Note that we FIRST reset the bit, and then set the lock:
2492
2478
the function works also if donator == receiver */
2494
lock_rec_add_to_queue(type_mode, receiver, receiver_heap_no,
2495
lock->index, lock->trx);
2496
lock = lock_rec_get_next(donator_heap_no, lock);
2480
lock_rec_add_to_queue(type_mode, receiver, lock->index,
2482
lock = lock_rec_get_next(donator, lock);
2499
ut_ad(lock_rec_get_first(donator, donator_heap_no) == NULL);
2485
ut_ad(lock_rec_get_first(donator) == NULL);
2502
2488
/*****************************************************************
2552
2542
lock = lock_rec_get_next_on_page(lock);
2553
} while (lock != NULL);
2555
comp = page_is_comp(block->frame);
2556
ut_ad(comp == page_is_comp(oblock->frame));
2558
for (lock = UT_LIST_GET_FIRST(old_locks); lock;
2559
lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
2545
sup = page_get_supremum_rec(page);
2547
lock = UT_LIST_GET_FIRST(old_locks);
2549
comp = page_is_comp(page);
2550
ut_ad(comp == page_is_comp(old_page));
2560
2553
/* NOTE: we copy also the locks set on the infimum and
2561
2554
supremum of the page; the infimum may carry locks if an
2562
2555
update of a record is occurring on the page, and its locks
2563
2556
were temporarily stored on the infimum */
2567
page_cur_set_before_first(block, &cur1);
2568
page_cur_set_before_first(oblock, &cur2);
2558
page_cur_set_before_first(page, &cur1);
2559
page_cur_set_before_first(old_page, &cur2);
2570
2561
/* Set locks according to old locks */
2575
2563
ut_ad(comp || !memcmp(page_cur_get_rec(&cur1),
2576
2564
page_cur_get_rec(&cur2),
2577
2565
rec_get_data_size_old(
2578
2566
page_cur_get_rec(
2580
if (UNIV_LIKELY(comp)) {
2581
old_heap_no = rec_get_heap_no_new(
2582
page_cur_get_rec(&cur2));
2583
new_heap_no = rec_get_heap_no_new(
2584
page_cur_get_rec(&cur1));
2586
old_heap_no = rec_get_heap_no_old(
2587
page_cur_get_rec(&cur2));
2588
new_heap_no = rec_get_heap_no_old(
2589
page_cur_get_rec(&cur1));
2568
old_heap_no = rec_get_heap_no(page_cur_get_rec(&cur2),
2592
2571
if (lock_rec_get_nth_bit(lock, old_heap_no)) {
2594
/* Clear the bit in old_lock. */
2595
ut_d(lock_rec_reset_nth_bit(lock,
2598
2573
/* NOTE that the old lock bitmap could be too
2599
2574
small for the new heap number! */
2601
lock_rec_add_to_queue(lock->type_mode, block,
2576
lock_rec_add_to_queue(lock->type_mode,
2577
page_cur_get_rec(&cur1),
2603
2578
lock->index, lock->trx);
2605
/* if (new_heap_no == PAGE_HEAP_NO_SUPREMUM
2580
/* if ((page_cur_get_rec(&cur1) == sup)
2606
2581
&& lock_get_wait(lock)) {
2607
2582
fprintf(stderr,
2608
2583
"---\n--\n!!!Lock reorg: supr type %lu\n",
2621
2594
page_cur_move_to_next(&cur2);
2626
ulint i = lock_rec_find_set_bit(lock);
2597
/* Remember that we chained old locks on the trx_locks field */
2628
/* Check that all locks were moved. */
2629
if (UNIV_UNLIKELY(i != ULINT_UNDEFINED)) {
2631
"lock_move_reorganize_page():"
2632
" %lu not moved in %p\n",
2633
(ulong) i, (void*) lock);
2637
#endif /* UNIV_DEBUG */
2599
lock = UT_LIST_GET_NEXT(trx_locks, lock);
2640
2602
lock_mutex_exit_kernel();
2642
2604
mem_heap_free(heap);
2644
#ifdef UNIV_DEBUG_LOCK_VALIDATE
2645
ut_ad(lock_rec_validate_page(buf_block_get_space(block),
2646
buf_block_get_page_no(block)));
2607
ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page),
2608
buf_frame_get_page_no(page)));
2650
2612
/*****************************************************************
2651
2613
Moves the explicit locks on user records to another page if a record
2652
2614
list end is moved to another page. */
2655
2617
lock_move_rec_list_end(
2656
2618
/*===================*/
2657
const buf_block_t* new_block, /* in: index page to move to */
2658
const buf_block_t* block, /* in: index page */
2659
const rec_t* rec) /* in: record on page: this
2660
is the first record moved */
2619
page_t* new_page, /* in: index page to move to */
2620
page_t* page, /* in: index page */
2621
rec_t* rec) /* in: record on page: this is the
2622
first record moved */
2663
const ulint comp = page_rec_is_comp(rec);
2631
ut_ad(page == buf_frame_align(rec));
2665
2633
lock_mutex_enter_kernel();
2670
2638
table to the end of the hash chain, and lock_rec_add_to_queue
2671
2639
does not reuse locks if there are waiters in the queue. */
2673
for (lock = lock_rec_get_first_on_page(block); lock;
2674
lock = lock_rec_get_next_on_page(lock)) {
2677
const ulint type_mode = lock->type_mode;
2679
page_cur_position(rec, block, &cur1);
2641
sup = page_get_supremum_rec(page);
2643
lock = lock_rec_get_first_on_page(page);
2645
comp = page_is_comp(page);
2647
while (lock != NULL) {
2649
page_cur_position(rec, &cur1);
2681
2651
if (page_cur_is_before_first(&cur1)) {
2682
2652
page_cur_move_to_next(&cur1);
2685
page_cur_set_before_first(new_block, &cur2);
2655
page_cur_set_before_first(new_page, &cur2);
2686
2656
page_cur_move_to_next(&cur2);
2688
2658
/* Copy lock requests on user records to new page and
2689
2659
reset the lock bits on the old */
2691
while (!page_cur_is_after_last(&cur1)) {
2695
heap_no = rec_get_heap_no_new(
2696
page_cur_get_rec(&cur1));
2698
heap_no = rec_get_heap_no_old(
2699
page_cur_get_rec(&cur1));
2700
ut_ad(!memcmp(page_cur_get_rec(&cur1),
2701
page_cur_get_rec(&cur2),
2702
rec_get_data_size_old(
2703
page_cur_get_rec(&cur2))));
2661
while (page_cur_get_rec(&cur1) != sup) {
2662
ut_ad(comp || !memcmp(page_cur_get_rec(&cur1),
2663
page_cur_get_rec(&cur2),
2664
rec_get_data_size_old(
2667
heap_no = rec_get_heap_no(page_cur_get_rec(&cur1),
2706
2670
if (lock_rec_get_nth_bit(lock, heap_no)) {
2671
type_mode = lock->type_mode;
2707
2673
lock_rec_reset_nth_bit(lock, heap_no);
2709
if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
2675
if (lock_get_wait(lock)) {
2710
2676
lock_reset_lock_and_trx_wait(lock);
2714
heap_no = rec_get_heap_no_new(
2715
page_cur_get_rec(&cur2));
2717
heap_no = rec_get_heap_no_old(
2718
page_cur_get_rec(&cur2));
2721
2679
lock_rec_add_to_queue(type_mode,
2680
page_cur_get_rec(&cur2),
2723
2681
lock->index, lock->trx);
2726
2684
page_cur_move_to_next(&cur1);
2727
2685
page_cur_move_to_next(&cur2);
2688
lock = lock_rec_get_next_on_page(lock);
2731
2691
lock_mutex_exit_kernel();
2733
#ifdef UNIV_DEBUG_LOCK_VALIDATE
2734
ut_ad(lock_rec_validate_page(buf_block_get_space(block),
2735
buf_block_get_page_no(block)));
2736
ut_ad(lock_rec_validate_page(buf_block_get_space(new_block),
2737
buf_block_get_page_no(new_block)));
2694
ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page),
2695
buf_frame_get_page_no(page)));
2696
ut_ad(lock_rec_validate_page(buf_frame_get_space_id(new_page),
2697
buf_frame_get_page_no(new_page)));
2741
2701
/*****************************************************************
2742
2702
Moves the explicit locks on user records to another page if a record
2743
2703
list start is moved to another page. */
2746
2706
lock_move_rec_list_start(
2747
2707
/*=====================*/
2748
const buf_block_t* new_block, /* in: index page to move to */
2749
const buf_block_t* block, /* in: index page */
2750
const rec_t* rec, /* in: record on page:
2752
record NOT copied */
2753
const rec_t* old_end) /* in: old
2708
page_t* new_page, /* in: index page to move to */
2709
page_t* page, /* in: index page */
2710
rec_t* rec, /* in: record on page: this is the
2711
first record NOT copied */
2712
rec_t* old_end) /* in: old previous-to-last record on
2713
new_page before the records were copied */
2760
const ulint comp = page_rec_is_comp(rec);
2762
ut_ad(block->frame == page_align(rec));
2763
ut_ad(new_block->frame == page_align(old_end));
2765
2724
lock_mutex_enter_kernel();
2767
for (lock = lock_rec_get_first_on_page(block); lock;
2768
lock = lock_rec_get_next_on_page(lock)) {
2771
const ulint type_mode = lock->type_mode;
2773
page_cur_set_before_first(block, &cur1);
2726
lock = lock_rec_get_first_on_page(page);
2727
comp = page_is_comp(page);
2728
ut_ad(comp == page_is_comp(new_page));
2729
ut_ad(page == buf_frame_align(rec));
2731
while (lock != NULL) {
2733
page_cur_set_before_first(page, &cur1);
2774
2734
page_cur_move_to_next(&cur1);
2776
page_cur_position(old_end, new_block, &cur2);
2736
page_cur_position(old_end, &cur2);
2777
2737
page_cur_move_to_next(&cur2);
2779
2739
/* Copy lock requests on user records to new page and
2780
2740
reset the lock bits on the old */
2782
2742
while (page_cur_get_rec(&cur1) != rec) {
2786
heap_no = rec_get_heap_no_new(
2787
page_cur_get_rec(&cur1));
2789
heap_no = rec_get_heap_no_old(
2790
page_cur_get_rec(&cur1));
2791
ut_ad(!memcmp(page_cur_get_rec(&cur1),
2743
ut_ad(comp || !memcmp(page_cur_get_rec(&cur1),
2792
2744
page_cur_get_rec(&cur2),
2793
2745
rec_get_data_size_old(
2794
2746
page_cur_get_rec(
2748
heap_no = rec_get_heap_no(page_cur_get_rec(&cur1),
2798
2751
if (lock_rec_get_nth_bit(lock, heap_no)) {
2752
type_mode = lock->type_mode;
2799
2754
lock_rec_reset_nth_bit(lock, heap_no);
2801
if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
2756
if (lock_get_wait(lock)) {
2802
2757
lock_reset_lock_and_trx_wait(lock);
2806
heap_no = rec_get_heap_no_new(
2807
page_cur_get_rec(&cur2));
2809
heap_no = rec_get_heap_no_old(
2810
page_cur_get_rec(&cur2));
2813
2760
lock_rec_add_to_queue(type_mode,
2761
page_cur_get_rec(&cur2),
2815
2762
lock->index, lock->trx);
2819
2766
page_cur_move_to_next(&cur2);
2823
if (page_rec_is_supremum(rec)) {
2826
for (i = PAGE_HEAP_NO_USER_LOW;
2827
i < lock_rec_get_n_bits(lock); i++) {
2829
(lock_rec_get_nth_bit(lock, i))) {
2832
"lock_move_rec_list_start():"
2833
" %lu not moved in %p\n",
2834
(ulong) i, (void*) lock);
2839
#endif /* UNIV_DEBUG */
2769
lock = lock_rec_get_next_on_page(lock);
2842
2772
lock_mutex_exit_kernel();
2844
#ifdef UNIV_DEBUG_LOCK_VALIDATE
2845
ut_ad(lock_rec_validate_page(buf_block_get_space(block),
2846
buf_block_get_page_no(block)));
2774
ut_ad(lock_rec_validate_page(buf_frame_get_space_id(page),
2775
buf_frame_get_page_no(page)));
2776
ut_ad(lock_rec_validate_page(buf_frame_get_space_id(new_page),
2777
buf_frame_get_page_no(new_page)));
2850
2781
/*****************************************************************
2851
2782
Updates the lock table when a page is split to the right. */
2854
2785
lock_update_split_right(
2855
2786
/*====================*/
2856
const buf_block_t* right_block, /* in: right page */
2857
const buf_block_t* left_block) /* in: left page */
2787
page_t* right_page, /* in: right page */
2788
page_t* left_page) /* in: left page */
2859
ulint heap_no = lock_get_min_heap_no(right_block);
2861
2791
lock_mutex_enter_kernel();
2792
comp = page_is_comp(left_page);
2793
ut_ad(comp == page_is_comp(right_page));
2863
2795
/* Move the locks on the supremum of the left page to the supremum
2864
2796
of the right page */
2866
lock_rec_move(right_block, left_block,
2867
PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
2798
lock_rec_move(page_get_supremum_rec(right_page),
2799
page_get_supremum_rec(left_page), comp);
2869
2801
/* Inherit the locks to the supremum of left page from the successor
2870
2802
of the infimum on right page */
2872
lock_rec_inherit_to_gap(left_block, right_block,
2873
PAGE_HEAP_NO_SUPREMUM, heap_no);
2804
lock_rec_inherit_to_gap(page_get_supremum_rec(left_page),
2806
page_get_infimum_rec(right_page)));
2875
2808
lock_mutex_exit_kernel();
2878
2811
/*****************************************************************
2879
2812
Updates the lock table when a page is merged to the right. */
2882
2815
lock_update_merge_right(
2883
2816
/*====================*/
2884
const buf_block_t* right_block, /* in: right page to
2886
const rec_t* orig_succ, /* in: original
2887
successor of infimum
2890
const buf_block_t* left_block) /* in: merged index
2817
rec_t* orig_succ, /* in: original successor of infimum
2818
on the right page before merge */
2819
page_t* left_page) /* in: merged index page which will be
2894
2822
lock_mutex_enter_kernel();
2919
2844
pages: the reason is that in a pessimistic update the infimum record
2920
2845
of the root page will act as a dummy carrier of the locks of the record
2921
2846
to be updated. */
2924
2849
lock_update_root_raise(
2925
2850
/*===================*/
2926
const buf_block_t* block, /* in: index page to which copied */
2927
const buf_block_t* root) /* in: root page */
2851
page_t* new_page, /* in: index page to which copied */
2852
page_t* root) /* in: root page */
2929
2855
lock_mutex_enter_kernel();
2856
comp = page_is_comp(root);
2857
ut_ad(comp == page_is_comp(new_page));
2931
2859
/* Move the locks on the supremum of the root to the supremum
2934
lock_rec_move(block, root,
2935
PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
2862
lock_rec_move(page_get_supremum_rec(new_page),
2863
page_get_supremum_rec(root), comp);
2936
2864
lock_mutex_exit_kernel();
2939
2867
/*****************************************************************
2940
2868
Updates the lock table when a page is copied to another and the original page
2941
2869
is removed from the chain of leaf pages, except if page is the root! */
2944
2872
lock_update_copy_and_discard(
2945
2873
/*=========================*/
2946
const buf_block_t* new_block, /* in: index page to
2948
const buf_block_t* block) /* in: index page;
2874
page_t* new_page, /* in: index page to which copied */
2875
page_t* page) /* in: index page; NOT the root! */
2951
2878
lock_mutex_enter_kernel();
2879
comp = page_is_comp(page);
2880
ut_ad(comp == page_is_comp(new_page));
2953
2882
/* Move the locks on the supremum of the old page to the supremum
2956
lock_rec_move(new_block, block,
2957
PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
2958
lock_rec_free_all_from_discard_page(block);
2885
lock_rec_move(page_get_supremum_rec(new_page),
2886
page_get_supremum_rec(page), comp);
2887
lock_rec_free_all_from_discard_page(page);
2960
2889
lock_mutex_exit_kernel();
2963
2892
/*****************************************************************
2964
2893
Updates the lock table when a page is split to the left. */
2967
2896
lock_update_split_left(
2968
2897
/*===================*/
2969
const buf_block_t* right_block, /* in: right page */
2970
const buf_block_t* left_block) /* in: left page */
2898
page_t* right_page, /* in: right page */
2899
page_t* left_page) /* in: left page */
2972
ulint heap_no = lock_get_min_heap_no(right_block);
2974
2901
lock_mutex_enter_kernel();
2976
2903
/* Inherit the locks to the supremum of the left page from the
2977
2904
successor of the infimum on the right page */
2979
lock_rec_inherit_to_gap(left_block, right_block,
2980
PAGE_HEAP_NO_SUPREMUM, heap_no);
2906
lock_rec_inherit_to_gap(page_get_supremum_rec(left_page),
2908
page_get_infimum_rec(right_page)));
2982
2910
lock_mutex_exit_kernel();
2985
2913
/*****************************************************************
2986
2914
Updates the lock table when a page is merged to the left. */
2989
2917
lock_update_merge_left(
2990
2918
/*===================*/
2991
const buf_block_t* left_block, /* in: left page to
2993
const rec_t* orig_pred, /* in: original predecessor
2994
of supremum on the left page
2996
const buf_block_t* right_block) /* in: merged index page
2997
which will be discarded */
2919
page_t* left_page, /* in: left page to which merged */
2920
rec_t* orig_pred, /* in: original predecessor of supremum
2921
on the left page before merge */
2922
page_t* right_page) /* in: merged index page which will be
2999
const rec_t* left_next_rec;
3001
ut_ad(left_block->frame == page_align(orig_pred));
2925
rec_t* left_next_rec;
2926
rec_t* left_supremum;
3003
2928
lock_mutex_enter_kernel();
3005
left_next_rec = page_rec_get_next_const(orig_pred);
3007
if (!page_rec_is_supremum(left_next_rec)) {
2929
comp = page_is_comp(left_page);
2930
ut_ad(comp == page_is_comp(right_page));
2931
ut_ad(left_page == buf_frame_align(orig_pred));
2933
left_next_rec = page_rec_get_next(orig_pred);
2934
left_supremum = page_get_supremum_rec(left_page);
2936
if (UNIV_LIKELY(left_next_rec != left_supremum)) {
3009
2938
/* Inherit the locks on the supremum of the left page to the
3010
2939
first record which was moved from the right page */
3012
lock_rec_inherit_to_gap(left_block, left_block,
3013
page_rec_get_heap_no(left_next_rec),
3014
PAGE_HEAP_NO_SUPREMUM);
2941
lock_rec_inherit_to_gap(left_next_rec, left_supremum);
3016
2943
/* Reset the locks on the supremum of the left page,
3017
2944
releasing waiting transactions */
3019
lock_rec_reset_and_release_wait(left_block,
3020
PAGE_HEAP_NO_SUPREMUM);
2946
lock_rec_reset_and_release_wait(left_supremum);
3023
2949
/* Move the locks from the supremum of right page to the supremum
3024
2950
of the left page */
3026
lock_rec_move(left_block, right_block,
3027
PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
2952
lock_rec_move(left_supremum, page_get_supremum_rec(right_page), comp);
3029
lock_rec_free_all_from_discard_page(right_block);
2954
lock_rec_free_all_from_discard_page(right_page);
3031
2956
lock_mutex_exit_kernel();
3034
2959
/*****************************************************************
3035
2960
Resets the original locks on heir and replaces them with gap type locks
3036
2961
inherited from rec. */
3039
2964
lock_rec_reset_and_inherit_gap_locks(
3040
2965
/*=================================*/
3041
const buf_block_t* heir_block, /* in: block containing the
3042
record which inherits */
3043
const buf_block_t* block, /* in: block containing the
3044
record from which inherited;
3045
does NOT reset the locks on
3047
ulint heir_heap_no, /* in: heap_no of the
3048
inheriting record */
3049
ulint heap_no) /* in: heap_no of the
2966
rec_t* heir, /* in: heir record */
2967
rec_t* rec) /* in: record */
3052
2969
mutex_enter(&kernel_mutex);
3054
lock_rec_reset_and_release_wait(heir_block, heir_heap_no);
2971
lock_rec_reset_and_release_wait(heir);
3056
lock_rec_inherit_to_gap(heir_block, block, heir_heap_no, heap_no);
2973
lock_rec_inherit_to_gap(heir, rec);
3058
2975
mutex_exit(&kernel_mutex);
3061
2978
/*****************************************************************
3062
2979
Updates the lock table when a page is discarded. */
3065
2982
lock_update_discard(
3066
2983
/*================*/
3067
const buf_block_t* heir_block, /* in: index page
3068
which will inherit the locks */
3069
ulint heir_heap_no, /* in: heap_no of the record
3070
which will inherit the locks */
3071
const buf_block_t* block) /* in: index page
3072
which will be discarded */
2984
rec_t* heir, /* in: record which will inherit the locks */
2985
page_t* page) /* in: index page which will be discarded */
3074
const page_t* page = block->frame;
3078
2989
lock_mutex_enter_kernel();
3080
if (!lock_rec_get_first_on_page(block)) {
2991
if (NULL == lock_rec_get_first_on_page(page)) {
3081
2992
/* No locks exist on page, nothing to do */
3083
2994
lock_mutex_exit_kernel();
3088
2999
/* Inherit all the locks on the page to the record and reset all
3089
3000
the locks on the page */
3091
if (page_is_comp(page)) {
3092
rec = page + PAGE_NEW_INFIMUM;
3095
heap_no = rec_get_heap_no_new(rec);
3097
lock_rec_inherit_to_gap(heir_block, block,
3098
heir_heap_no, heap_no);
3100
lock_rec_reset_and_release_wait(block, heap_no);
3102
rec = page + rec_get_next_offs(rec, TRUE);
3103
} while (heap_no != PAGE_HEAP_NO_SUPREMUM);
3105
rec = page + PAGE_OLD_INFIMUM;
3108
heap_no = rec_get_heap_no_old(rec);
3110
lock_rec_inherit_to_gap(heir_block, block,
3111
heir_heap_no, heap_no);
3113
lock_rec_reset_and_release_wait(block, heap_no);
3115
rec = page + rec_get_next_offs(rec, FALSE);
3116
} while (heap_no != PAGE_HEAP_NO_SUPREMUM);
3002
rec = page_get_infimum_rec(page);
3005
lock_rec_inherit_to_gap(heir, rec);
3007
/* Reset the locks on rec, releasing waiting transactions */
3009
lock_rec_reset_and_release_wait(rec);
3011
if (page_rec_is_supremum(rec)) {
3016
rec = page_rec_get_next(rec);
3119
lock_rec_free_all_from_discard_page(block);
3019
lock_rec_free_all_from_discard_page(page);
3121
3021
lock_mutex_exit_kernel();
3124
3024
/*****************************************************************
3125
3025
Updates the lock table when a new user record is inserted. */
3128
3028
lock_update_insert(
3129
3029
/*===============*/
3130
const buf_block_t* block, /* in: buffer block containing rec */
3131
const rec_t* rec) /* in: the inserted record */
3030
rec_t* rec) /* in: the inserted record */
3133
ulint receiver_heap_no;
3134
ulint donator_heap_no;
3136
ut_ad(block->frame == page_align(rec));
3032
lock_mutex_enter_kernel();
3138
3034
/* Inherit the gap-locking locks for rec, in gap mode, from the next
3141
if (page_rec_is_comp(rec)) {
3142
receiver_heap_no = rec_get_heap_no_new(rec);
3143
donator_heap_no = rec_get_heap_no_new(
3144
page_rec_get_next_low(rec, TRUE));
3146
receiver_heap_no = rec_get_heap_no_old(rec);
3147
donator_heap_no = rec_get_heap_no_old(
3148
page_rec_get_next_low(rec, FALSE));
3037
lock_rec_inherit_to_gap_if_gap_lock(rec, page_rec_get_next(rec));
3151
lock_mutex_enter_kernel();
3152
lock_rec_inherit_to_gap_if_gap_lock(block,
3153
receiver_heap_no, donator_heap_no);
3154
3039
lock_mutex_exit_kernel();
3157
3042
/*****************************************************************
3158
3043
Updates the lock table when a record is removed. */
3161
3046
lock_update_delete(
3162
3047
/*===============*/
3163
const buf_block_t* block, /* in: buffer block containing rec */
3164
const rec_t* rec) /* in: the record to be removed */
3048
rec_t* rec) /* in: the record to be removed */
3166
const page_t* page = block->frame;
3170
ut_ad(page == page_align(rec));
3172
if (page_is_comp(page)) {
3173
heap_no = rec_get_heap_no_new(rec);
3174
next_heap_no = rec_get_heap_no_new(page
3175
+ rec_get_next_offs(rec,
3178
heap_no = rec_get_heap_no_old(rec);
3179
next_heap_no = rec_get_heap_no_old(page
3180
+ rec_get_next_offs(rec,
3184
3050
lock_mutex_enter_kernel();
3186
3052
/* Let the next record inherit the locks from rec, in gap mode */
3188
lock_rec_inherit_to_gap(block, block, next_heap_no, heap_no);
3054
lock_rec_inherit_to_gap(page_rec_get_next(rec), rec);
3190
3056
/* Reset the lock bits on rec and release waiting transactions */
3192
lock_rec_reset_and_release_wait(block, heap_no);
3058
lock_rec_reset_and_release_wait(rec);
3194
3060
lock_mutex_exit_kernel();
3201
3067
is moved in such an update, perhaps to another page. The infimum record
3202
3068
acts as a dummy carrier record, taking care of lock releases while the
3203
3069
actual record is being moved. */
3206
3072
lock_rec_store_on_page_infimum(
3207
3073
/*===========================*/
3208
const buf_block_t* block, /* in: buffer block containing rec */
3209
const rec_t* rec) /* in: record whose lock state
3210
is stored on the infimum
3211
record of the same page; lock
3212
bits are reset on the
3074
page_t* page, /* in: page containing the record */
3075
rec_t* rec) /* in: record whose lock state is stored
3076
on the infimum record of the same page; lock
3077
bits are reset on the record */
3215
ulint heap_no = page_rec_get_heap_no(rec);
3217
ut_ad(block->frame == page_align(rec));
3079
ut_ad(page == buf_frame_align(rec));
3219
3081
lock_mutex_enter_kernel();
3221
lock_rec_move(block, block, PAGE_HEAP_NO_INFIMUM, heap_no);
3083
lock_rec_move(page_get_infimum_rec(page), rec, page_is_comp(page));
3223
3085
lock_mutex_exit_kernel();
3226
3088
/*************************************************************************
3227
3089
Restores the state of explicit lock requests on a single record, where the
3228
3090
state was stored on the infimum of the page. */
3231
3093
lock_rec_restore_from_page_infimum(
3232
3094
/*===============================*/
3233
const buf_block_t* block, /* in: buffer block containing rec */
3234
const rec_t* rec, /* in: record whose lock state
3236
const buf_block_t* donator)/* in: page (rec is not
3237
necessarily on this page)
3238
whose infimum stored the lock
3239
state; lock bits are reset on
3095
rec_t* rec, /* in: record whose lock state is restored */
3096
page_t* page) /* in: page (rec is not necessarily on this page)
3097
whose infimum stored the lock state; lock bits are
3098
reset on the infimum */
3242
ulint heap_no = page_rec_get_heap_no(rec);
3244
3101
lock_mutex_enter_kernel();
3102
comp = page_is_comp(page);
3103
ut_ad(!comp == !page_rec_is_comp(rec));
3246
lock_rec_move(block, donator, heap_no, PAGE_HEAP_NO_INFIMUM);
3105
lock_rec_move(rec, page_get_infimum_rec(page), comp);
3248
3107
lock_mutex_exit_kernel();
3871
3726
Removes a granted record lock of a transaction from the queue and grants
3872
3727
locks to other transactions waiting in the queue if they now are entitled
3876
3731
lock_rec_unlock(
3877
3732
/*============*/
3878
trx_t* trx, /* in: transaction that has
3879
set a record lock */
3880
const buf_block_t* block, /* in: buffer block containing rec */
3881
const rec_t* rec, /* in: record */
3882
enum lock_mode lock_mode)/* in: LOCK_S or LOCK_X */
3733
trx_t* trx, /* in: transaction that has set a record
3735
rec_t* rec, /* in: record */
3736
ulint lock_mode) /* in: LOCK_S or LOCK_X */
3885
3739
lock_t* release_lock = NULL;
3888
3742
ut_ad(trx && rec);
3889
ut_ad(block->frame == page_align(rec));
3891
heap_no = page_rec_get_heap_no(rec);
3893
3744
mutex_enter(&kernel_mutex);
3895
lock = lock_rec_get_first(block, heap_no);
3746
heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));
3748
lock = lock_rec_get_first(rec);
3897
3750
/* Find the last lock with the same lock_mode and transaction
3898
3751
from the record. */
4134
3988
/*************************************************************************
4135
3989
Prints info of a table lock. */
4138
3992
lock_table_print(
4139
3993
/*=============*/
4140
FILE* file, /* in: file where to print */
4141
const lock_t* lock) /* in: table type lock */
3994
FILE* file, /* in: file where to print */
3995
lock_t* lock) /* in: table type lock */
4143
3997
ut_ad(mutex_own(&kernel_mutex));
4144
ut_a(lock_get_type_low(lock) == LOCK_TABLE);
3998
ut_a(lock_get_type(lock) == LOCK_TABLE);
4146
4000
fputs("TABLE LOCK table ", file);
4147
4001
ut_print_name(file, lock->trx, TRUE,
4148
4002
lock->un_member.tab_lock.table->name);
4149
fprintf(file, " trx id " TRX_ID_FMT,
4150
TRX_ID_PREP_PRINTF(lock->trx->id));
4003
fprintf(file, " trx id %lu %lu",
4004
(ulong) (lock->trx)->id.high, (ulong) (lock->trx)->id.low);
4152
4006
if (lock_get_mode(lock) == LOCK_S) {
4153
4007
fputs(" lock mode S", file);
4232
4087
putc('\n', file);
4234
block = buf_page_try_get(space, page_no, &mtr);
4237
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
4239
if (lock_rec_get_nth_bit(lock, i)) {
4242
= page_find_rec_with_heap_no(
4243
buf_block_get_frame(block), i);
4089
/* If the page is not in the buffer pool, we cannot load it
4090
because we have the kernel mutex and ibuf operations would
4091
break the latching order */
4093
page = buf_page_get_gen(space, page_no, RW_NO_LATCH,
4094
NULL, BUF_GET_IF_IN_POOL,
4095
__FILE__, __LINE__, &mtr);
4097
page = buf_page_get_nowait(space, page_no, RW_S_LATCH, &mtr);
4100
/* Let us try to get an X-latch. If the current thread
4101
is holding an X-latch on the page, we cannot get an
4104
page = buf_page_get_nowait(space, page_no, RW_X_LATCH,
4110
#ifdef UNIV_SYNC_DEBUG
4111
buf_page_dbg_add_level(page, SYNC_NO_ORDER_CHECK);
4112
#endif /* UNIV_SYNC_DEBUG */
4115
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
4117
if (lock_rec_get_nth_bit(lock, i)) {
4119
fprintf(file, "Record lock, heap no %lu ", (ulong) i);
4123
= page_find_rec_with_heap_no(page, i);
4244
4124
offsets = rec_get_offsets(
4245
4125
rec, lock->index, offsets,
4246
4126
ULINT_UNDEFINED, &heap);
4248
fprintf(file, "Record lock, heap no %lu ",
4250
4127
rec_print_new(file, rec, offsets);
4255
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
4256
fprintf(file, "Record lock, heap no %lu\n", (ulong) i);
4318
4192
"TRANSACTIONS\n"
4319
4193
"------------\n", file);
4321
fprintf(file, "Trx id counter " TRX_ID_FMT "\n",
4322
TRX_ID_PREP_PRINTF(trx_sys->max_trx_id));
4195
fprintf(file, "Trx id counter %lu %lu\n",
4196
(ulong) ut_dulint_get_high(trx_sys->max_trx_id),
4197
(ulong) ut_dulint_get_low(trx_sys->max_trx_id));
4325
"Purge done for trx's n:o < " TRX_ID_FMT
4326
" undo n:o < " TRX_ID_FMT "\n",
4327
TRX_ID_PREP_PRINTF(purge_sys->purge_trx_no),
4328
TRX_ID_PREP_PRINTF(purge_sys->purge_undo_no));
4200
"Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n",
4201
(ulong) ut_dulint_get_high(purge_sys->purge_trx_no),
4202
(ulong) ut_dulint_get_low(purge_sys->purge_trx_no),
4203
(ulong) ut_dulint_get_high(purge_sys->purge_undo_no),
4204
(ulong) ut_dulint_get_low(purge_sys->purge_undo_no));
4331
4207
"History list length %lu\n",
4536
4416
/*************************************************************************
4537
4417
Validates the lock queue on a single record. */
4540
4420
lock_rec_queue_validate(
4541
4421
/*====================*/
4542
/* out: TRUE if ok */
4543
const buf_block_t* block, /* in: buffer block containing rec */
4544
const rec_t* rec, /* in: record to look at */
4545
dict_index_t* index, /* in: index, or NULL if not known */
4546
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
4422
/* out: TRUE if ok */
4423
rec_t* rec, /* in: record to look at */
4424
dict_index_t* index, /* in: index, or NULL if not known */
4425
const ulint* offsets)/* in: rec_get_offsets(rec, index) */
4548
4427
trx_t* impl_trx;
4553
ut_a(block->frame == page_align(rec));
4554
4431
ut_ad(rec_offs_validate(rec, index, offsets));
4555
4432
ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
4557
heap_no = page_rec_get_heap_no(rec);
4559
4434
lock_mutex_enter_kernel();
4561
4436
if (!page_rec_is_user_rec(rec)) {
4563
lock = lock_rec_get_first(block, heap_no);
4438
lock = lock_rec_get_first(rec);
4566
4441
switch(lock->trx->conc_state) {
4842
4711
be suspended for some reason; if not, then puts the transaction and
4843
4712
the query thread to the lock wait state and inserts a waiting request
4844
4713
for a gap x-lock to the lock queue. */
4847
4716
lock_rec_insert_check_and_lock(
4848
4717
/*===========================*/
4849
4718
/* out: DB_SUCCESS, DB_LOCK_WAIT,
4850
4719
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
4851
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is
4852
set, does nothing */
4720
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
4853
4722
rec_t* rec, /* in: record after which to insert */
4854
buf_block_t* block, /* in/out: buffer block of rec */
4855
4723
dict_index_t* index, /* in: index */
4856
4724
que_thr_t* thr, /* in: query thread */
4857
ibool* inherit)/* out: set to TRUE if the new
4858
inserted record maybe should inherit
4859
LOCK_GAP type locks from the successor
4725
ibool* inherit)/* out: set to TRUE if the new inserted
4726
record maybe should inherit LOCK_GAP type
4727
locks from the successor record */
4862
const rec_t* next_rec;
4866
ulint next_rec_heap_no;
4868
ut_ad(block->frame == page_align(rec));
4870
4734
if (flags & BTR_NO_LOCKING_FLAG) {
4872
4736
return(DB_SUCCESS);
4875
4741
trx = thr_get_trx(thr);
4876
4742
next_rec = page_rec_get_next(rec);
4877
next_rec_heap_no = page_rec_get_heap_no(next_rec);
4879
4746
lock_mutex_enter_kernel();
4881
/* When inserting a record into an index, the table must be at
4882
least IX-locked or we must be building an index, in which case
4883
the table must be at least S-locked. */
4884
ut_ad(lock_table_has(trx, index->table, LOCK_IX)
4885
|| (*index->name == TEMP_INDEX_PREFIX
4886
&& lock_table_has(trx, index->table, LOCK_S)));
4888
lock = lock_rec_get_first(block, next_rec_heap_no);
4890
if (UNIV_LIKELY(lock == NULL)) {
4748
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
4750
lock = lock_rec_get_first(next_rec);
4891
4753
/* We optimize CPU time usage in the simplest case */
4893
4755
lock_mutex_exit_kernel();
4895
if (!dict_index_is_clust(index)) {
4757
if (!(index->type & DICT_CLUSTERED)) {
4896
4759
/* Update the page max trx id field */
4897
page_update_max_trx_id(block,
4898
buf_block_get_page_zip(block),
4760
page_update_max_trx_id(buf_frame_align(rec),
4761
thr_get_trx(thr)->id);
4904
4764
return(DB_SUCCESS);
5008
4863
reason; if not, then puts the transaction and the query thread to the
5009
4864
lock wait state and inserts a waiting request for a record x-lock to the
5013
4868
lock_clust_rec_modify_check_and_lock(
5014
4869
/*=================================*/
5016
DB_LOCK_WAIT, DB_DEADLOCK, or
5017
DB_QUE_THR_SUSPENDED */
5018
ulint flags, /* in: if BTR_NO_LOCKING_FLAG
5019
bit is set, does nothing */
5020
const buf_block_t* block, /* in: buffer block of rec */
5021
const rec_t* rec, /* in: record which should be
5023
dict_index_t* index, /* in: clustered index */
5024
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
5025
que_thr_t* thr) /* in: query thread */
4870
/* out: DB_SUCCESS, DB_LOCK_WAIT,
4871
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
4872
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
4874
rec_t* rec, /* in: record which should be modified */
4875
dict_index_t* index, /* in: clustered index */
4876
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
4877
que_thr_t* thr) /* in: query thread */
5030
4881
ut_ad(rec_offs_validate(rec, index, offsets));
5031
ut_ad(dict_index_is_clust(index));
5032
ut_ad(block->frame == page_align(rec));
4882
ut_ad(index->type & DICT_CLUSTERED);
5034
4884
if (flags & BTR_NO_LOCKING_FLAG) {
5036
4886
return(DB_SUCCESS);
5039
heap_no = rec_offs_comp(offsets)
5040
? rec_get_heap_no_new(rec)
5041
: rec_get_heap_no_old(rec);
5043
4889
lock_mutex_enter_kernel();
5045
4891
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
5062
4907
/*************************************************************************
5063
4908
Checks if locks of other transactions prevent an immediate modify (delete
5064
4909
mark or delete unmark) of a secondary index record. */
5067
4912
lock_sec_rec_modify_check_and_lock(
5068
4913
/*===============================*/
5069
4914
/* out: DB_SUCCESS, DB_LOCK_WAIT,
5070
4915
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5071
ulint flags, /* in: if BTR_NO_LOCKING_FLAG
5072
bit is set, does nothing */
5073
buf_block_t* block, /* in/out: buffer block of rec */
5074
rec_t* rec, /* in: record which should be
5075
modified; NOTE: as this is a secondary
5076
index, we always have to modify the
5077
clustered index record first: see the
4916
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
4918
rec_t* rec, /* in: record which should be modified;
4919
NOTE: as this is a secondary index, we
4920
always have to modify the clustered index
4921
record first: see the comment below */
5079
4922
dict_index_t* index, /* in: secondary index */
5080
4923
que_thr_t* thr) /* in: query thread */
5085
ut_ad(!dict_index_is_clust(index));
5086
ut_ad(block->frame == page_align(rec));
5088
4927
if (flags & BTR_NO_LOCKING_FLAG) {
5090
4929
return(DB_SUCCESS);
5093
heap_no = page_rec_get_heap_no(rec);
4932
ut_ad(!(index->type & DICT_CLUSTERED));
5095
4934
/* Another transaction cannot have an implicit lock on the record,
5096
4935
because when we come here, we already have modified the clustered
5135
4973
/*************************************************************************
5136
4974
Like the counterpart for a clustered index below, but now we read a
5137
4975
secondary index record. */
5140
4978
lock_sec_rec_read_check_and_lock(
5141
4979
/*=============================*/
5143
DB_LOCK_WAIT, DB_DEADLOCK, or
5144
DB_QUE_THR_SUSPENDED */
5145
ulint flags, /* in: if BTR_NO_LOCKING_FLAG
5146
bit is set, does nothing */
5147
const buf_block_t* block, /* in: buffer block of rec */
5148
const rec_t* rec, /* in: user record or page
5149
supremum record which should
5150
be read or passed over by a
5152
dict_index_t* index, /* in: secondary index */
5153
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
5154
enum lock_mode mode, /* in: mode of the lock which
5155
the read cursor should set on
5156
records: LOCK_S or LOCK_X; the
5157
latter is possible in
5158
SELECT FOR UPDATE */
5159
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
5161
que_thr_t* thr) /* in: query thread */
4980
/* out: DB_SUCCESS, DB_LOCK_WAIT,
4981
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
4982
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
4984
rec_t* rec, /* in: user record or page supremum record
4985
which should be read or passed over by a read
4987
dict_index_t* index, /* in: secondary index */
4988
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
4989
ulint mode, /* in: mode of the lock which the read cursor
4990
should set on records: LOCK_S or LOCK_X; the
4991
latter is possible in SELECT FOR UPDATE */
4992
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
4994
que_thr_t* thr) /* in: query thread */
5166
ut_ad(!dict_index_is_clust(index));
5167
ut_ad(block->frame == page_align(rec));
4998
ut_ad(!(index->type & DICT_CLUSTERED));
5168
4999
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
5169
5000
ut_ad(rec_offs_validate(rec, index, offsets));
5170
ut_ad(mode == LOCK_X || mode == LOCK_S);
5172
5002
if (flags & BTR_NO_LOCKING_FLAG) {
5174
5004
return(DB_SUCCESS);
5177
heap_no = page_rec_get_heap_no(rec);
5179
5007
lock_mutex_enter_kernel();
5181
5009
ut_ad(mode != LOCK_X
5187
5015
if the max trx id for the page >= min trx id for the trx list or a
5188
5016
database recovery is running. */
5190
if (((ut_dulint_cmp(page_get_max_trx_id(block->frame),
5018
if (((ut_dulint_cmp(page_get_max_trx_id(buf_frame_align(rec)),
5191
5019
trx_list_get_min_trx_id()) >= 0)
5192
5020
|| recv_recovery_is_on())
5193
5021
&& !page_rec_is_supremum(rec)) {
5195
lock_rec_convert_impl_to_expl(block, rec, index, offsets);
5023
lock_rec_convert_impl_to_expl(rec, index, offsets);
5198
err = lock_rec_lock(FALSE, mode | gap_mode,
5199
block, heap_no, index, thr);
5026
err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
5201
5028
lock_mutex_exit_kernel();
5203
ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5030
ut_ad(lock_rec_queue_validate(rec, index, offsets));
5212
5039
puts the transaction and the query thread to the lock wait state and inserts a
5213
5040
waiting request for a record lock to the lock queue. Sets the requested mode
5214
5041
lock on the record. */
5217
5044
lock_clust_rec_read_check_and_lock(
5218
5045
/*===============================*/
5220
DB_LOCK_WAIT, DB_DEADLOCK, or
5221
DB_QUE_THR_SUSPENDED */
5222
ulint flags, /* in: if BTR_NO_LOCKING_FLAG
5223
bit is set, does nothing */
5224
const buf_block_t* block, /* in: buffer block of rec */
5225
const rec_t* rec, /* in: user record or page
5226
supremum record which should
5227
be read or passed over by a
5229
dict_index_t* index, /* in: clustered index */
5230
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
5231
enum lock_mode mode, /* in: mode of the lock which
5232
the read cursor should set on
5233
records: LOCK_S or LOCK_X; the
5234
latter is possible in
5235
SELECT FOR UPDATE */
5236
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
5238
que_thr_t* thr) /* in: query thread */
5046
/* out: DB_SUCCESS, DB_LOCK_WAIT,
5047
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5048
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
5050
rec_t* rec, /* in: user record or page supremum record
5051
which should be read or passed over by a read
5053
dict_index_t* index, /* in: clustered index */
5054
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
5055
ulint mode, /* in: mode of the lock which the read cursor
5056
should set on records: LOCK_S or LOCK_X; the
5057
latter is possible in SELECT FOR UPDATE */
5058
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
5060
que_thr_t* thr) /* in: query thread */
5243
ut_ad(dict_index_is_clust(index));
5244
ut_ad(block->frame == page_align(rec));
5064
ut_ad(index->type & DICT_CLUSTERED);
5245
5065
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
5246
5066
ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP
5247
5067
|| gap_mode == LOCK_REC_NOT_GAP);
5261
5079
ut_ad(mode != LOCK_S
5262
5080
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
5264
if (UNIV_LIKELY(heap_no != PAGE_HEAP_NO_SUPREMUM)) {
5082
if (!page_rec_is_supremum(rec)) {
5266
lock_rec_convert_impl_to_expl(block, rec, index, offsets);
5084
lock_rec_convert_impl_to_expl(rec, index, offsets);
5269
err = lock_rec_lock(FALSE, mode | gap_mode,
5270
block, heap_no, index, thr);
5087
err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
5272
5089
lock_mutex_exit_kernel();
5274
ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5091
ut_ad(lock_rec_queue_validate(rec, index, offsets));
5284
5101
lock on the record. This is an alternative version of
5285
5102
lock_clust_rec_read_check_and_lock() that does not require the parameter
5289
5106
lock_clust_rec_read_check_and_lock_alt(
5290
5107
/*===================================*/
5292
DB_LOCK_WAIT, DB_DEADLOCK, or
5293
DB_QUE_THR_SUSPENDED */
5294
ulint flags, /* in: if BTR_NO_LOCKING_FLAG
5295
bit is set, does nothing */
5296
const buf_block_t* block, /* in: buffer block of rec */
5297
const rec_t* rec, /* in: user record or page
5298
supremum record which should
5299
be read or passed over by a
5301
dict_index_t* index, /* in: clustered index */
5302
enum lock_mode mode, /* in: mode of the lock which
5303
the read cursor should set on
5304
records: LOCK_S or LOCK_X; the
5305
latter is possible in
5306
SELECT FOR UPDATE */
5307
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
5309
que_thr_t* thr) /* in: query thread */
5108
/* out: DB_SUCCESS, DB_LOCK_WAIT,
5109
DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5110
ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set,
5112
rec_t* rec, /* in: user record or page supremum record
5113
which should be read or passed over by a read
5115
dict_index_t* index, /* in: clustered index */
5116
ulint mode, /* in: mode of the lock which the read cursor
5117
should set on records: LOCK_S or LOCK_X; the
5118
latter is possible in SELECT FOR UPDATE */
5119
ulint gap_mode,/* in: LOCK_ORDINARY, LOCK_GAP, or
5121
que_thr_t* thr) /* in: query thread */
5311
5123
mem_heap_t* tmp_heap = NULL;
5312
5124
ulint offsets_[REC_OFFS_NORMAL_SIZE];
5313
5125
ulint* offsets = offsets_;
5315
rec_offs_init(offsets_);
5127
*offsets_ = (sizeof offsets_) / sizeof *offsets_;
5317
5129
offsets = rec_get_offsets(rec, index, offsets,
5318
5130
ULINT_UNDEFINED, &tmp_heap);
5319
ret = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
5131
ret = lock_clust_rec_read_check_and_lock(flags, rec, index,
5320
5132
offsets, mode, gap_mode, thr);
5321
5133
if (tmp_heap) {
5322
5134
mem_heap_free(tmp_heap);
5327
/***********************************************************************
5328
Gets the type of a lock. Non-inline version for using outside of the
5334
/* out: LOCK_TABLE or LOCK_REC */
5335
const lock_t* lock) /* in: lock */
5337
return(lock_get_type_low(lock));
5340
/***********************************************************************
5341
Gets the id of the transaction owning a lock. */
5346
/* out: transaction id */
5347
const lock_t* lock) /* in: lock */
5349
return(trx_get_id(lock->trx));
5352
/***********************************************************************
5353
Gets the mode of a lock in a human readable string.
5354
The string should not be free()'d or modified. */
5359
/* out: lock mode */
5360
const lock_t* lock) /* in: lock */
5364
is_gap_lock = lock_get_type_low(lock) == LOCK_REC
5365
&& lock_rec_get_gap(lock);
5367
switch (lock_get_mode(lock)) {
5399
/***********************************************************************
5400
Gets the type of a lock in a human readable string.
5401
The string should not be free()'d or modified. */
5406
/* out: lock type */
5407
const lock_t* lock) /* in: lock */
5409
switch (lock_get_type_low(lock)) {
5419
/***********************************************************************
5420
Gets the table on which the lock is. */
5426
const lock_t* lock) /* in: lock */
5428
switch (lock_get_type_low(lock)) {
5430
return(lock->index->table);
5432
return(lock->un_member.tab_lock.table);
5439
/***********************************************************************
5440
Gets the id of the table on which the lock is. */
5445
/* out: id of the table */
5446
const lock_t* lock) /* in: lock */
5448
dict_table_t* table;
5450
table = lock_get_table(lock);
5452
return((ullint)ut_conv_dulint_to_longlong(table->id));
5455
/***********************************************************************
5456
Gets the name of the table on which the lock is.
5457
The string should not be free()'d or modified. */
5460
lock_get_table_name(
5461
/*================*/
5462
/* out: name of the table */
5463
const lock_t* lock) /* in: lock */
5465
dict_table_t* table;
5467
table = lock_get_table(lock);
5469
return(table->name);
5472
/***********************************************************************
5473
For a record lock, gets the index on which the lock is. */
5479
const lock_t* lock) /* in: lock */
5481
ut_a(lock_get_type_low(lock) == LOCK_REC);
5483
return(lock->index);
5486
/***********************************************************************
5487
For a record lock, gets the name of the index on which the lock is.
5488
The string should not be free()'d or modified. */
5491
lock_rec_get_index_name(
5492
/*====================*/
5493
/* out: name of the index */
5494
const lock_t* lock) /* in: lock */
5496
ut_a(lock_get_type_low(lock) == LOCK_REC);
5498
return(lock->index->name);
5501
/***********************************************************************
5502
For a record lock, gets the tablespace number on which the lock is. */
5505
lock_rec_get_space_id(
5506
/*==================*/
5507
/* out: tablespace number */
5508
const lock_t* lock) /* in: lock */
5510
ut_a(lock_get_type_low(lock) == LOCK_REC);
5512
return(lock->un_member.rec_lock.space);
5515
/***********************************************************************
5516
For a record lock, gets the page number on which the lock is. */
5519
lock_rec_get_page_no(
5520
/*=================*/
5521
/* out: page number */
5522
const lock_t* lock) /* in: lock */
5524
ut_a(lock_get_type_low(lock) == LOCK_REC);
5526
return(lock->un_member.rec_lock.page_no);