summaryrefslogtreecommitdiff
path: root/storage/innobase/page
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@oracle.com>2011-06-16 10:27:21 +0300
committerMarko Mäkelä <marko.makela@oracle.com>2011-06-16 10:27:21 +0300
commit5b4ceba58d1c9c35e0cba1f126290009bd7643ae (patch)
treef252321948bdee1d282694c11764203a51217f46 /storage/innobase/page
parenta8629376994c1365923ac9144354d7cd99d8288a (diff)
downloadmariadb-git-5b4ceba58d1c9c35e0cba1f126290009bd7643ae.tar.gz
Bug#12612184 Race condition after btr_cur_pessimistic_update()
btr_cur_compress_if_useful(), btr_compress(): Add the parameter ibool adjust. If adjust=TRUE, adjust the cursor position after compressing the page. btr_lift_page_up(): Return a pointer to the father page. BTR_KEEP_POS_FLAG: A new flag for btr_cur_pessimistic_update(). btr_cur_pessimistic_update(): If *big_rec != NULL and flags & BTR_KEEP_POS_FLAG, keep the cursor positioned on the updated record. Also, do not release the index tree x-lock if *big_rec != NULL. btr_cur_mtr_commit_and_start(): Commits and restarts a mini-transaction so that it will retain an x-lock on index->lock and the page of the cursor. This is invoked when btr_cur_pessimistic_update() returns *big_rec != NULL. In all callers of btr_cur_pessimistic_update() that do not pass BTR_KEEP_POS_FLAG, assert that *big_rec == NULL. btr_cur_compress(): Unused function [in the built-in MySQL 5.1], remove. page_rec_get_nth(): Return the nth record on the page (an inverse function of page_rec_get_n_recs_before()). Refactored from page_get_middle_rec(). page_get_middle_rec(): Invoke page_rec_get_nth(). page_cur_insert_rec_zip_reorg(): Make use of the page directory shortcuts in page_rec_get_nth() instead of scanning the whole list of records. row_ins_clust_index_entry_by_modify(): Pass BTR_KEEP_POS_FLAG to btr_cur_pessimistic_update(). row_ins_index_entry_low(): If row_ins_clust_index_entry_by_modify() returns a big_rec, invoke btr_cur_mtr_commit_and_start() in order to commit and start the mini-transaction without releasing the x-locks on index->lock and the cursor page, and write the big_rec. Releasing the page latch in mtr_commit() caused a race condition. row_upd_clust_rec(): Pass BTR_KEEP_POS_FLAG to btr_cur_pessimistic_update(). If it returns a big_rec, invoke btr_cur_mtr_commit_and_start() in order to commit and start the mini-transaction without releasing the x-locks on index->lock and the cursor page, and write the big_rec. Releasing the page latch in mtr_commit() caused a race condition. sync_thread_add_level(): Add the parameter ibool relock. When TRUE, bypass the latching order rules. rw_lock_add_debug_info(): For nested X-lock requests, pass relock=TRUE to sync_thread_add_level(). rb:678 approved by Jimmy Yang
Diffstat (limited to 'storage/innobase/page')
-rw-r--r--storage/innobase/page/page0page.c31
1 files changed, 12 insertions, 19 deletions
diff --git a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c
index 543cf9e34eb..6a89df7de22 100644
--- a/storage/innobase/page/page0page.c
+++ b/storage/innobase/page/page0page.c
@@ -1194,49 +1194,42 @@ page_dir_balance_slot(
}
/****************************************************************
-Returns the middle record of the record list. If there are an even number
-of records in the list, returns the first record of the upper half-list. */
+Returns the nth record of the record list. */
rec_t*
-page_get_middle_rec(
-/*================*/
- /* out: middle record */
- page_t* page) /* in: page */
+page_rec_get_nth(
+/*=============*/
+ /* out: nth record */
+ page_t* page, /* in: page */
+ ulint nth) /* in: nth record */
{
page_dir_slot_t* slot;
- ulint middle;
ulint i;
ulint n_owned;
- ulint count;
rec_t* rec;
- /* This many records we must leave behind */
- middle = (page_get_n_recs(page) + 2) / 2;
-
- count = 0;
+ ut_ad(nth < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1));
for (i = 0;; i++) {
slot = page_dir_get_nth_slot(page, i);
n_owned = page_dir_slot_get_n_owned(slot);
- if (count + n_owned > middle) {
+ if (n_owned > nth) {
break;
} else {
- count += n_owned;
+ nth -= n_owned;
}
}
ut_ad(i > 0);
slot = page_dir_get_nth_slot(page, i - 1);
rec = page_dir_slot_get_rec(slot);
- rec = page_rec_get_next(rec);
-
- /* There are now count records behind rec */
- for (i = 0; i < middle - count; i++) {
+ do {
rec = page_rec_get_next(rec);
- }
+ ut_ad(rec);
+ } while (nth--);
return(rec);
}