From 0083f645886eba3d9611b9430b30fcde458c3be7 Mon Sep 17 00:00:00 2001 From: marko <> Date: Wed, 10 Dec 2008 15:20:17 +0000 Subject: [PATCH] branches/innodb+: When buffering an insert, notify the buffer pool watch. This should fix the race condition that seems to have caused Issue #126: When another thread is buffering an insert for the record that is being purged, it should invoke buf_pool_watch_notify(), so that the purge will not be buffered. Otherwise, the purge would be buffered for the wrong record (one that was inserted after the purge determined that the record can be removed). When deletes are not buffered, the latch on the secondary index page would prevent the insert from occurring. In delete buffering, the buf_pool_watch replaces the page latch when the page is not in the buffer pool. buf_pool_watch_notify(): Make public. ibuf_insert(): Invoke buf_pool_watch_notify() when buffering an insert or a delete-mark operation. --- buf/buf0buf.c | 8 ++++---- ibuf/ibuf0ibuf.c | 17 +++++++++++++++++ include/buf0buf.h | 8 ++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/buf/buf0buf.c b/buf/buf0buf.c index 4b4355033cb..acb9af524f9 100644 --- a/buf/buf0buf.c +++ b/buf/buf0buf.c @@ -2506,13 +2506,13 @@ buf_page_init_low( } /************************************************************************ -Set watch happened flag. */ -UNIV_INLINE +Set watch occurred flag. */ +UNIV_INTERN void buf_pool_watch_notify( /*==================*/ - ulint space, /* in: space id of page read in */ - ulint offset) /* in: offset of page read in */ + ulint space, /* in: space id of page read in */ + ulint offset) /* in: offset of page read in */ { ut_ad(buf_pool_mutex_own()); diff --git a/ibuf/ibuf0ibuf.c b/ibuf/ibuf0ibuf.c index 762e15daeb7..9afa1bb06d1 100644 --- a/ibuf/ibuf0ibuf.c +++ b/ibuf/ibuf0ibuf.c @@ -3462,6 +3462,23 @@ ibuf_insert( ut_a(!dict_index_is_clust(index)); + if (UNIV_LIKELY(op != IBUF_OP_DELETE)) { + /* If another thread buffers an insert on a page while + the purge is in progress, the purge for the same page + must not be buffered, because it could remove a record + that was re-inserted later. + + We do not call this in the IBUF_OP_DELETE case, + because that would always trigger the buffer pool + watch during purge and thus prevent the buffering of + delete operations. We assume that IBUF_OP_DELETE + operations are only issued by the purge thread. */ + + buf_pool_mutex_enter(); + buf_pool_watch_notify(space, page_no); + buf_pool_mutex_exit(); + } + entry_size = rec_get_converted_size(index, entry, 0); if (entry_size >= (page_get_free_space_of_empty(comp) / 2)) { diff --git a/include/buf0buf.h b/include/buf0buf.h index c5701586619..09664bd2258 100644 --- a/include/buf0buf.h +++ b/include/buf0buf.h @@ -981,6 +981,14 @@ UNIV_INTERN void buf_pool_watch_clear(void); /*======================*/ +/************************************************************************ +Set watch occurred flag. */ +UNIV_INTERN +void +buf_pool_watch_notify( +/*==================*/ + ulint space, /* in: space id of page read in */ + ulint offset);/* in: offset of page read in */ /******************************************************************** Check if the given page is being watched and has been read to the buffer pool. */