From c6e0b8d18e768661a22d05e685348a0d0dec3aa1 Mon Sep 17 00:00:00 2001 From: "istruewing@chilla.local" <> Date: Wed, 16 May 2007 20:00:23 +0200 Subject: [PATCH 1/2] Bug#23068 - key_cache_block_size is not set or displayes correctly Command line and configuration file option 'key_cache_block_size' was reduced by MALLOC_OVERHEAD (8 in a production server, 36 in a debug server) from the user supplied value and restricted it to the greatest multiple of 512 less or equal to the reduced value. This patch changes option 'key_cache_block_size' to not deduce MALLOC_OVERHEAD from the input value. However, the restriction to a multiple of 512 is still done. --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e5abef25b62..c1c7dad1551 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5806,7 +5806,7 @@ log and this option does nothing anymore.", (gptr*) &dflt_key_cache_var.param_block_size, (gptr*) 0, 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, - KEY_CACHE_BLOCK_SIZE , 512, 1024*16, MALLOC_OVERHEAD, 512, 0}, + KEY_CACHE_BLOCK_SIZE, 512, 1024 * 16, 0, 512, 0}, {"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT, "The minimum percentage of warm blocks in key cache", (gptr*) &dflt_key_cache_var.param_division_limit, From 59a05422097a9f902f29c0aa749f65f321e23460 Mon Sep 17 00:00:00 2001 From: "istruewing@chilla.local" <> Date: Thu, 31 May 2007 20:04:54 +0200 Subject: [PATCH 2/2] Bug#28478 - Improper key_cache_block_size corrupts MyISAM tables Setting a key_cache_block_size which is not a power of 2 could corrupt MyISAM tables. A couple of computations in the key cache code use bit operations which do only work if key_cache_block_size is a power of 2. Replaced bit operations by arithmetic operations to make key cache able to handle block sizes that are not a power of 2. --- include/keycache.h | 1 - mysql-test/r/key_cache.result | 27 +++++++++++++++++++++++++++ mysql-test/t/key_cache.test | 27 +++++++++++++++++++++++++++ mysys/mf_keycache.c | 11 +++++------ 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/include/keycache.h b/include/keycache.h index dc763b8cc08..54c099fc474 100644 --- a/include/keycache.h +++ b/include/keycache.h @@ -46,7 +46,6 @@ typedef struct st_key_cache my_bool key_cache_inited; my_bool resize_in_flush; /* true during flush of resize operation */ my_bool can_be_used; /* usage of cache for read/write is allowed */ - uint key_cache_shift; ulong key_cache_mem_size; /* specified size of the cache memory */ uint key_cache_block_size; /* size of the page buffer of a cache block */ ulong min_warm_blocks; /* min number of warm blocks; */ diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result index a1bf3d0e128..1ab58c1ad6c 100644 --- a/mysql-test/r/key_cache.result +++ b/mysql-test/r/key_cache.result @@ -341,3 +341,30 @@ Warning 1438 Cannot drop default keycache select @@global.key_buffer_size; @@global.key_buffer_size 2097152 +SET @bug28478_key_cache_block_size= @@global.key_cache_block_size; +SET GLOBAL key_cache_block_size= 1536; +CREATE TABLE t1 ( +id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, +c1 CHAR(150), +c2 CHAR(150), +c3 CHAR(150), +KEY(c1, c2, c3) +) ENGINE= MyISAM; +INSERT INTO t1 (c1, c2, c3) VALUES +('a', 'b', 'c'), ('b', 'c', 'd'), ('c', 'd', 'e'), ('d', 'e', 'f'), +('e', 'f', 'g'), ('f', 'g', 'h'), ('g', 'h', 'i'), ('h', 'i', 'j'), +('i', 'j', 'k'), ('j', 'k', 'l'), ('k', 'l', 'm'), ('l', 'm', 'n'), +('m', 'n', 'o'), ('n', 'o', 'p'), ('o', 'p', 'q'), ('p', 'q', 'r'), +('q', 'r', 's'), ('r', 's', 't'), ('s', 't', 'u'), ('t', 'u', 'v'), +('u', 'v', 'w'), ('v', 'w', 'x'), ('w', 'x', 'y'), ('x', 'y', 'z'); +INSERT INTO t1 (c1, c2, c3) SELECT c1, c2, c3 from t1; +INSERT INTO t1 (c1, c2, c3) SELECT c1, c2, c3 from t1; +INSERT INTO t1 (c1, c2, c3) SELECT c1, c2, c3 from t1; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +SHOW VARIABLES LIKE 'key_cache_block_size'; +Variable_name Value +key_cache_block_size 1536 +SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size; +DROP TABLE t1; diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test index 3044964ebc3..4c14dc96aaa 100644 --- a/mysql-test/t/key_cache.test +++ b/mysql-test/t/key_cache.test @@ -219,4 +219,31 @@ set global key_cache_block_size= @my_key_cache_block_size; set @@global.key_buffer_size=0; select @@global.key_buffer_size; +# +# Bug#28478 - Improper key_cache_block_size corrupts MyISAM tables +# +SET @bug28478_key_cache_block_size= @@global.key_cache_block_size; +SET GLOBAL key_cache_block_size= 1536; +CREATE TABLE t1 ( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + c1 CHAR(150), + c2 CHAR(150), + c3 CHAR(150), + KEY(c1, c2, c3) + ) ENGINE= MyISAM; +INSERT INTO t1 (c1, c2, c3) VALUES + ('a', 'b', 'c'), ('b', 'c', 'd'), ('c', 'd', 'e'), ('d', 'e', 'f'), + ('e', 'f', 'g'), ('f', 'g', 'h'), ('g', 'h', 'i'), ('h', 'i', 'j'), + ('i', 'j', 'k'), ('j', 'k', 'l'), ('k', 'l', 'm'), ('l', 'm', 'n'), + ('m', 'n', 'o'), ('n', 'o', 'p'), ('o', 'p', 'q'), ('p', 'q', 'r'), + ('q', 'r', 's'), ('r', 's', 't'), ('s', 't', 'u'), ('t', 'u', 'v'), + ('u', 'v', 'w'), ('v', 'w', 'x'), ('w', 'x', 'y'), ('x', 'y', 'z'); +INSERT INTO t1 (c1, c2, c3) SELECT c1, c2, c3 from t1; +INSERT INTO t1 (c1, c2, c3) SELECT c1, c2, c3 from t1; +INSERT INTO t1 (c1, c2, c3) SELECT c1, c2, c3 from t1; +CHECK TABLE t1; +SHOW VARIABLES LIKE 'key_cache_block_size'; +SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size; +DROP TABLE t1; + # End of 4.1 tests diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 87f136dbf81..af910678a1f 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -173,7 +173,7 @@ static void test_key_cache(KEY_CACHE *keycache, #endif #define KEYCACHE_HASH(f, pos) \ -(((ulong) ((pos) >> keycache->key_cache_shift)+ \ +(((ulong) ((pos) / keycache->key_cache_block_size) + \ (ulong) (f)) & (keycache->hash_entries-1)) #define FILE_HASH(f) ((uint) (f) & (CHANGED_BLOCKS_HASH-1)) @@ -329,7 +329,6 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, keycache->key_cache_mem_size= use_mem; keycache->key_cache_block_size= key_cache_block_size; - keycache->key_cache_shift= my_bit_log2(key_cache_block_size); DBUG_PRINT("info", ("key_cache_block_size: %u", key_cache_block_size)); @@ -352,7 +351,7 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, ALIGN_SIZE(hash_links * sizeof(HASH_LINK)) + ALIGN_SIZE(sizeof(HASH_LINK*) * keycache->hash_entries))) + - ((ulong) blocks << keycache->key_cache_shift) > use_mem) + ((ulong) blocks * keycache->key_cache_block_size) > use_mem) blocks--; /* Allocate memory for cache page buffers */ if ((keycache->block_mem= @@ -1807,7 +1806,7 @@ byte *key_cache_read(KEY_CACHE *keycache, uint status; int page_st; - offset= (uint) (filepos & (keycache->key_cache_block_size-1)); + offset= (uint) (filepos % keycache->key_cache_block_size); /* Read data in key_cache_block_size increments */ do { @@ -1946,7 +1945,7 @@ int key_cache_insert(KEY_CACHE *keycache, int error; uint offset; - offset= (uint) (filepos & (keycache->key_cache_block_size-1)); + offset= (uint) (filepos % keycache->key_cache_block_size); do { keycache_pthread_mutex_lock(&keycache->cache_lock); @@ -2081,7 +2080,7 @@ int key_cache_write(KEY_CACHE *keycache, int page_st; uint offset; - offset= (uint) (filepos & (keycache->key_cache_block_size-1)); + offset= (uint) (filepos % keycache->key_cache_block_size); do { keycache_pthread_mutex_lock(&keycache->cache_lock);