From: Annamalai Gurusami Date: December 20 2012 6:28am Subject: bzr push into mysql-5.6 branch (annamalai.gurusami:4807 to 4808) Bug#14556349 List-Archive: http://lists.mysql.com/commits/145541 X-Bug: 14556349 Message-Id: <20121220062858.29042.71802.4808@rainbow> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 4808 Annamalai Gurusami 2012-12-20 Bug #14556349 RENAME OF COMPRESSED TABLE AND INSERT BUFFER MERGE CAUSE HANG Problem Statement: When the operation RENAME TABLE is about rename the tablespace of the table, it will stop all i/o operations on the tablespace temporarily. For this the fil_space_t::stop_ios member is used. Once the fil_space_t::stop_ios member is set to TRUE in the RENAME TABLE operation, it is expected that no new i/o operation will be done on the tablespace and all pending i/o operation can be completed on the tablespace. If the pending i/o operations initiate any new i/o operations then there will be deadlock. The RENAME TABLE operation will be waiting for pending i/o on the tablespace to be completed, and the pending i/o operations will be waiting on the RENAME TABLE operation to set the file_space_t::stop_ios flag to be set to FALSE. But in the given scenario the pending i/o operations did not initiate new i/o. But they where still unnecessarily checking the fil_space_t::stop_ios flag. This resulted in deadlock. Solution: I noticed that this deadlock happens in fil_space_get_size() and fil_space_get_zip_size() in the i/o threads. These functions check the stop_ios flag even when no i/o will be initiated. I modified these functions to ensure that they check the stop_ios flag only when they will be initiating an i/o operation. This solves the problem. rb://1635 (mysql-5.5) rb://1660 (mysql-trunk) approved by Inaam, Jimmy, and ima. modified: storage/innobase/fil/fil0fil.cc 4807 Tor Didriksen 2012-12-19 [merge] empty merge 5.5 => 5.6 === modified file 'storage/innobase/fil/fil0fil.cc' --- a/storage/innobase/fil/fil0fil.cc revid:tor.didriksen@stripped +++ b/storage/innobase/fil/fil0fil.cc revid:annamalai.gurusami@stripped @@ -1481,6 +1481,21 @@ fil_space_get_space( if (space->size == 0 && space->purpose == FIL_TABLESPACE) { ut_a(id != 0); + mutex_exit(&fil_system->mutex); + + /* It is possible that the space gets evicted at this point + before the fil_mutex_enter_and_prepare_for_io() acquires + the fil_system->mutex. Check for this after completing the + call to fil_mutex_enter_and_prepare_for_io(). */ + fil_mutex_enter_and_prepare_for_io(id); + + /* We are still holding the fil_system->mutex. Check if + the space is still in memory cache. */ + space = fil_space_get_by_id(id); + if (space == NULL) { + return(NULL); + } + /* The following code must change when InnoDB supports multiple datafiles per tablespace. */ ut_a(1 == UT_LIST_GET_LEN(space->chain)); @@ -1552,8 +1567,7 @@ fil_space_get_size( ulint size; ut_ad(fil_system); - - fil_mutex_enter_and_prepare_for_io(id); + mutex_enter(&fil_system->mutex); space = fil_space_get_space(id); @@ -1583,7 +1597,7 @@ fil_space_get_flags( return(0); } - fil_mutex_enter_and_prepare_for_io(id); + mutex_enter(&fil_system->mutex); space = fil_space_get_space(id); No bundle (reason: useless for push emails).