summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-09-11 15:55:30 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-09-17 14:08:41 +0300
commit00cd53d39aa932718ead738e61d590da28579574 (patch)
tree9f9eef34bfa0b1b3fa8115ffdbe417f480d7d7df
parent852771ba1e41142a84f90e76e4ed228fc7699700 (diff)
downloadmariadb-git-00cd53d39aa932718ead738e61d590da28579574.tar.gz
MDEV-23719: Make lock_sys use page_id_t
Since commit 8ccb3caafb7cba0fca12e89c5c9b67a740364fdd it should be more efficient to use page_id_t rather than two separate variables for tablespace identifier and page number. lock_rec_fold(): Replaced with page_id_t::fold(). lock_rec_hash(): Replaced with lock_sys.hash(page_id). lock_rec_expl_exist_on_page(), lock_rec_get_first_on_page_addr(), lock_rec_get_first_on_page(): Replaced with lock_sys.get_first().
-rw-r--r--storage/innobase/btr/btr0cur.cc3
-rw-r--r--storage/innobase/gis/gis0rtree.cc15
-rw-r--r--storage/innobase/gis/gis0sea.cc12
-rw-r--r--storage/innobase/handler/i_s.cc4
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc18
-rw-r--r--storage/innobase/include/lock0lock.h77
-rw-r--r--storage/innobase/include/lock0lock.ic34
-rw-r--r--storage/innobase/include/lock0prdt.h24
-rw-r--r--storage/innobase/include/lock0priv.h37
-rw-r--r--storage/innobase/include/lock0priv.ic132
-rw-r--r--storage/innobase/include/lock0types.h17
-rw-r--r--storage/innobase/include/trx0i_s.h7
-rw-r--r--storage/innobase/lock/lock0lock.cc346
-rw-r--r--storage/innobase/lock/lock0prdt.cc76
-rw-r--r--storage/innobase/row/row0purge.cc5
-rw-r--r--storage/innobase/trx/trx0i_s.cc29
16 files changed, 259 insertions, 577 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 9c627ecd145..a190c11eb0a 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -5423,8 +5423,7 @@ btr_cur_compress_if_useful(
const buf_block_t* block = btr_cur_get_block(cursor);
/* Check whether page lock prevents the compression */
- if (!lock_test_prdt_page_lock(trx, block->page.id().space(),
- block->page.id().page_no())) {
+ if (!lock_test_prdt_page_lock(trx, block->page.id())) {
return(false);
}
}
diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc
index 778202a11c6..2e50d1b2cad 100644
--- a/storage/innobase/gis/gis0rtree.cc
+++ b/storage/innobase/gis/gis0rtree.cc
@@ -652,8 +652,7 @@ rtr_adjust_upper_level(
new_prdt.op = 0;
lock_prdt_update_parent(block, new_block, &prdt, &new_prdt,
- index->table->space_id,
- page_cursor->block->page.id().page_no());
+ page_cursor->block->page.id());
mem_heap_free(heap);
@@ -881,8 +880,6 @@ rtr_page_split_and_insert(
buf_block_t* block;
page_t* page;
page_t* new_page;
- ulint page_no;
- ulint hint_page_no;
buf_block_t* new_block;
page_zip_des_t* page_zip;
page_zip_des_t* new_page_zip;
@@ -931,7 +928,7 @@ func_start:
ut_ad(mtr->memo_contains_flagged(block, MTR_MEMO_PAGE_X_FIX));
ut_ad(page_get_n_recs(page) >= 1);
- page_no = block->page.id().page_no();
+ const page_id_t page_id(block->page.id());
if (!page_has_prev(page) && !page_is_leaf(page)) {
first_rec = page_rec_get_next(
@@ -969,10 +966,9 @@ func_start:
static_cast<uchar*>(first_rec));
/* Allocate a new page to the index */
- hint_page_no = page_no + 1;
const uint16_t page_level = btr_page_get_level(page);
- new_block = btr_page_alloc(cursor->index, hint_page_no, FSP_UP,
- page_level, mtr, mtr);
+ new_block = btr_page_alloc(cursor->index, page_id.page_no() + 1,
+ FSP_UP, page_level, mtr, mtr);
if (!new_block) {
return NULL;
}
@@ -1155,8 +1151,7 @@ after_insert:
/* Check any predicate locks need to be moved/copied to the
new page */
- lock_prdt_update_split(new_block, &prdt, &new_prdt,
- cursor->index->table->space_id, page_no);
+ lock_prdt_update_split(new_block, &prdt, &new_prdt, page_id);
/* Adjust the upper level. */
rtr_adjust_upper_level(cursor, flags, block, new_block,
diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc
index dab15188bd4..21783a94e9c 100644
--- a/storage/innobase/gis/gis0sea.cc
+++ b/storage/innobase/gis/gis0sea.cc
@@ -298,8 +298,9 @@ rtr_pcur_getnext_from_path(
&& mode != PAGE_CUR_RTREE_LOCATE) {
ut_ad(rtr_info->thr);
lock_place_prdt_page_lock(
- index->table->space_id,
- next_page_no, index,
+ page_id_t(block->page.id().space(),
+ next_page_no),
+ index,
rtr_info->thr);
}
new_split = true;
@@ -1689,7 +1690,6 @@ rtr_cur_search_with_match(
const rec_t* best_rec;
const rec_t* last_match_rec = NULL;
bool match_init = false;
- ulint space = block->page.id().space();
page_cur_mode_t orig_mode = mode;
const rec_t* first_rec = NULL;
@@ -1870,7 +1870,11 @@ rtr_cur_search_with_match(
/* Lock the page, preventing it
from being shrunk */
lock_place_prdt_page_lock(
- space, page_no, index,
+ page_id_t(block->page
+ .id()
+ .space(),
+ page_no),
+ index,
rtr_info->thr);
}
} else {
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index 4cff424179c..a5713e32d86 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -699,10 +699,10 @@ fill_innodb_locks_from_cache(
OK(field_store_string(fields[IDX_LOCK_INDEX],
row->lock_index));
OK(fields[IDX_LOCK_SPACE]->store(
- row->lock_space, true));
+ row->lock_page.space(), true));
fields[IDX_LOCK_SPACE]->set_notnull();
OK(fields[IDX_LOCK_PAGE]->store(
- row->lock_page, true));
+ row->lock_page.page_no(), true));
fields[IDX_LOCK_PAGE]->set_notnull();
OK(fields[IDX_LOCK_REC]->store(
row->lock_rec, true));
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index a3ed5b104c6..ca13e2e33af 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -3329,18 +3329,22 @@ fail_exit:
and done mtr_commit(&mtr) to release the latch. */
ibuf_mtr_start(&bitmap_mtr);
- index->set_modified(bitmap_mtr);
bitmap_page = ibuf_bitmap_get_map_page(page_id, zip_size, &bitmap_mtr);
/* We check if the index page is suitable for buffered entries */
- if (buf_pool.page_hash_contains(page_id)
- || lock_rec_expl_exist_on_page(page_id.space(),
- page_id.page_no())) {
-
+ if (buf_pool.page_hash_contains(page_id)) {
+commit_exit:
ibuf_mtr_commit(&bitmap_mtr);
goto fail_exit;
+ } else {
+ lock_mutex_enter();
+ const auto lock_exists = lock_sys.get_first(page_id);
+ lock_mutex_exit();
+ if (lock_exists) {
+ goto commit_exit;
+ }
}
if (op == IBUF_OP_INSERT) {
@@ -3378,8 +3382,7 @@ fail_exit:
dfield_t* field;
if (counter == ULINT_UNDEFINED) {
- ibuf_mtr_commit(&bitmap_mtr);
- goto fail_exit;
+ goto commit_exit;
}
field = dtuple_get_nth_field(
@@ -3391,6 +3394,7 @@ fail_exit:
/* Set the bitmap bit denoting that the insert buffer contains
buffered entries for this index page, if the bit is not set yet */
+ index->set_modified(bitmap_mtr);
ibuf_bitmap_page_set_bits<IBUF_BITMAP_BUFFERED>(
bitmap_page, page_id, physical_size, true, &bitmap_mtr);
ibuf_mtr_commit(&bitmap_mtr);
diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h
index ab697a730d2..dd25c52101f 100644
--- a/storage/innobase/include/lock0lock.h
+++ b/storage/innobase/include/lock0lock.h
@@ -252,15 +252,6 @@ lock_rec_restore_from_page_infimum(
state; lock bits are reset on
the infimum */
/*********************************************************************//**
-Determines if there are explicit record locks on a page.
-@return an explicit record lock on the page, or NULL if there are none */
-lock_t*
-lock_rec_expl_exist_on_page(
-/*========================*/
- ulint space, /*!< in: space id */
- ulint page_no)/*!< in: page number */
- MY_ATTRIBUTE((warn_unused_result));
-/*********************************************************************//**
Checks if locks of other transactions prevent an immediate insert of
a record. If they do, first tests if the query thread should anyway
be suspended for some reason; if not, then puts the transaction and
@@ -487,28 +478,6 @@ lock_rec_unlock(
and release possible other transactions waiting because of these locks. */
void lock_release(trx_t* trx);
-/*********************************************************************//**
-Calculates the fold value of a page file address: used in inserting or
-searching for a lock in the hash table.
-@return folded value */
-UNIV_INLINE
-ulint
-lock_rec_fold(
-/*==========*/
- ulint space, /*!< in: space */
- ulint page_no)/*!< in: page number */
- MY_ATTRIBUTE((const));
-/*********************************************************************//**
-Calculates the hash value of a page file address: used in inserting or
-searching for a lock in the hash table.
-@return hashed value */
-UNIV_INLINE
-unsigned
-lock_rec_hash(
-/*==========*/
- ulint space, /*!< in: space */
- ulint page_no);/*!< in: page number */
-
/*************************************************************//**
Get the lock hash table */
UNIV_INLINE
@@ -819,6 +788,46 @@ public:
/** Closes the lock system at database shutdown. */
void close();
+
+ /** @return the hash value for a page address */
+ ulint hash(const page_id_t id) const
+ { ut_ad(mutex_own(&mutex)); return rec_hash.calc_hash(id.fold()); }
+
+ /** Get the first lock on a page.
+ @param lock_hash hash table to look at
+ @param id page number
+ @return first lock
+ @retval nullptr if none exists */
+ lock_t *get_first(const hash_table_t &lock_hash, const page_id_t id) const
+ {
+ ut_ad(&lock_hash == &rec_hash || &lock_hash == &prdt_hash ||
+ &lock_hash == &prdt_page_hash);
+ for (lock_t *lock= static_cast<lock_t*>
+ (HASH_GET_FIRST(&lock_hash, hash(id)));
+ lock; lock= static_cast<lock_t*>(HASH_GET_NEXT(hash, lock)))
+ if (lock->un_member.rec_lock.page_id == id)
+ return lock;
+ return nullptr;
+ }
+
+ /** Get the first record lock on a page.
+ @param id page number
+ @return first lock
+ @retval nullptr if none exists */
+ lock_t *get_first(const page_id_t id) const
+ { return get_first(rec_hash, id); }
+ /** Get the first predicate lock on a SPATIAL INDEX page.
+ @param id page number
+ @return first lock
+ @retval nullptr if none exists */
+ lock_t *get_first_prdt(const page_id_t id) const
+ { return get_first(prdt_hash, id); }
+ /** Get the first predicate lock on a SPATIAL INDEX page.
+ @param id page number
+ @return first lock
+ @retval nullptr if none exists */
+ lock_t *get_first_prdt_page(const page_id_t id) const
+ { return get_first(prdt_page_hash, id); }
};
/*********************************************************************//**
@@ -858,8 +867,7 @@ lock_rec_discard(
without checking for deadlocks or conflicts.
@param[in] type_mode lock mode and wait flag; type will be replaced
with LOCK_REC
-@param[in] space tablespace id
-@param[in] page_no index page number
+@param[in] page_id index page number
@param[in] page R-tree index page, or NULL
@param[in] heap_no record heap number in the index page
@param[in] index the index tree
@@ -873,8 +881,7 @@ lock_rec_create_low(
que_thr_t* thr, /*!< thread owning trx */
#endif
unsigned type_mode,
- ulint space,
- ulint page_no,
+ const page_id_t page_id,
const page_t* page,
ulint heap_no,
dict_index_t* index,
diff --git a/storage/innobase/include/lock0lock.ic b/storage/innobase/include/lock0lock.ic
index 674821a4931..2d5b6ff37f1 100644
--- a/storage/innobase/include/lock0lock.ic
+++ b/storage/innobase/include/lock0lock.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -29,34 +29,6 @@ Created 5/7/1996 Heikki Tuuri
#include "page0page.h"
/*********************************************************************//**
-Calculates the fold value of a page file address: used in inserting or
-searching for a lock in the hash table.
-@return folded value */
-UNIV_INLINE
-ulint
-lock_rec_fold(
-/*==========*/
- ulint space, /*!< in: space */
- ulint page_no)/*!< in: page number */
-{
- return page_id_t(space, page_no).fold();
-}
-
-/*********************************************************************//**
-Calculates the hash value of a page file address: used in inserting or
-searching for a lock in the hash table.
-@return hashed value */
-UNIV_INLINE
-unsigned
-lock_rec_hash(
-/*==========*/
- ulint space, /*!< in: space */
- ulint page_no)/*!< in: page number */
-{
- return unsigned(lock_sys.rec_hash.calc_hash(lock_rec_fold(space, page_no)));
-}
-
-/*********************************************************************//**
Gets the heap_no of the smallest user record on a page.
@return heap_no of smallest user record, or PAGE_HEAP_NO_SUPREMUM */
UNIV_INLINE
@@ -122,12 +94,10 @@ lock_rec_create(
trx mutex */
{
btr_assert_not_corrupted(block, index);
- const page_id_t id(block->page.id());
return lock_rec_create_low(
#ifdef WITH_WSREP
c_lock, thr,
#endif
- type_mode, id.space(), id.page_no(),
- block->frame, heap_no,
+ type_mode, block->page.id(), block->frame, heap_no,
index, trx, caller_owns_trx_mutex);
}
diff --git a/storage/innobase/include/lock0prdt.h b/storage/innobase/include/lock0prdt.h
index 59cf0130625..43d68996691 100644
--- a/storage/innobase/include/lock0prdt.h
+++ b/storage/innobase/include/lock0prdt.h
@@ -58,9 +58,7 @@ Acquire a "Page" lock on a block
@return DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK */
dberr_t
lock_place_prdt_page_lock(
-/*======================*/
- ulint space, /*!< in: space for the page to lock */
- ulint pageno, /*!< in: page number */
+ const page_id_t page_id, /*!< in: page identifier */
dict_index_t* index, /*!< in: secondary index */
que_thr_t* thr); /*!< in: query thread */
@@ -108,8 +106,7 @@ lock_prdt_update_split(
buf_block_t* new_block, /*!< in/out: the new half page */
lock_prdt_t* prdt, /*!< in: MBR on the old page */
lock_prdt_t* new_prdt, /*!< in: MBR on the new page */
- ulint space, /*!< in: space id */
- ulint page_no); /*!< in: page number */
+ const page_id_t page_id); /*!< in: page number */
/**************************************************************//**
Ajust locks from an ancester page of Rtree on the appropriate level . */
@@ -120,8 +117,7 @@ lock_prdt_update_parent(
buf_block_t* right_block, /*!< in/out: the new half page */
lock_prdt_t* left_prdt, /*!< in: MBR on the old page */
lock_prdt_t* right_prdt, /*!< in: MBR on the new page */
- ulint space, /*!< in: space id */
- ulint page_no); /*!< in: page number */
+ const page_id_t page_id); /*!< in: parent page */
/*********************************************************************//**
Checks if locks of other transactions prevent an immediate insert of
@@ -190,17 +186,11 @@ lock_prdt_rec_move(
const buf_block_t* donator); /*!< in: buffer block containing
the donating record */
-/** Check whether there are R-tree Page lock on a buffer page
+/** Check whether there are R-tree Page lock on a page
@param[in] trx trx to test the lock
-@param[in] space space id for the page
-@param[in] page_no page number
-@return true if there is none */
-bool
-lock_test_prdt_page_lock(
-/*=====================*/
- const trx_t* trx,
- ulint space,
- ulint page_no);
+@param[in] page_id page identifier
+@return true if there is none */
+bool lock_test_prdt_page_lock(const trx_t *trx, const page_id_t page_id);
/** Removes predicate lock objects set on an index page which is discarded.
@param[in] block page to be discarded
diff --git a/storage/innobase/include/lock0priv.h b/storage/innobase/include/lock0priv.h
index 2743becea8f..1b2f9d0f0d3 100644
--- a/storage/innobase/include/lock0priv.h
+++ b/storage/innobase/include/lock0priv.h
@@ -539,29 +539,6 @@ lock_t*
lock_rec_get_next_on_page(
/*======================*/
lock_t* lock); /*!< in: a record lock */
-/*********************************************************************//**
-Gets the first record lock on a page, where the page is identified by its
-file address.
-@return first lock, NULL if none exists */
-UNIV_INLINE
-lock_t*
-lock_rec_get_first_on_page_addr(
-/*============================*/
- hash_table_t* lock_hash, /* Lock hash table */
- ulint space, /*!< in: space */
- ulint page_no); /*!< in: page number */
-
-/*********************************************************************//**
-Gets the first record lock on a page, where the page is identified by a
-pointer to it.
-@return first lock, NULL if none exists */
-UNIV_INLINE
-lock_t*
-lock_rec_get_first_on_page(
-/*=======================*/
- hash_table_t* lock_hash, /*!< in: lock hash table */
- const buf_block_t* block); /*!< in: buffer block */
-
/*********************************************************************//**
Gets the next explicit lock request on a record.
@@ -633,20 +610,6 @@ lock_get_wait(
const lock_t* lock); /*!< in: lock */
/*********************************************************************//**
-Looks for a suitable type record lock struct by the same trx on the same page.
-This can be used to save space when a new record lock should be set on a page:
-no new struct is needed, if a suitable old is found.
-@return lock or NULL */
-UNIV_INLINE
-lock_t*
-lock_rec_find_similar_on_page(
-/*==========================*/
- ulint type_mode, /*!< in: lock type_mode field */
- ulint heap_no, /*!< in: heap number of the record */
- lock_t* lock, /*!< in: lock_rec_get_first_on_page() */
- const trx_t* trx); /*!< in: transaction */
-
-/*********************************************************************//**
Checks if a transaction has the specified table lock, or stronger. This
function should only be called by the thread that owns the transaction.
@return lock or NULL */
diff --git a/storage/innobase/include/lock0priv.ic b/storage/innobase/include/lock0priv.ic
index 8fa7338e02b..e16949a4917 100644
--- a/storage/innobase/include/lock0priv.ic
+++ b/storage/innobase/include/lock0priv.ic
@@ -122,70 +122,6 @@ lock_rec_get_next_on_page(
}
/*********************************************************************//**
-Gets the first record lock on a page, where the page is identified by its
-file address.
-@return first lock, NULL if none exists */
-UNIV_INLINE
-lock_t*
-lock_rec_get_first_on_page_addr(
-/*============================*/
- hash_table_t* lock_hash, /* Lock hash table */
- ulint space, /*!< in: space */
- ulint page_no) /*!< in: page number */
-{
- ut_ad(lock_mutex_own());
-
- for (lock_t* lock = static_cast<lock_t*>(
- HASH_GET_FIRST(lock_hash,
- lock_rec_hash(space, page_no)));
- lock != NULL;
- lock = static_cast<lock_t*>(HASH_GET_NEXT(hash, lock))) {
-
- if (lock->un_member.rec_lock.space == space
- && lock->un_member.rec_lock.page_no == page_no) {
-
- return(lock);
- }
- }
-
- return(NULL);
-}
-
-/*********************************************************************//**
-Gets the first record lock on a page, where the page is identified by a
-pointer to it.
-@return first lock, NULL if none exists */
-UNIV_INLINE
-lock_t*
-lock_rec_get_first_on_page(
-/*=======================*/
- hash_table_t* lock_hash, /*!< in: lock hash table */
- const buf_block_t* block) /*!< in: buffer block */
-{
- ut_ad(lock_mutex_own());
-
- const page_id_t page_id(block->page.id());
-
- ulint space = page_id.space();
- ulint page_no = page_id.page_no();
-
- for (lock_t* lock = static_cast<lock_t*>(
- HASH_GET_FIRST(lock_hash,
- lock_rec_hash(space, page_no)));
- lock != NULL;
- lock = static_cast<lock_t*>(HASH_GET_NEXT(hash, lock))) {
-
- if (lock->un_member.rec_lock.space == space
- && lock->un_member.rec_lock.page_no == page_no) {
-
- return(lock);
- }
- }
-
- return(NULL);
-}
-
-/*********************************************************************//**
Gets the next explicit lock request on a record.
@return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */
UNIV_INLINE
@@ -229,16 +165,11 @@ lock_rec_get_first(
const buf_block_t* block, /*!< in: block containing the record */
ulint heap_no)/*!< in: heap number of the record */
{
- ut_ad(lock_mutex_own());
-
- for (lock_t* lock = lock_rec_get_first_on_page(hash, block); lock;
- lock = lock_rec_get_next_on_page(lock)) {
- if (lock_rec_get_nth_bit(lock, heap_no)) {
- return(lock);
- }
- }
-
- return(NULL);
+ for (lock_t *lock= lock_sys.get_first(*hash, block->page.id());
+ lock; lock= lock_rec_get_next_on_page(lock))
+ if (lock_rec_get_nth_bit(lock, heap_no))
+ return lock;
+ return nullptr;
}
/*********************************************************************//**
@@ -275,23 +206,15 @@ lock_rec_get_next_on_page_const(
/*============================*/
const lock_t* lock) /*!< in: a record lock */
{
- ut_ad(lock_mutex_own());
- ut_ad(lock_get_type_low(lock) == LOCK_REC);
-
- ulint space = lock->un_member.rec_lock.space;
- ulint page_no = lock->un_member.rec_lock.page_no;
-
- while ((lock = static_cast<const lock_t*>(HASH_GET_NEXT(hash, lock)))
- != NULL) {
-
- if (lock->un_member.rec_lock.space == space
- && lock->un_member.rec_lock.page_no == page_no) {
+ ut_ad(lock_mutex_own());
+ ut_ad(lock_get_type_low(lock) == LOCK_REC);
- return(lock);
- }
- }
+ const page_id_t page_id(lock->un_member.rec_lock.page_id);
- return(NULL);
+ while (!!(lock= static_cast<const lock_t*>(HASH_GET_NEXT(hash, lock))))
+ if (lock->un_member.rec_lock.page_id == page_id)
+ break;
+ return lock;
}
/*********************************************************************//**
@@ -355,37 +278,6 @@ lock_get_wait(
}
/*********************************************************************//**
-Looks for a suitable type record lock struct by the same trx on the same page.
-This can be used to save space when a new record lock should be set on a page:
-no new struct is needed, if a suitable old is found.
-@return lock or NULL */
-UNIV_INLINE
-lock_t*
-lock_rec_find_similar_on_page(
-/*==========================*/
- ulint type_mode, /*!< in: lock type_mode field */
- ulint heap_no, /*!< in: heap number of the record */
- lock_t* lock, /*!< in: lock_rec_get_first_on_page() */
- const trx_t* trx) /*!< in: transaction */
-{
- ut_ad(lock_mutex_own());
-
- for (/* No op */;
- lock != NULL;
- lock = lock_rec_get_next_on_page(lock)) {
-
- if (lock->trx == trx
- && lock->type_mode == type_mode
- && lock_rec_get_n_bits(lock) > heap_no) {
-
- return(lock);
- }
- }
-
- return(NULL);
-}
-
-/*********************************************************************//**
Checks if a transaction has the specified table lock, or stronger. This
function should only be called by the thread that owns the transaction.
@return lock or NULL */
diff --git a/storage/innobase/include/lock0types.h b/storage/innobase/include/lock0types.h
index cb04afdf9db..23307375426 100644
--- a/storage/innobase/include/lock0types.h
+++ b/storage/innobase/include/lock0types.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 2019, MariaDB Corporation.
+Copyright (c) 2018, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -25,6 +25,7 @@ Created 5/7/1996 Heikki Tuuri
*******************************************************/
#include "dict0types.h"
+#include "buf0types.h"
#include "ut0lst.h"
#ifndef lock0types_h
@@ -89,8 +90,8 @@ struct lock_table_t {
/** Record lock for a page */
struct lock_rec_t {
- ib_uint32_t space; /*!< space id */
- ib_uint32_t page_no; /*!< page number */
+ /** page identifier */
+ page_id_t page_id;
ib_uint32_t n_bits; /*!< number of bits in the lock
bitmap; NOTE: the lock bitmap is
placed immediately after the
@@ -105,12 +106,12 @@ struct lock_rec_t {
/** Print the record lock into the given output stream
@param[in,out] out the output stream
@return the given output stream. */
-inline
-std::ostream& lock_rec_t::print(std::ostream& out) const
+inline std::ostream &lock_rec_t::print(std::ostream &out) const
{
- out << "[lock_rec_t: space=" << space << ", page_no=" << page_no
- << ", n_bits=" << n_bits << "]";
- return(out);
+ out << "[lock_rec_t: space=" << page_id.space()
+ << ", page_no=" << page_id.page_no()
+ << ", n_bits=" << n_bits << "]";
+ return out;
}
inline
diff --git a/storage/innobase/include/trx0i_s.h b/storage/innobase/include/trx0i_s.h
index 892ee3cfe18..98b84fe0985 100644
--- a/storage/innobase/include/trx0i_s.h
+++ b/storage/innobase/include/trx0i_s.h
@@ -31,6 +31,7 @@ Created July 17, 2007 Vasil Dimov
#include "trx0types.h"
#include "dict0types.h"
+#include "buf0types.h"
/** The maximum amount of memory that can be consumed by innodb_trx,
innodb_locks and innodb_lock_waits information schema tables. */
@@ -90,10 +91,8 @@ struct i_s_locks_row_t {
lock_get_table_name() */
/** index name of a record lock; NULL for table locks */
const char* lock_index;
- /** tablespace identifier of the record; 0 if !lock_index */
- uint32_t lock_space;
- /** page number of the record; 0 if !lock_index */
- uint32_t lock_page;
+ /** page identifier of the record; (0,0) if !lock_index */
+ page_id_t lock_page;
/** heap number of the record; 0 if !lock_index */
uint16_t lock_rec;
/** lock mode corresponding to lock_mode_values_typelib */
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index e5718a9e75c..88ed047ed77 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -477,13 +477,9 @@ void lock_sys_t::create(ulint n_cells)
/** Calculates the fold value of a lock: used in migrating the hash table.
@param[in] lock record lock object
@return folded value */
-static
-ulint
-lock_rec_lock_fold(
- const lock_t* lock)
+static ulint lock_rec_lock_fold(const lock_t *lock)
{
- return(lock_rec_fold(lock->un_member.rec_lock.space,
- lock->un_member.rec_lock.page_no));
+ return lock->un_member.rec_lock.page_id.fold();
}
@@ -847,26 +843,6 @@ lock_rec_find_set_bit(
}
/*********************************************************************//**
-Determines if there are explicit record locks on a page.
-@return an explicit record lock on the page, or NULL if there are none */
-lock_t*
-lock_rec_expl_exist_on_page(
-/*========================*/
- ulint space, /*!< in: space id */
- ulint page_no)/*!< in: page number */
-{
- lock_t* lock;
-
- lock_mutex_enter();
- /* Only used in ibuf pages, so rec_hash is good enough */
- lock = lock_rec_get_first_on_page_addr(&lock_sys.rec_hash,
- space, page_no);
- lock_mutex_exit();
-
- return(lock);
-}
-
-/*********************************************************************//**
Resets the record lock bitmap to zero. NOTE: does not touch the wait_lock
pointer in the transaction! This function is used in lock object creation
and resetting. */
@@ -887,7 +863,7 @@ lock_rec_bitmap_reset(
ut_ad((lock_rec_get_n_bits(lock) % 8) == 0);
- memset(&lock[1], 0, n_bytes);
+ memset(reinterpret_cast<void*>(&lock[1]), 0, n_bytes);
}
/*********************************************************************//**
@@ -919,35 +895,21 @@ lock_rec_get_prev(
ulint heap_no)/*!< in: heap number of the record */
{
lock_t* lock;
- ulint space;
- ulint page_no;
lock_t* found_lock = NULL;
- hash_table_t* hash;
ut_ad(lock_mutex_own());
ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
- space = in_lock->un_member.rec_lock.space;
- page_no = in_lock->un_member.rec_lock.page_no;
-
- hash = lock_hash_get(in_lock->type_mode);
-
- for (lock = lock_rec_get_first_on_page_addr(hash, space, page_no);
- /* No op */;
+ for (lock = lock_sys.get_first(*lock_hash_get(in_lock->type_mode),
+ in_lock->un_member.rec_lock.page_id);
+ lock != in_lock;
lock = lock_rec_get_next_on_page(lock)) {
-
- ut_ad(lock);
-
- if (lock == in_lock) {
-
- return(found_lock);
- }
-
if (lock_rec_get_nth_bit(lock, heap_no)) {
-
found_lock = lock;
}
}
+
+ return found_lock;
}
/*============= FUNCTIONS FOR ANALYZING RECORD LOCK QUEUE ================*/
@@ -1285,8 +1247,7 @@ wsrep_print_wait_locks(
without checking for deadlocks or conflicts.
@param[in] type_mode lock mode and wait flag; type will be replaced
with LOCK_REC
-@param[in] space tablespace id
-@param[in] page_no index page number
+@param[in] page_id index page number
@param[in] page R-tree index page, or NULL
@param[in] heap_no record heap number in the index page
@param[in] index the index tree
@@ -1300,8 +1261,7 @@ lock_rec_create_low(
que_thr_t* thr, /*!< thread owning trx */
#endif
unsigned type_mode,
- ulint space,
- ulint page_no,
+ const page_id_t page_id,
const page_t* page,
ulint heap_no,
dict_index_t* index,
@@ -1370,8 +1330,7 @@ lock_rec_create_low(
lock->trx = trx;
lock->type_mode = (type_mode & unsigned(~LOCK_TYPE_MASK)) | LOCK_REC;
lock->index = index;
- lock->un_member.rec_lock.space = uint32_t(space);
- lock->un_member.rec_lock.page_no = uint32_t(page_no);
+ lock->un_member.rec_lock.page_id = page_id;
if (UNIV_LIKELY(!(type_mode & (LOCK_PREDICATE | LOCK_PRDT_PAGE)))) {
lock->un_member.rec_lock.n_bits = uint32_t(n_bytes * 8);
@@ -1457,10 +1416,10 @@ lock_rec_create_low(
== INNODB_LOCK_SCHEDULE_ALGORITHM_VATS
&& !thd_is_replication_slave_thread(trx->mysql_thd)) {
HASH_PREPEND(lock_t, hash, &lock_sys.rec_hash,
- lock_rec_fold(space, page_no), lock);
+ page_id.fold(), lock);
} else {
HASH_INSERT(lock_t, hash, lock_hash_get(type_mode),
- lock_rec_fold(space, page_no), lock);
+ page_id.fold(), lock);
}
if (!holds_trx_mutex) {
@@ -1514,19 +1473,14 @@ static
dberr_t
lock_rec_insert_by_trx_age(
lock_t *in_lock) /*!< in: lock to be insert */{
- ulint space;
- ulint page_no;
- ulint rec_fold;
lock_t* node;
lock_t* next;
hash_table_t* hash;
hash_cell_t* cell;
- space = in_lock->un_member.rec_lock.space;
- page_no = in_lock->un_member.rec_lock.page_no;
- rec_fold = lock_rec_fold(space, page_no);
+ const page_id_t page_id(in_lock->un_member.rec_lock.page_id);
hash = lock_hash_get(in_lock->type_mode);
- cell = &hash->array[hash->calc_hash(rec_fold)];
+ cell = &hash->array[hash->calc_hash(page_id.fold())];
node = (lock_t *) cell->node;
// If in_lock is not a wait lock, we insert it to the head of the list.
@@ -1568,9 +1522,6 @@ bool
lock_queue_validate(
const lock_t *in_lock) /*!< in: lock whose hash list is to be validated */
{
- ulint space;
- ulint page_no;
- ulint rec_fold;
hash_table_t* hash;
hash_cell_t* cell;
lock_t* next;
@@ -1580,11 +1531,9 @@ lock_queue_validate(
return true;
}
- space = in_lock->un_member.rec_lock.space;
- page_no = in_lock->un_member.rec_lock.page_no;
- rec_fold = lock_rec_fold(space, page_no);
+ const page_id_t page_id(in_lock->un_member.rec_lock.page_id);
hash = lock_hash_get(in_lock->type_mode);
- cell = &hash->array[hash->calc_hash(rec_fold)];
+ cell = &hash->array[hash->calc_hash(page_id.fold())];
next = (lock_t *) cell->node;
while (next != NULL) {
// If this is a granted lock, check that there's no wait lock before it.
@@ -1742,6 +1691,36 @@ lock_rec_enqueue_waiting(
}
/*********************************************************************//**
+Looks for a suitable type record lock struct by the same trx on the same page.
+This can be used to save space when a new record lock should be set on a page:
+no new struct is needed, if a suitable old is found.
+@return lock or NULL */
+static inline
+lock_t*
+lock_rec_find_similar_on_page(
+ ulint type_mode, /*!< in: lock type_mode field */
+ ulint heap_no, /*!< in: heap number of the record */
+ lock_t* lock, /*!< in: lock_sys.get_first() */
+ const trx_t* trx) /*!< in: transaction */
+{
+ ut_ad(lock_mutex_own());
+
+ for (/* No op */;
+ lock != NULL;
+ lock = lock_rec_get_next_on_page(lock)) {
+
+ if (lock->trx == trx
+ && lock->type_mode == type_mode
+ && lock_rec_get_n_bits(lock) > heap_no) {
+
+ return(lock);
+ }
+ }
+
+ return(NULL);
+}
+
+/*********************************************************************//**
Adds a record lock request in the record queue. The request is normally
added as the last in the queue, but if there are no waiting lock requests
on the record, and the request to be added is not a waiting request, we
@@ -1828,11 +1807,11 @@ lock_rec_add_to_queue(
lock_t* lock;
lock_t* first_lock;
- hash_table_t* hash = lock_hash_get(type_mode);
/* Look for a waiting lock request on the same record or on a gap */
- for (first_lock = lock = lock_rec_get_first_on_page(hash, block);
+ for (first_lock = lock = lock_sys.get_first(*lock_hash_get(type_mode),
+ block->page.id());
lock != NULL;
lock = lock_rec_get_next_on_page(lock)) {
@@ -1911,7 +1890,7 @@ lock_rec_lock(
if (lock_table_has(trx, index->table,
static_cast<lock_mode>(LOCK_MODE_MASK & mode)));
- else if (lock_t *lock= lock_rec_get_first_on_page(&lock_sys.rec_hash, block))
+ else if (lock_t *lock= lock_sys.get_first(block->page.id()))
{
trx_mutex_enter(trx);
if (lock_rec_get_next_on_page(lock) ||
@@ -1992,28 +1971,22 @@ lock_rec_has_to_wait_in_queue(
const lock_t* wait_lock) /*!< in: waiting record lock */
{
const lock_t* lock;
- ulint space;
- ulint page_no;
ulint heap_no;
ulint bit_mask;
ulint bit_offset;
- hash_table_t* hash;
ut_ad(wait_lock);
ut_ad(lock_mutex_own());
ut_ad(lock_get_wait(wait_lock));
ut_ad(lock_get_type_low(wait_lock) == LOCK_REC);
- space = wait_lock->un_member.rec_lock.space;
- page_no = wait_lock->un_member.rec_lock.page_no;
heap_no = lock_rec_find_set_bit(wait_lock);
bit_offset = heap_no / 8;
bit_mask = static_cast<ulint>(1) << (heap_no % 8);
- hash = lock_hash_get(wait_lock->type_mode);
-
- for (lock = lock_rec_get_first_on_page_addr(hash, space, page_no);
+ for (lock = lock_sys.get_first(*lock_hash_get(wait_lock->type_mode),
+ wait_lock->un_member.rec_lock.page_id);
#ifdef WITH_WSREP
lock &&
#endif
@@ -2132,9 +2105,7 @@ lock_rec_cancel(
trx_mutex_exit(lock->trx);
}
-static
-void
-lock_grant_and_move_on_page(ulint rec_fold, ulint space, ulint page_no)
+static void lock_grant_and_move_on_page(ulint rec_fold, const page_id_t id)
{
lock_t* lock;
lock_t* previous = static_cast<lock_t*>(
@@ -2143,15 +2114,13 @@ lock_grant_and_move_on_page(ulint rec_fold, ulint space, ulint page_no)
if (previous == NULL) {
return;
}
- if (previous->un_member.rec_lock.space == space &&
- previous->un_member.rec_lock.page_no == page_no) {
+ if (previous->un_member.rec_lock.page_id == id) {
lock = previous;
}
else {
while (previous->hash &&
- (previous->hash->un_member.rec_lock.space != space ||
- previous->hash->un_member.rec_lock.page_no != page_no)) {
- previous = previous->hash;
+ (previous->hash->un_member.rec_lock.page_id != id)) {
+ previous = previous->hash;
}
lock = previous->hash;
}
@@ -2162,8 +2131,7 @@ lock_grant_and_move_on_page(ulint rec_fold, ulint space, ulint page_no)
while (lock) {
/* If the lock is a wait lock on this page, and it does not need to wait. */
if (lock_get_wait(lock)
- && lock->un_member.rec_lock.space == space
- && lock->un_member.rec_lock.page_no == page_no
+ && lock->un_member.rec_lock.page_id == id
&& !lock_rec_has_to_wait_in_queue(lock)) {
lock_grant(lock);
@@ -2190,22 +2158,19 @@ to a lock. NOTE: all record locks contained in in_lock are removed.
@param[in,out] in_lock record lock */
static void lock_rec_dequeue_from_page(lock_t* in_lock)
{
- ulint space;
- ulint page_no;
hash_table_t* lock_hash;
ut_ad(lock_mutex_own());
ut_ad(lock_get_type_low(in_lock) == LOCK_REC);
/* We may or may not be holding in_lock->trx->mutex here. */
- space = in_lock->un_member.rec_lock.space;
- page_no = in_lock->un_member.rec_lock.page_no;
+ const page_id_t page_id(in_lock->un_member.rec_lock.page_id);
in_lock->index->table->n_rec_locks--;
lock_hash = lock_hash_get(in_lock->type_mode);
- ulint rec_fold = lock_rec_fold(space, page_no);
+ const ulint rec_fold = page_id.fold();
HASH_DELETE(lock_t, hash, lock_hash, rec_fold, in_lock);
UT_LIST_REMOVE(in_lock->trx->lock.trx_locks, in_lock);
@@ -2221,8 +2186,7 @@ static void lock_rec_dequeue_from_page(lock_t* in_lock)
grant locks if there are no conflicting locks ahead. Stop at
the first X lock that is waiting or has been granted. */
- for (lock_t* lock = lock_rec_get_first_on_page_addr(
- lock_hash, space, page_no);
+ for (lock_t* lock = lock_sys.get_first(*lock_hash, page_id);
lock != NULL;
lock = lock_rec_get_next_on_page(lock)) {
@@ -2234,7 +2198,7 @@ static void lock_rec_dequeue_from_page(lock_t* in_lock)
}
}
} else {
- lock_grant_and_move_on_page(rec_fold, space, page_no);
+ lock_grant_and_move_on_page(rec_fold, page_id);
}
}
@@ -2247,8 +2211,6 @@ lock_rec_discard(
record locks which are contained
in this lock object are removed */
{
- ulint space;
- ulint page_no;
trx_lock_t* trx_lock;
ut_ad(lock_mutex_own());
@@ -2256,13 +2218,10 @@ lock_rec_discard(
trx_lock = &in_lock->trx->lock;
- space = in_lock->un_member.rec_lock.space;
- page_no = in_lock->un_member.rec_lock.page_no;
-
in_lock->index->table->n_rec_locks--;
HASH_DELETE(lock_t, hash, lock_hash_get(in_lock->type_mode),
- lock_rec_fold(space, page_no), in_lock);
+ in_lock->un_member.rec_lock.page_id.fold(), in_lock);
UT_LIST_REMOVE(trx_lock->trx_locks, in_lock);
@@ -2274,29 +2233,19 @@ lock_rec_discard(
Removes record lock objects set on an index page which is discarded. This
function does not move locks, or check for waiting locks, therefore the
lock bitmaps must already be reset when this function is called. */
-static
-void
-lock_rec_free_all_from_discard_page_low(
-/*====================================*/
- ulint space,
- ulint page_no,
- hash_table_t* lock_hash)
+static void lock_rec_free_all_from_discard_page_low(const page_id_t id,
+ hash_table_t *lock_hash)
{
- lock_t* lock;
- lock_t* next_lock;
-
- lock = lock_rec_get_first_on_page_addr(lock_hash, space, page_no);
+ lock_t *lock= lock_sys.get_first(*lock_hash, id);
- while (lock != NULL) {
- ut_ad(lock_rec_find_set_bit(lock) == ULINT_UNDEFINED);
- ut_ad(!lock_get_wait(lock));
-
- next_lock = lock_rec_get_next_on_page(lock);
-
- lock_rec_discard(lock);
-
- lock = next_lock;
- }
+ while (lock)
+ {
+ ut_ad(lock_rec_find_set_bit(lock) == ULINT_UNDEFINED);
+ ut_ad(!lock_get_wait(lock));
+ lock_t *next_lock= lock_rec_get_next_on_page(lock);
+ lock_rec_discard(lock);
+ lock= next_lock;
+ }
}
/*************************************************************//**
@@ -2308,20 +2257,10 @@ lock_rec_free_all_from_discard_page(
/*================================*/
const buf_block_t* block) /*!< in: page to be discarded */
{
- ulint space;
- ulint page_no;
-
- ut_ad(lock_mutex_own());
-
- space = block->page.id().space();
- page_no = block->page.id().page_no();
-
- lock_rec_free_all_from_discard_page_low(
- space, page_no, &lock_sys.rec_hash);
- lock_rec_free_all_from_discard_page_low(
- space, page_no, &lock_sys.prdt_hash);
- lock_rec_free_all_from_discard_page_low(
- space, page_no, &lock_sys.prdt_page_hash);
+ const page_id_t page_id(block->page.id());
+ lock_rec_free_all_from_discard_page_low(page_id, &lock_sys.rec_hash);
+ lock_rec_free_all_from_discard_page_low(page_id, &lock_sys.prdt_hash);
+ lock_rec_free_all_from_discard_page_low(page_id, &lock_sys.prdt_page_hash);
}
/*============= RECORD LOCK MOVING AND INHERITING ===================*/
@@ -2588,7 +2527,7 @@ lock_move_reorganize_page(
lock_mutex_enter();
/* FIXME: This needs to deal with predicate lock too */
- lock = lock_rec_get_first_on_page(&lock_sys.rec_hash, block);
+ lock = lock_sys.get_first(block->page.id());
if (lock == NULL) {
lock_mutex_exit();
@@ -2721,7 +2660,7 @@ lock_move_rec_list_end(
table to the end of the hash chain, and lock_rec_add_to_queue
does not reuse locks if there are waiters in the queue. */
- for (lock = lock_rec_get_first_on_page(&lock_sys.rec_hash, block);
+ for (lock = lock_sys.get_first(block->page.id());
lock;
lock = lock_rec_get_next_on_page(lock)) {
const rec_t* rec1 = rec;
@@ -2837,7 +2776,7 @@ lock_move_rec_list_start(
lock_mutex_enter();
- for (lock = lock_rec_get_first_on_page(&lock_sys.rec_hash, block);
+ for (lock = lock_sys.get_first(block->page.id());
lock;
lock = lock_rec_get_next_on_page(lock)) {
const rec_t* rec1;
@@ -2950,7 +2889,7 @@ lock_rtr_move_rec_list(
lock_mutex_enter();
- for (lock = lock_rec_get_first_on_page(&lock_sys.rec_hash, block);
+ for (lock = lock_sys.get_first(block->page.id());
lock;
lock = lock_rec_get_next_on_page(lock)) {
ulint moved = 0;
@@ -3067,10 +3006,7 @@ lock_update_merge_right(
/* there should exist no page lock on the left page,
otherwise, it will be blocked from merge */
- ut_ad(!lock_rec_get_first_on_page_addr(
- &lock_sys.prdt_page_hash,
- left_block->page.id().space(),
- left_block->page.id().page_no()));
+ ut_ad(!lock_sys.get_first_prdt_page(left_block->page.id()));
lock_rec_free_all_from_discard_page(left_block);
@@ -3189,10 +3125,7 @@ lock_update_merge_left(
/* there should exist no page lock on the right page,
otherwise, it will be blocked from merge */
- ut_ad(!lock_rec_get_first_on_page_addr(
- &lock_sys.prdt_page_hash,
- right_block->page.id().space(),
- right_block->page.id().page_no()));
+ ut_ad(!lock_sys.get_first_prdt_page(right_block->page.id()));
lock_rec_free_all_from_discard_page(right_block);
@@ -3240,13 +3173,13 @@ lock_update_discard(
const page_t* page = block->frame;
const rec_t* rec;
ulint heap_no;
+ const page_id_t page_id(block->page.id());
lock_mutex_enter();
- if (lock_rec_get_first_on_page(&lock_sys.rec_hash, block)) {
- ut_ad(!lock_rec_get_first_on_page(&lock_sys.prdt_hash, block));
- ut_ad(!lock_rec_get_first_on_page(&lock_sys.prdt_page_hash,
- block));
+ if (lock_sys.get_first(page_id)) {
+ ut_ad(!lock_sys.get_first_prdt(page_id));
+ ut_ad(!lock_sys.get_first_prdt_page(page_id));
/* Inherit all the locks on the page to the record and
reset all the locks on the page */
@@ -3280,16 +3213,13 @@ lock_update_discard(
} while (heap_no != PAGE_HEAP_NO_SUPREMUM);
}
- lock_rec_free_all_from_discard_page_low(
- block->page.id().space(), block->page.id().page_no(),
- &lock_sys.rec_hash);
+ lock_rec_free_all_from_discard_page_low(page_id,
+ &lock_sys.rec_hash);
} else {
+ lock_rec_free_all_from_discard_page_low(page_id,
+ &lock_sys.prdt_hash);
lock_rec_free_all_from_discard_page_low(
- block->page.id().space(), block->page.id().page_no(),
- &lock_sys.prdt_hash);
- lock_rec_free_all_from_discard_page_low(
- block->page.id().space(), block->page.id().page_no(),
- &lock_sys.prdt_page_hash);
+ page_id, &lock_sys.prdt_page_hash);
}
lock_mutex_exit();
@@ -4061,16 +3991,10 @@ lock_grant_and_move_on_rec(
ulint heap_no)
{
lock_t* lock;
- ulint space;
- ulint page_no;
- ulint rec_fold;
-
- space = first_lock->un_member.rec_lock.space;
- page_no = first_lock->un_member.rec_lock.page_no;
- rec_fold = lock_rec_fold(space, page_no);
-
+ const page_id_t page_id(first_lock->un_member.rec_lock.page_id);
+ const ulint rec_fold= page_id.fold();
lock_t* previous = static_cast<lock_t*>(
- lock_sys.rec_hash.array[lock_sys.rec_hash.calc_hash(rec_fold)]
+ lock_sys.rec_hash.array[lock_sys.hash(page_id)]
.node);
if (previous == NULL) {
return;
@@ -4089,8 +4013,7 @@ lock_grant_and_move_on_rec(
for (;lock != NULL;) {
/* If the lock is a wait lock on this page, and it does not need to wait. */
- if (lock->un_member.rec_lock.space == space
- && lock->un_member.rec_lock.page_no == page_no
+ if (lock->un_member.rec_lock.page_id == page_id
&& lock_rec_get_nth_bit(lock, heap_no)
&& lock_get_wait(lock)
&& !lock_rec_has_to_wait_in_queue(lock)) {
@@ -4392,19 +4315,15 @@ lock_table_print(FILE* file, const lock_t* lock)
@param[in,out] mtr mini-transaction for accessing the record */
static void lock_rec_print(FILE* file, const lock_t* lock, mtr_t& mtr)
{
- ulint space;
- ulint page_no;
-
ut_ad(lock_mutex_own());
ut_a(lock_get_type_low(lock) == LOCK_REC);
- space = lock->un_member.rec_lock.space;
- page_no = lock->un_member.rec_lock.page_no;
+ const page_id_t page_id(lock->un_member.rec_lock.page_id);
- fprintf(file, "RECORD LOCKS space id %lu page no %lu n bits %lu "
- "index %s of table ",
- (ulong) space, (ulong) page_no,
- (ulong) lock_rec_get_n_bits(lock),
+ fprintf(file, "RECORD LOCKS space id %u page no %u n bits " ULINTPF
+ " index %s of table ",
+ page_id.space(), page_id.page_no(),
+ lock_rec_get_n_bits(lock),
lock->index->name());
ut_print_name(file, lock->trx, lock->index->table->name.m_name);
fprintf(file, " trx id " TRX_ID_FMT, trx_get_id_for_print(lock->trx));
@@ -4441,8 +4360,7 @@ static void lock_rec_print(FILE* file, const lock_t* lock, mtr_t& mtr)
rec_offs_init(offsets_);
mtr.start();
- const buf_block_t* block = buf_page_try_get(page_id_t(space, page_no),
- &mtr);
+ const buf_block_t* block = buf_page_try_get(page_id, &mtr);
for (ulint i = 0; i < lock_rec_get_n_bits(lock); ++i) {
@@ -4941,13 +4859,9 @@ lock_rec_validate_page(
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
- ut_ad(!lock_mutex_own());
-
lock_mutex_enter();
loop:
- lock = lock_rec_get_first_on_page_addr(
- &lock_sys.rec_hash,
- block->page.id().space(), block->page.id().page_no());
+ lock = lock_sys.get_first(block->page.id());
if (!lock) {
goto function_exit;
@@ -5019,7 +4933,7 @@ lock_rec_validate(
/*==============*/
ulint start, /*!< in: lock_sys.rec_hash
bucket */
- ib_uint64_t* limit) /*!< in/out: upper limit of
+ page_id_t* limit) /*!< in/out: upper limit of
(space, page_no) */
{
ut_ad(lock_mutex_own());
@@ -5029,14 +4943,10 @@ lock_rec_validate(
lock != NULL;
lock = static_cast<const lock_t*>(HASH_GET_NEXT(hash, lock))) {
- ib_uint64_t current;
-
ut_ad(!trx_is_ac_nl_ro(lock->trx));
ut_ad(lock_get_type(lock) == LOCK_REC);
- current = ut_ull_create(
- lock->un_member.rec_lock.space,
- lock->un_member.rec_lock.page_no);
+ page_id_t current(lock->un_member.rec_lock.page_id);
if (current > *limit) {
*limit = current + 1;
@@ -5049,12 +4959,7 @@ lock_rec_validate(
/*********************************************************************//**
Validate a record lock's block */
-static
-void
-lock_rec_block_validate(
-/*====================*/
- ulint space_id,
- ulint page_no)
+static void lock_rec_block_validate(const page_id_t page_id)
{
/* The lock and the block that it is referring to may be freed at
this point. We pass BUF_GET_POSSIBLY_FREED to skip a debug check.
@@ -5069,12 +4974,12 @@ lock_rec_block_validate(
discard or rebuild a tablespace do hold an exclusive table
lock, which would conflict with any locks referring to the
tablespace from other transactions. */
- if (fil_space_t* space = fil_space_acquire(space_id)) {
+ if (fil_space_t* space = fil_space_acquire(page_id.space())) {
dberr_t err = DB_SUCCESS;
mtr_start(&mtr);
block = buf_page_get_gen(
- page_id_t(space_id, page_no),
+ page_id,
space->zip_size(),
RW_X_LATCH, NULL,
BUF_GET_POSSIBLY_FREED,
@@ -5083,8 +4988,7 @@ lock_rec_block_validate(
if (err != DB_SUCCESS) {
ib::error() << "Lock rec block validate failed for tablespace "
<< space->name
- << " space_id " << space_id
- << " page_no " << page_no << " err " << err;
+ << page_id << " err " << err;
}
if (block) {
@@ -5128,13 +5032,7 @@ bool
lock_validate()
/*===========*/
{
- typedef std::pair<ulint, ulint> page_addr_t;
- typedef std::set<
- page_addr_t,
- std::less<page_addr_t>,
- ut_allocator<page_addr_t> > page_addr_set;
-
- page_addr_set pages;
+ std::set<page_id_t> pages;
lock_mutex_enter();
@@ -5146,24 +5044,21 @@ lock_validate()
validation check. */
for (ulint i = 0; i < lock_sys.rec_hash.n_cells; i++) {
- ib_uint64_t limit = 0;
+ page_id_t limit(0, 0);
while (const lock_t* lock = lock_rec_validate(i, &limit)) {
if (lock_rec_find_set_bit(lock) == ULINT_UNDEFINED) {
/* The lock bitmap is empty; ignore it. */
continue;
}
- const lock_rec_t& l = lock->un_member.rec_lock;
- pages.insert(std::make_pair(l.space, l.page_no));
+ pages.insert(lock->un_member.rec_lock.page_id);
}
}
lock_mutex_exit();
- for (page_addr_set::const_iterator it = pages.begin();
- it != pages.end();
- ++it) {
- lock_rec_block_validate((*it).first, (*it).second);
+ for (const page_id_t page_id : pages) {
+ lock_rec_block_validate(page_id);
}
return(true);
@@ -6460,10 +6355,6 @@ DeadlockChecker::get_first_lock(ulint* heap_no) const
const lock_t* lock = m_wait_lock;
if (lock_get_type_low(lock) == LOCK_REC) {
- hash_table_t* lock_hash = lock->type_mode & LOCK_PREDICATE
- ? &lock_sys.prdt_hash
- : &lock_sys.rec_hash;
-
/* We are only interested in records that match the heap_no. */
*heap_no = lock_rec_find_set_bit(lock);
@@ -6471,10 +6362,11 @@ DeadlockChecker::get_first_lock(ulint* heap_no) const
ut_ad(*heap_no != ULINT_UNDEFINED);
/* Find the locks on the page. */
- lock = lock_rec_get_first_on_page_addr(
- lock_hash,
- lock->un_member.rec_lock.space,
- lock->un_member.rec_lock.page_no);
+ lock = lock_sys.get_first(
+ lock->type_mode & LOCK_PREDICATE
+ ? lock_sys.prdt_hash
+ : lock_sys.rec_hash,
+ lock->un_member.rec_lock.page_id);
/* Position on the first lock on the physical record.*/
if (!lock_rec_get_nth_bit(lock, *heap_no)) {
diff --git a/storage/innobase/lock/lock0prdt.cc b/storage/innobase/lock/lock0prdt.cc
index a04fd3fe73c..1eb96a0dcf0 100644
--- a/storage/innobase/lock/lock0prdt.cc
+++ b/storage/innobase/lock/lock0prdt.cc
@@ -394,7 +394,8 @@ lock_prdt_find_on_page(
ut_ad(lock_mutex_own());
- for (lock = lock_rec_get_first_on_page(lock_hash_get(type_mode), block);
+ for (lock = lock_sys.get_first(*lock_hash_get(type_mode),
+ block->page.id());
lock != NULL;
lock = lock_rec_get_next_on_page(lock)) {
@@ -457,7 +458,8 @@ lock_prdt_add_to_queue(
lock_t* lock;
- for (lock = lock_rec_get_first_on_page(lock_hash_get(type_mode), block);
+ for (lock = lock_sys.get_first(*lock_hash_get(type_mode),
+ block->page.id());
lock != NULL;
lock = lock_rec_get_next_on_page(lock)) {
@@ -619,16 +621,12 @@ lock_prdt_update_parent(
buf_block_t* right_block, /*!< in/out: the new half page */
lock_prdt_t* left_prdt, /*!< in: MBR on the old page */
lock_prdt_t* right_prdt, /*!< in: MBR on the new page */
- ulint space, /*!< in: parent space id */
- ulint page_no) /*!< in: parent page number */
+ const page_id_t page_id) /*!< in: parent page */
{
- lock_t* lock;
-
lock_mutex_enter();
/* Get all locks in parent */
- for (lock = lock_rec_get_first_on_page_addr(
- &lock_sys.prdt_hash, space, page_no);
+ for (lock_t *lock = lock_sys.get_first_prdt(page_id);
lock;
lock = lock_rec_get_next_on_page(lock)) {
lock_prdt_t* lock_prdt;
@@ -675,21 +673,15 @@ lock_prdt_update_split_low(
buf_block_t* new_block, /*!< in/out: the new half page */
lock_prdt_t* prdt, /*!< in: MBR on the old page */
lock_prdt_t* new_prdt, /*!< in: MBR on the new page */
- ulint space, /*!< in: space id */
- ulint page_no, /*!< in: page number */
+ const page_id_t page_id, /*!< in: page number */
unsigned type_mode) /*!< in: LOCK_PREDICATE or
LOCK_PRDT_PAGE */
{
lock_t* lock;
- lock_mutex_enter();
-
- for (lock = lock_rec_get_first_on_page_addr(
- lock_hash_get(type_mode), space, page_no);
+ for (lock = lock_sys.get_first(*lock_hash_get(type_mode), page_id);
lock;
lock = lock_rec_get_next_on_page(lock)) {
- ut_ad(lock);
-
/* First dealing with Page Lock */
if (lock->type_mode & LOCK_PRDT_PAGE) {
/* Duplicate the lock to new page */
@@ -739,8 +731,6 @@ lock_prdt_update_split_low(
trx_mutex_exit(lock->trx);
}
}
-
- lock_mutex_exit();
}
/**************************************************************//**
@@ -751,14 +741,17 @@ lock_prdt_update_split(
buf_block_t* new_block, /*!< in/out: the new half page */
lock_prdt_t* prdt, /*!< in: MBR on the old page */
lock_prdt_t* new_prdt, /*!< in: MBR on the new page */
- ulint space, /*!< in: space id */
- ulint page_no) /*!< in: page number */
+ const page_id_t page_id) /*!< in: page number */
{
+ lock_mutex_enter();
+
lock_prdt_update_split_low(new_block, prdt, new_prdt,
- space, page_no, LOCK_PREDICATE);
+ page_id, LOCK_PREDICATE);
lock_prdt_update_split_low(new_block, NULL, NULL,
- space, page_no, LOCK_PRDT_PAGE);
+ page_id, LOCK_PRDT_PAGE);
+
+ lock_mutex_exit();
}
/*********************************************************************//**
@@ -814,9 +807,9 @@ lock_prdt_lock(
ut_ad(!dict_index_is_online_ddl(index));
ut_ad(type_mode & (LOCK_PREDICATE | LOCK_PRDT_PAGE));
- hash_table_t* hash = type_mode == LOCK_PREDICATE
- ? &lock_sys.prdt_hash
- : &lock_sys.prdt_page_hash;
+ const hash_table_t& hash = type_mode == LOCK_PREDICATE
+ ? lock_sys.prdt_hash
+ : lock_sys.prdt_page_hash;
/* Another transaction cannot have an implicit lock on the record,
because when we come here, we already have modified the clustered
@@ -826,7 +819,7 @@ lock_prdt_lock(
lock_mutex_enter();
const unsigned prdt_mode = type_mode | mode;
- lock_t* lock = lock_rec_get_first_on_page(hash, block);
+ lock_t* lock = lock_sys.get_first(hash, block->page.id());
if (lock == NULL) {
lock = lock_rec_create(
@@ -905,9 +898,7 @@ Acquire a "Page" lock on a block
@return DB_SUCCESS, DB_LOCK_WAIT, or DB_DEADLOCK */
dberr_t
lock_place_prdt_page_lock(
-/*======================*/
- ulint space, /*!< in: space for the page to lock */
- ulint page_no, /*!< in: page number */
+ const page_id_t page_id, /*!< in: page identifier */
dict_index_t* index, /*!< in: secondary index */
que_thr_t* thr) /*!< in: query thread */
{
@@ -924,9 +915,7 @@ lock_place_prdt_page_lock(
lock_mutex_enter();
- const lock_t* lock = lock_rec_get_first_on_page_addr(
- &lock_sys.prdt_page_hash, space, page_no);
-
+ const lock_t* lock = lock_sys.get_first_prdt_page(page_id);
const ulint mode = LOCK_S | LOCK_PRDT_PAGE;
trx_t* trx = thr_get_trx(thr);
@@ -952,7 +941,7 @@ lock_place_prdt_page_lock(
#ifdef WITH_WSREP
NULL, NULL, /* FIXME: replicate SPATIAL INDEX locks */
#endif
- mode, space, page_no, NULL, PRDT_HEAPNO,
+ mode, page_id, NULL, PRDT_HEAPNO,
index, trx, FALSE);
#ifdef PRDT_DIAG
@@ -967,25 +956,19 @@ lock_place_prdt_page_lock(
/** Check whether there are R-tree Page lock on a page
@param[in] trx trx to test the lock
-@param[in] space space id for the page
-@param[in] page_no page number
+@param[in] page_id page identifier
@return true if there is none */
-bool
-lock_test_prdt_page_lock(
- const trx_t* trx,
- ulint space,
- ulint page_no)
+bool lock_test_prdt_page_lock(const trx_t *trx, const page_id_t page_id)
{
lock_t* lock;
lock_mutex_enter();
- lock = lock_rec_get_first_on_page_addr(
- &lock_sys.prdt_page_hash, space, page_no);
+ lock = lock_sys.get_first_prdt_page(page_id);
lock_mutex_exit();
- return(lock == NULL || trx == lock->trx);
+ return(!lock || trx == lock->trx);
}
/*************************************************************//**
@@ -1030,15 +1013,10 @@ lock_prdt_page_free_from_discard(
{
lock_t* lock;
lock_t* next_lock;
- ulint space;
- ulint page_no;
ut_ad(lock_mutex_own());
- space = block->page.id().space();
- page_no = block->page.id().page_no();
-
- lock = lock_rec_get_first_on_page_addr(lock_hash, space, page_no);
+ lock = lock_sys.get_first(*lock_hash, block->page.id());
while (lock != NULL) {
next_lock = lock_rec_get_next_on_page(lock);
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index aec4fa32ad7..5579e53b6c1 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -499,9 +499,8 @@ row_purge_remove_sec_if_poss_leaf(
&& btr_cur->rtr_info->thr
? thr_get_trx(
btr_cur->rtr_info->thr)
- : NULL,
- block->page.id().space(),
- block->page.id().page_no())) {
+ : nullptr,
+ block->page.id())) {
/* this is the last record on page,
and it has a "page" lock on it,
which mean search is still depending
diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc
index 2736dbd285f..82477399552 100644
--- a/storage/innobase/trx/trx0i_s.cc
+++ b/storage/innobase/trx/trx0i_s.cc
@@ -394,13 +394,11 @@ i_s_locks_row_validate(
if (!row->lock_index) {
/* table lock */
ut_ad(!row->lock_data);
- ut_ad(!row->lock_space);
- ut_ad(!row->lock_page);
+ ut_ad(row->lock_page == page_id_t(0, 0));
ut_ad(!row->lock_rec);
} else {
/* record lock */
/* row->lock_data == NULL if buf_page_try_get() == NULL */
- ut_ad(row->lock_page);
}
return(TRUE);
@@ -631,9 +629,7 @@ fill_lock_data(
mtr_start(&mtr);
- block = buf_page_try_get(page_id_t(lock->un_member.rec_lock.space,
- lock->un_member.rec_lock.page_no),
- &mtr);
+ block = buf_page_try_get(lock->un_member.rec_lock.page_id, &mtr);
if (block == NULL) {
@@ -754,8 +750,7 @@ static bool fill_locks_row(
return false;
}
- row->lock_space = lock->un_member.rec_lock.space;
- row->lock_page = lock->un_member.rec_lock.page_no;
+ row->lock_page = lock->un_member.rec_lock.page_id;
row->lock_rec = heap_no;
if (!fill_lock_data(&row->lock_data, lock, heap_no, cache)) {
@@ -766,8 +761,7 @@ static bool fill_locks_row(
} else {
row->lock_index = NULL;
- row->lock_space = 0;
- row->lock_page = 0;
+ row->lock_page = page_id_t(0, 0);
row->lock_rec = 0;
row->lock_data = NULL;
@@ -831,13 +825,9 @@ fold_lock(
switch (lock_get_type(lock)) {
case LOCK_REC:
ut_a(heap_no != 0xFFFF);
-
ret = ut_fold_ulint_pair((ulint) lock->trx->id,
- lock->un_member.rec_lock.space);
-
- ret = ut_fold_ulint_pair(ret,
- lock->un_member.rec_lock.page_no);
-
+ lock->un_member.rec_lock.page_id.
+ fold());
ret = ut_fold_ulint_pair(ret, heap_no);
break;
@@ -880,8 +870,7 @@ locks_row_eq_lock(
ut_a(heap_no != 0xFFFF);
return(row->lock_trx_id == lock->trx->id
- && row->lock_space == lock->un_member.rec_lock.space
- && row->lock_page == lock->un_member.rec_lock.page_no
+ && row->lock_page == lock->un_member.rec_lock.page_id
&& row->lock_rec == heap_no);
case LOCK_TABLE:
@@ -1477,8 +1466,8 @@ trx_i_s_create_lock_id(
res_len = snprintf(lock_id, lock_id_size,
TRX_ID_FMT
":%u:%u:%u",
- row->lock_trx_id, row->lock_space,
- row->lock_page, row->lock_rec);
+ row->lock_trx_id, row->lock_page.space(),
+ row->lock_page.page_no(), row->lock_rec);
} else {
/* table lock */
res_len = snprintf(lock_id, lock_id_size,