#At file:///home/svoj/devel/innodb-snapshots/mysql-5.1-bugteam/ based on revid:svoj@stripped
3478 Sergey Vojtovich 2010-04-01
Applying InnoDB snapshot, fixes BUG#35077.
Detailed revision comments:
r6548 | marko | 2010-02-03 15:01:39 +0200 (Wed, 03 Feb 2010) | 11 lines
branches/zip: buf_LRU_invalidate_tablespace(): Ensure that prev_bpage
is not relocated when freeing a compressed block. This avoids the
costly rescan of the LRU list. (Bug #35077, Issue #449)
At most one buffer-fix will be active at a time, affecting two blocks:
the buf_page_t and the compressed page frame. This should not block
the memory defragmentation in buf0buddy.c too much. In fact, it may
avoid unnecessary copying if also prev_bpage belongs to the tablespace
that is being invalidated.
rb://240
modified:
storage/innodb_plugin/ChangeLog
storage/innodb_plugin/buf/buf0lru.c
=== modified file 'storage/innodb_plugin/ChangeLog'
--- a/storage/innodb_plugin/ChangeLog 2010-04-01 11:36:27 +0000
+++ b/storage/innodb_plugin/ChangeLog 2010-04-01 11:36:54 +0000
@@ -1,5 +1,11 @@
2010-02-03 The InnoDB Team
+ * buf/buf0lru.c:
+ Fix Bug#35077 Very slow DROP TABLE (ALTER TABLE, OPTIMIZE TABLE)
+ on compressed tables
+
+2010-02-03 The InnoDB Team
+
* handler/ha_innodb.cc, include/row0mysql.h, row/row0mysql.c:
Clean up CHECK TABLE error handling.
=== modified file 'storage/innodb_plugin/buf/buf0lru.c'
--- a/storage/innodb_plugin/buf/buf0lru.c 2010-04-01 11:27:18 +0000
+++ b/storage/innodb_plugin/buf/buf0lru.c 2010-04-01 11:36:54 +0000
@@ -347,11 +347,11 @@ scan_again:
all_freed = TRUE;
-rescan:
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
while (bpage != NULL) {
buf_page_t* prev_bpage;
+ ibool prev_bpage_buf_fix = FALSE;
ut_a(buf_page_in_file(bpage));
@@ -394,8 +394,40 @@ rescan:
(ulong) buf_page_get_page_no(bpage));
}
#endif
- if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE
- && ((buf_block_t*) bpage)->is_hashed) {
+ if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
+ /* This is a compressed-only block
+ descriptor. Ensure that prev_bpage
+ cannot be relocated when bpage is freed. */
+ if (UNIV_LIKELY(prev_bpage != NULL)) {
+ switch (buf_page_get_state(
+ prev_bpage)) {
+ case BUF_BLOCK_FILE_PAGE:
+ /* Descriptors of uncompressed
+ blocks will not be relocated,
+ because we are holding the
+ buf_pool_mutex. */
+ break;
+ case BUF_BLOCK_ZIP_PAGE:
+ case BUF_BLOCK_ZIP_DIRTY:
+ /* Descriptors of compressed-
+ only blocks can be relocated,
+ unless they are buffer-fixed.
+ Because both bpage and
+ prev_bpage are protected by
+ buf_pool_zip_mutex, it is
+ not necessary to acquire
+ further mutexes. */
+ ut_ad(&buf_pool_zip_mutex
+ == block_mutex);
+ ut_ad(mutex_own(block_mutex));
+ prev_bpage_buf_fix = TRUE;
+ prev_bpage->buf_fix_count++;
+ break;
+ default:
+ ut_error;
+ }
+ }
+ } else if (((buf_block_t*) bpage)->is_hashed) {
ulint page_no;
ulint zip_size;
@@ -419,7 +451,8 @@ rescan:
buf_flush_remove(bpage);
}
- /* Remove from the LRU list */
+ /* Remove from the LRU list. */
+
if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
!= BUF_BLOCK_ZIP_FREE) {
buf_LRU_block_free_hashed_page((buf_block_t*)
@@ -431,18 +464,27 @@ rescan:
ut_ad(block_mutex == &buf_pool_zip_mutex);
ut_ad(!mutex_own(block_mutex));
- /* The compressed block descriptor
- (bpage) has been deallocated and
- block_mutex released. Also,
- buf_buddy_free() may have relocated
- prev_bpage. Rescan the LRU list. */
+ if (prev_bpage_buf_fix) {
+ /* We temporarily buffer-fixed
+ prev_bpage, so that
+ buf_buddy_free() could not
+ relocate it, in case it was a
+ compressed-only block
+ descriptor. */
+
+ mutex_enter(block_mutex);
+ ut_ad(prev_bpage->buf_fix_count > 0);
+ prev_bpage->buf_fix_count--;
+ mutex_exit(block_mutex);
+ }
- goto rescan;
+ goto next_page_no_mutex;
}
next_page:
mutex_exit(block_mutex);
}
+next_page_no_mutex:
bpage = prev_bpage;
}
Attachment: [text/bzr-bundle] bzr/svoj@sun.com-20100401113654-grersf4w0gbyzl5l.bundle
| Thread |
|---|
| • bzr commit into mysql-5.1-bugteam branch (svoj:3478) Bug#35077 | Sergey Vojtovich | 1 Apr |