From 0e4caf39fe792168c1032ad4097a3991a12a1cc0 Mon Sep 17 00:00:00 2001 From: Satya B Date: Fri, 24 Apr 2009 17:18:20 +0530 Subject: [PATCH 1/2] Applying InnoDB snashot 5.0-ss4900 part 1, Fixes BUG#42279 1) BUG#42279 - Race condition in btr_search_drop_page_hash_when_freed() Detailed revision comments: r4031 | marko | 2009-01-23 15:33:46 +0200 (Fri, 23 Jan 2009) | 8 lines branches/5.0: btr_search_drop_page_hash_when_freed(): Check if buf_page_get_gen() returns NULL. The page may have been evicted from the buffer pool between buf_page_peek_if_search_hashed() and buf_page_get_gen(), because the buffer pool mutex will be released between these two calls. (Bug #42279) rb://82 approved by Heikki Tuuri --- innobase/btr/btr0sea.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 3c202c5a3bf..e8f294e9305 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -1101,12 +1101,20 @@ btr_search_drop_page_hash_when_freed( page = buf_page_get_gen(space, page_no, RW_S_LATCH, NULL, BUF_GET_IF_IN_POOL, __FILE__, __LINE__, &mtr); + /* Because the buffer pool mutex was released by + buf_page_peek_if_search_hashed(), it is possible that the + block was removed from the buffer pool by another thread + before buf_page_get_gen() got a chance to acquire the buffer + pool mutex again. Thus, we must check for a NULL return. */ + + if (UNIV_LIKELY(page != NULL)) { #ifdef UNIV_SYNC_DEBUG - buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH); + buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH); #endif /* UNIV_SYNC_DEBUG */ - btr_search_drop_page_hash_index(page); + btr_search_drop_page_hash_index(page); + } mtr_commit(&mtr); } From d5065d14265fd2fa6efc8d566a8f542f30ced36e Mon Sep 17 00:00:00 2001 From: Satya B Date: Fri, 24 Apr 2009 17:27:53 +0530 Subject: [PATCH 2/2] Applying InnoDB snashot 5.0-ss4900, part 2. Fixes BUG#43309 1) BUG#43309 - Test main.innodb can't be run twice Detailed revision comments: r4701 | vasil | 2009-04-13 17:03:46 +0300 (Mon, 13 Apr 2009) | 6 lines branches/5.0: Fix Bug#43309 Test main.innodb can't be run twice by making the innodb.test reentrant. --- mysql-test/r/innodb.result | 15 ++++++--------- mysql-test/t/innodb.test | 29 ++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 854712fdb1d..415fbe87f53 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1803,15 +1803,12 @@ Innodb_buffer_pool_pages_total 512 show status like "Innodb_page_size"; Variable_name Value Innodb_page_size 16384 -show status like "Innodb_rows_deleted"; -Variable_name Value -Innodb_rows_deleted 73 -show status like "Innodb_rows_inserted"; -Variable_name Value -Innodb_rows_inserted 29734 -show status like "Innodb_rows_updated"; -Variable_name Value -Innodb_rows_updated 29532 +innodb_rows_deleted +73 +innodb_rows_inserted +29734 +innodb_rows_updated +29532 show status like "Innodb_row_lock_waits"; Variable_name Value Innodb_row_lock_waits 0 diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index d045bad39f7..f09901d1112 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -13,6 +13,18 @@ -- source include/have_innodb.inc +# Save the original values of some variables in order to be able to +# estimate how much they have changed during the tests. Previously this +# test assumed that e.g. rows_deleted is 0 here and after deleting 23 +# rows it expected that rows_deleted will be 23. Now we do not make +# assumptions about the values of the variables at the beginning, e.g. +# rows_deleted should be 23 + "rows_deleted before the test". This allows +# the test to be run multiple times without restarting the mysqld server. +# See Bug#43309 Test main.innodb can't be run twice +-- let $innodb_rows_deleted_orig = query_get_value(SHOW STATUS WHERE variable_name = 'innodb_rows_deleted', Value, 1) +-- let $innodb_rows_inserted_orig = query_get_value(SHOW STATUS WHERE variable_name = 'innodb_rows_inserted', Value, 1) +-- let $innodb_rows_updated_orig = query_get_value(SHOW STATUS WHERE variable_name = 'innodb_rows_updated', Value, 1) + # # Small basic test with ignore # @@ -1344,9 +1356,14 @@ drop table t1; # uses previous ones(pages_created, rows_deleted, ...). show status like "Innodb_buffer_pool_pages_total"; show status like "Innodb_page_size"; -show status like "Innodb_rows_deleted"; -show status like "Innodb_rows_inserted"; -show status like "Innodb_rows_updated"; +-- let $innodb_rows_deleted = query_get_value(SHOW STATUS WHERE variable_name = 'innodb_rows_deleted', Value, 1) +-- let $innodb_rows_inserted = query_get_value(SHOW STATUS WHERE variable_name = 'innodb_rows_inserted', Value, 1) +-- let $innodb_rows_updated = query_get_value(SHOW STATUS WHERE variable_name = 'innodb_rows_updated', Value, 1) +-- disable_query_log +-- eval SELECT $innodb_rows_deleted - $innodb_rows_deleted_orig AS innodb_rows_deleted +-- eval SELECT $innodb_rows_inserted - $innodb_rows_inserted_orig AS innodb_rows_inserted +-- eval SELECT $innodb_rows_updated - $innodb_rows_updated_orig AS innodb_rows_updated +-- enable_query_log # Test for row locks InnoDB status variables. show status like "Innodb_row_lock_waits"; @@ -1365,6 +1382,8 @@ set global innodb_sync_spin_loops=20; show variables like "innodb_sync_spin_loops"; # Test for innodb_thread_concurrency variable +# save the original value so we can restore it at the end +-- let $innodb_thread_concurrency_orig = query_get_value(SHOW VARIABLES WHERE variable_name = 'innodb_thread_concurrency', Value, 1) show variables like "innodb_thread_concurrency"; set global innodb_thread_concurrency=1001; show variables like "innodb_thread_concurrency"; @@ -1372,6 +1391,10 @@ set global innodb_thread_concurrency=0; show variables like "innodb_thread_concurrency"; set global innodb_thread_concurrency=16; show variables like "innodb_thread_concurrency"; +# restore the orginal value, this way the test can be run multiple times +-- disable_query_log +-- eval set global innodb_thread_concurrency = $innodb_thread_concurrency_orig +-- enable_query_log # Test for innodb_concurrency_tickets variable show variables like "innodb_concurrency_tickets";