WL#86: Partitioned key cache for MyISAM.

This is the base patch for the task.
This commit is contained in:
Igor Babaev 2010-02-16 08:41:11 -08:00
parent abb87914ec
commit 7e4d89c973
33 changed files with 8063 additions and 325 deletions

View file

@ -19,96 +19,121 @@
#define _keycache_h
C_MODE_START
/* declare structures that is used by st_key_cache */
struct st_block_link;
typedef struct st_block_link BLOCK_LINK;
struct st_keycache_page;
typedef struct st_keycache_page KEYCACHE_PAGE;
struct st_hash_link;
typedef struct st_hash_link HASH_LINK;
/* info about requests in a waiting queue */
typedef struct st_keycache_wqueue
/*
Currently the default key cache is created as non-partitioned at
the start of the server unless the server is started with the parameter
--key-cache-partitions that is greater than 0
*/
#define DEFAULT_KEY_CACHE_PARTITIONS 0
/*
MAX_KEY_CACHE_PARTITIONS cannot be greater than
sizeof(MYISAM_SHARE::dirty_part_map)
Currently sizeof(MYISAM_SHARE::dirty_part_map)=sizeof(ulonglong)
*/
#define MAX_KEY_CACHE_PARTITIONS 64
/* The structure to get statistical data about a key cache */
typedef struct st_key_cache_statistics
{
struct st_my_thread_var *last_thread; /* circular list of waiting threads */
} KEYCACHE_WQUEUE;
ulonglong mem_size; /* memory for cache buffers/auxiliary structures */
ulonglong block_size; /* size of the each buffers in the key cache */
ulonglong blocks_used; /* maximum number of used blocks/buffers */
ulonglong blocks_unused; /* number of currently unused blocks */
ulonglong blocks_changed; /* number of currently dirty blocks */
ulonglong read_requests; /* number of read requests (read hits) */
ulonglong reads; /* number of actual reads from files into buffers */
ulonglong write_requests; /* number of write requests (write hits) */
ulonglong writes; /* number of actual writes from buffers into files */
} KEY_CACHE_STATISTICS;
/* The type of a key cache object */
typedef enum key_cache_type
{
SIMPLE_KEY_CACHE,
PARTITIONED_KEY_CACHE
} KEY_CACHE_TYPE;
#define CHANGED_BLOCKS_HASH 128 /* must be power of 2 */
/*
The key cache structure
It also contains read-only statistics parameters.
An object of the type KEY_CACHE_FUNCS contains pointers to all functions
from the key cache interface.
Currently a key cache can be of two types: simple and partitioned.
For each of them its own static structure of the type KEY_CACHE_FUNCS is
defined . The structures contain the pointers to the implementations of
the interface functions used by simple key caches and partitioned key
caches respectively. Pointers to these structures are assigned to key cache
objects at the time of their creation.
*/
typedef struct st_key_cache_funcs
{
int (*init) (void *, uint key_cache_block_size,
size_t use_mem, uint division_limit, uint age_threshold);
int (*resize) (void *, uint key_cache_block_size,
size_t use_mem, uint division_limit, uint age_threshold);
void (*change_param) (void *keycache_cb,
uint division_limit, uint age_threshold);
uchar* (*read) (void *keycache_cb,
File file, my_off_t filepos, int level,
uchar *buff, uint length,
uint block_length, int return_buffer);
int (*insert) (void *keycache_cb,
File file, my_off_t filepos, int level,
uchar *buff, uint length);
int (*write) (void *keycache_cb,
File file, void *file_extra,
my_off_t filepos, int level,
uchar *buff, uint length,
uint block_length, int force_write);
int (*flush) (void *keycache_cb,
int file, void *file_extra,
enum flush_type type);
int (*reset_counters) (const char *name, void *keycache_cb);
void (*end) (void *keycache_cb, my_bool cleanup);
void (*get_stats) (void *keycache_cb, uint partition_no,
KEY_CACHE_STATISTICS *key_cache_stats);
ulonglong (*get_stat_val) (void *keycache_cb, uint var_no);
} KEY_CACHE_FUNCS;
typedef struct st_key_cache
{
my_bool key_cache_inited;
my_bool in_resize; /* true during resize operation */
my_bool resize_in_flush; /* true during flush of resize operation */
KEY_CACHE_TYPE key_cache_type; /* type of the key cache used for debugging */
void *keycache_cb; /* control block of the used key cache */
KEY_CACHE_FUNCS *interface_funcs; /* interface functions of the key cache */
ulonglong param_buff_size; /* size the memory allocated for the cache */
ulong param_block_size; /* size of the blocks in the key cache */
ulong param_division_limit; /* min. percentage of warm blocks */
ulong param_age_threshold; /* determines when hot block is downgraded */
ulong param_partitions; /* number of the key cache partitions */
my_bool key_cache_inited; /* <=> key cache has been created */
my_bool can_be_used; /* usage of cache for read/write is allowed */
size_t 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; */
ulong age_threshold; /* age threshold for hot blocks */
ulonglong keycache_time; /* total number of block link operations */
uint hash_entries; /* max number of entries in the hash table */
int hash_links; /* max number of hash links */
int hash_links_used; /* number of hash links currently used */
int disk_blocks; /* max number of blocks in the cache */
ulong blocks_used; /* maximum number of concurrently used blocks */
ulong blocks_unused; /* number of currently unused blocks */
ulong blocks_changed; /* number of currently dirty blocks */
ulong warm_blocks; /* number of blocks in warm sub-chain */
ulong cnt_for_resize_op; /* counter to block resize operation */
long blocks_available; /* number of blocks available in the LRU chain */
HASH_LINK **hash_root; /* arr. of entries into hash table buckets */
HASH_LINK *hash_link_root; /* memory for hash table links */
HASH_LINK *free_hash_list; /* list of free hash links */
BLOCK_LINK *free_block_list; /* list of free blocks */
BLOCK_LINK *block_root; /* memory for block links */
uchar HUGE_PTR *block_mem; /* memory for block buffers */
BLOCK_LINK *used_last; /* ptr to the last block of the LRU chain */
BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */
pthread_mutex_t cache_lock; /* to lock access to the cache structure */
KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */
/*
Waiting for a zero resize count. Using a queue for symmetry though
only one thread can wait here.
*/
KEYCACHE_WQUEUE waiting_for_resize_cnt;
KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */
KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */
BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/
BLOCK_LINK *file_blocks[CHANGED_BLOCKS_HASH]; /* hash for other file bl.*/
/*
The following variables are and variables used to hold parameters for
initializing the key cache.
*/
ulonglong param_buff_size; /* size the memory allocated for the cache */
ulong param_block_size; /* size of the blocks in the key cache */
ulong param_division_limit; /* min. percentage of warm blocks */
ulong param_age_threshold; /* determines when hot block is downgraded */
/* Statistics variables. These are reset in reset_key_cache_counters(). */
ulong global_blocks_changed; /* number of currently dirty blocks */
my_bool in_init; /* Set to 1 in MySQL during init/resize */
uint partitions; /* actual number of partitions */
size_t key_cache_mem_size; /* specified size of the cache memory */
ulong blocks_used; /* maximum number of concurrently used blocks */
ulong blocks_unused; /* number of currently unused blocks */
ulong global_blocks_changed; /* number of currently dirty blocks */
ulonglong global_cache_w_requests;/* number of write requests (write hits) */
ulonglong global_cache_write; /* number of writes from cache to files */
ulonglong global_cache_r_requests;/* number of read requests (read hits) */
ulonglong global_cache_read; /* number of reads from files to cache */
int blocks; /* max number of blocks in the cache */
my_bool in_init; /* Set to 1 in MySQL during init/resize */
} KEY_CACHE;
/* The default key cache */
extern KEY_CACHE dflt_key_cache_var, *dflt_key_cache;
extern int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
size_t use_mem, uint division_limit,
uint age_threshold);
uint age_threshold, uint partitions);
extern int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
size_t use_mem, uint division_limit,
uint age_threshold);
@ -122,12 +147,18 @@ extern int key_cache_insert(KEY_CACHE *keycache,
File file, my_off_t filepos, int level,
uchar *buff, uint length);
extern int key_cache_write(KEY_CACHE *keycache,
File file, my_off_t filepos, int level,
File file, void *file_extra,
my_off_t filepos, int level,
uchar *buff, uint length,
uint block_length,int force_write);
uint block_length, int force_write);
extern int flush_key_blocks(KEY_CACHE *keycache,
int file, enum flush_type type);
int file, void *file_extra,
enum flush_type type);
extern void end_key_cache(KEY_CACHE *keycache, my_bool cleanup);
extern void get_key_cache_statistics(KEY_CACHE *keycache,
uint partition_no,
KEY_CACHE_STATISTICS *key_cache_stats);
extern ulonglong get_key_cache_stat_value(KEY_CACHE *keycache, uint var_no);
/* Functions to handle multiple key caches */
extern my_bool multi_keycache_init(void);
@ -140,5 +171,11 @@ extern void multi_key_cache_change(KEY_CACHE *old_data,
KEY_CACHE *new_data);
extern int reset_key_cache_counters(const char *name,
KEY_CACHE *key_cache);
extern int repartition_key_cache(KEY_CACHE *keycache,
uint key_cache_block_size,
size_t use_mem,
uint division_limit,
uint age_threshold,
uint partitions);
C_MODE_END
#endif /* _keycache_h */

View file

@ -69,6 +69,7 @@ INNODB_LOCK_WAITS
INNODB_RSEG
INNODB_TABLE_STATS
INNODB_TRX
KEY_CACHES
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS

View file

@ -13,6 +13,7 @@ FILES
GLOBAL_STATUS
GLOBAL_VARIABLES
INDEX_STATISTICS
KEY_CACHES
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
@ -76,6 +77,7 @@ FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME
INDEX_STATISTICS TABLE_SCHEMA
KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
@ -139,6 +141,7 @@ FILES TABLE_SCHEMA
GLOBAL_STATUS VARIABLE_NAME
GLOBAL_VARIABLES VARIABLE_NAME
INDEX_STATISTICS TABLE_SCHEMA
KEY_CACHES KEY_CACHE_NAME
KEY_COLUMN_USAGE CONSTRAINT_SCHEMA
PARTITIONS TABLE_SCHEMA
PLUGINS PLUGIN_NAME
@ -221,6 +224,7 @@ INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
INNODB_RSEG information_schema.INNODB_RSEG 1
INNODB_TABLE_STATS information_schema.INNODB_TABLE_STATS 1
INNODB_TRX information_schema.INNODB_TRX 1
KEY_CACHES information_schema.KEY_CACHES 1
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
PARTITIONS information_schema.PARTITIONS 1
PBXT_STATISTICS information_schema.PBXT_STATISTICS 1
@ -259,6 +263,7 @@ Database: information_schema
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
@ -312,6 +317,7 @@ Database: INFORMATION_SCHEMA
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
@ -357,5 +363,5 @@ Wildcard: inf_rmation_schema
+--------------------+
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
table_schema count(*)
information_schema 48
information_schema 49
mysql 22

View file

@ -1,5 +1,7 @@
drop table if exists t1, t2, t3;
SET @save_key_buffer=@@key_buffer_size;
SET @save_key_buffer_size=@@key_buffer_size;
SET @save_key_cache_block_size=@@key_cache_block_size;
SET @save_key_cache_partitions=@@key_cache_partitions;
SELECT @@key_buffer_size, @@small.key_buffer_size;
@@key_buffer_size @@small.key_buffer_size
2097152 131072
@ -37,7 +39,7 @@ SELECT @@small.key_buffer_size;
SELECT @@medium.key_buffer_size;
@@medium.key_buffer_size
0
SET @@global.key_buffer_size=@save_key_buffer;
SET @@global.key_buffer_size=@save_key_buffer_size;
SELECT @@default.key_buffer_size;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'default.key_buffer_size' at line 1
SELECT @@skr.storage_engine="test";
@ -366,3 +368,537 @@ Variable_name Value
key_cache_block_size 1536
SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size;
DROP TABLE t1;
set global key_buffer_size=@save_key_buffer_size;
set global key_cache_block_size=@save_key_cache_block_size;
select @@key_buffer_size;
@@key_buffer_size
2097152
select @@key_cache_block_size;
@@key_cache_block_size
1024
select @@key_cache_partitions;
@@key_cache_partitions
0
create table t1 (
p int not null auto_increment primary key,
a char(10));
create table t2 (
p int not null auto_increment primary key,
i int, a char(10), key k1(i), key k2(a));
select @@key_cache_partitions;
@@key_cache_partitions
0
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
p a
1 qqqq
2 yyyy
select * from t2;
p i a
1 1 qqqq
2 1 pppp
3 1 yyyy
4 3 zzzz
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
show status like 'key_%';
Variable_name Value
Key_blocks_not_flushed 0
Key_blocks_unused KEY_BLOCKS_UNUSED
Key_blocks_used 4
Key_read_requests 22
Key_reads 0
Key_write_requests 26
Key_writes 6
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t2 where a='zzzz';
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 4 # 0 29 0 32 9
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t1;
delete from t2;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default NULL NULL 2097152 1024 4 # 0 29 0 32 9
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
set global key_cache_partitions=2;
select @@key_cache_partitions;
@@key_cache_partitions
2
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 1048576 1024 0 # 0 0 0 0 0
default 2 2 1048576 1024 0 # 0 0 0 0 0
default 2 NULL 2097152 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
p a
1 qqqq
2 yyyy
select * from t2;
p i a
1 1 qqqq
2 1 pppp
3 1 yyyy
4 3 zzzz
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
show status like 'key_%';
Variable_name Value
Key_blocks_not_flushed 0
Key_blocks_unused KEY_BLOCKS_UNUSED
Key_blocks_used 4
Key_read_requests 22
Key_reads 0
Key_write_requests 26
Key_writes 6
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 1048576 1024 3 # 0 10 0 13 4
default 2 2 1048576 1024 1 # 0 12 0 13 2
default 2 NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t1;
delete from t2;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 1048576 1024 3 # 0 10 0 13 4
default 2 2 1048576 1024 1 # 0 12 0 13 2
default 2 NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
set global key_cache_partitions=1;
select @@key_cache_partitions;
@@key_cache_partitions
1
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 1 1 2097152 1024 0 # 0 0 0 0 0
default 1 NULL 2097152 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
p a
1 qqqq
2 yyyy
select * from t2;
p i a
1 1 qqqq
2 1 pppp
3 1 yyyy
4 3 zzzz
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
show status like 'key_%';
Variable_name Value
Key_blocks_not_flushed 0
Key_blocks_unused KEY_BLOCKS_UNUSED
Key_blocks_used 4
Key_read_requests 22
Key_reads 0
Key_write_requests 26
Key_writes 6
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 1 1 2097152 1024 4 # 0 22 0 26 6
default 1 NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
delete from t1;
delete from t2;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 1 1 2097152 1024 4 # 0 22 0 26 6
default 1 NULL 2097152 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 1 0 2 1
flush tables;
flush status;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 1 1 2097152 1024 4 # 0 0 0 0 0
default 1 NULL 2097152 1024 4 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 0 0 0 0
set global key_buffer_size=32*1024;
select @@key_buffer_size;
@@key_buffer_size
32768
set global key_cache_partitions=2;
select @@key_cache_partitions;
@@key_cache_partitions
2
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 0 # 0 0 0 0 0
default 2 2 16384 1024 0 # 0 0 0 0 0
default 2 NULL 32768 1024 0 # 0 0 0 0 0
small NULL NULL 1048576 1024 1 # 0 0 0 0 0
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
p a
1 qqqq
2 yyyy
select * from t2;
p i a
1 1 qqqq
2 1 pppp
3 1 yyyy
4 3 zzzz
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 1 # 0 12 0 13 2
default 2 2 16384 1024 3 # 0 10 0 13 4
default 2 NULL 32768 1024 4 # 0 22 0 26 6
small NULL NULL 1048576 1024 1 # 0 0 0 0 0
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 1951 # 1976 43
default 2 2 16384 1024 # # 0 4782 # 1708 60
default 2 NULL 32768 1024 # # 0 6733 # 3684 103
small NULL NULL 1048576 1024 # # 0 0 # 0 0
select * from t1 where p between 1010 and 1020 ;
p a
select * from t2 where p between 1010 and 1020 ;
p i a
1010 2 pppp
1011 2 yyyy
1012 3 zzzz
1013 2 qqqq
1014 2 pppp
1015 2 yyyy
1016 3 zzzz
1017 2 qqqq
1018 2 pppp
1019 2 yyyy
1020 3 zzzz
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 1954 # 1976 43
default 2 2 16384 1024 # # 0 4796 # 1708 60
default 2 NULL 32768 1024 # # 0 6750 # 3684 103
small NULL NULL 1048576 1024 # # 0 0 # 0 0
flush tables;
flush status;
update t1 set a='zzzz' where a='qqqq';
update t2 set i=1 where i=2;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 940 10 939 10
default 2 2 16384 1024 # # 0 2136 8 613 8
default 2 NULL 32768 1024 # # 0 3076 18 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=256*1024;
select @@keycache1.key_buffer_size;
@@keycache1.key_buffer_size
262144
set global keycache1.key_cache_partitions=7;
select @@keycache1.key_cache_partitions;
@@keycache1.key_cache_partitions
7
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 940 10 939 10
default 2 2 16384 1024 # # 0 2136 8 613 8
default 2 NULL 32768 1024 # # 0 3076 18 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 1 37449 2048 # # 0 0 0 0 0
keycache1 7 2 37449 2048 # # 0 0 0 0 0
keycache1 7 3 37449 2048 # # 0 0 0 0 0
keycache1 7 4 37449 2048 # # 0 0 0 0 0
keycache1 7 5 37449 2048 # # 0 0 0 0 0
keycache1 7 6 37449 2048 # # 0 0 0 0 0
keycache1 7 7 37449 2048 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 0 0 0 0
select * from information_schema.key_caches where key_cache_name like "key%";
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
keycache1 7 1 37449 2048 0 # 0 0 0 0 0
keycache1 7 2 37449 2048 0 # 0 0 0 0 0
keycache1 7 3 37449 2048 0 # 0 0 0 0 0
keycache1 7 4 37449 2048 0 # 0 0 0 0 0
keycache1 7 5 37449 2048 0 # 0 0 0 0 0
keycache1 7 6 37449 2048 0 # 0 0 0 0 0
keycache1 7 7 37449 2048 0 # 0 0 0 0 0
keycache1 7 NULL 262143 2048 0 # 0 0 0 0 0
cache index t1 key (`primary`) in keycache1;
Table Op Msg_type Msg_text
test.t1 assign_to_keycache status OK
explain select p from t1 where p between 1010 and 1020;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 1 Using where; Using index
select p from t1 where p between 1010 and 1020;
p
explain select i from t2 where p between 1010 and 1020;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 28 Using where
select i from t2 where p between 1010 and 1020;
i
1
1
3
1
1
1
3
1
1
1
3
explain select count(*) from t1, t2 where t1.p = t2.i;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index k1 k1 5 NULL 1024 Using index
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.i 1 Using index
select count(*) from t1, t2 where t1.p = t2.i;
count(*)
256
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 1 37449 2048 # # 0 2 1 0 0
keycache1 7 2 37449 2048 # # 0 7 1 0 0
keycache1 7 3 37449 2048 # # 0 0 0 0 0
keycache1 7 4 37449 2048 # # 0 5 1 0 0
keycache1 7 5 37449 2048 # # 0 0 0 0 0
keycache1 7 6 37449 2048 # # 0 0 0 0 0
keycache1 7 7 37449 2048 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 14 3 0 0
select * from information_schema.key_caches where key_cache_name like "key%";
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
keycache1 7 1 37449 2048 1 # 0 2 1 0 0
keycache1 7 2 37449 2048 1 # 0 7 1 0 0
keycache1 7 3 37449 2048 0 # 0 0 0 0 0
keycache1 7 4 37449 2048 1 # 0 5 1 0 0
keycache1 7 5 37449 2048 0 # 0 0 0 0 0
keycache1 7 6 37449 2048 0 # 0 0 0 0 0
keycache1 7 7 37449 2048 0 # 0 0 0 0 0
keycache1 7 NULL 262143 2048 3 # 0 14 3 0 0
cache index t2 in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
update t2 set p=p+3000, i=2 where a='qqqq';
select * from information_schema.key_caches where key_cache_name like "key%";
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
keycache1 7 1 37449 2048 3 # 0 44 3 43 2
keycache1 7 2 37449 2048 4 # 0 61 4 51 1
keycache1 7 3 37449 2048 4 # 0 177 4 176 3
keycache1 7 4 37449 2048 4 # 0 122 4 119 3
keycache1 7 5 37449 2048 4 # 0 840 4 335 4
keycache1 7 6 37449 2048 3 # 0 627 3 133 3
keycache1 7 7 37449 2048 3 # 0 211 3 214 3
keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
set global keycache2.key_buffer_size=1024*1024;
cache index t2 in keycache2;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
insert into t2 values (2000, 3, 'yyyy');
select * from information_schema.key_caches where key_cache_name like "keycache2";
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
keycache2 NULL NULL 1048576 1024 0 # 0 0 0 0 0
select * from information_schema.key_caches where key_cache_name like "key%";
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
keycache1 7 1 37449 2048 3 # 0 44 3 43 2
keycache1 7 2 37449 2048 4 # 0 61 4 51 1
keycache1 7 3 37449 2048 4 # 0 177 4 176 3
keycache1 7 4 37449 2048 4 # 0 122 4 119 3
keycache1 7 5 37449 2048 4 # 0 840 4 335 4
keycache1 7 6 37449 2048 3 # 0 627 3 133 3
keycache1 7 7 37449 2048 3 # 0 211 3 214 3
keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
keycache2 NULL NULL 1048576 1024 0 # 0 0 0 0 0
cache index t2 in keycache1;
Table Op Msg_type Msg_text
test.t2 assign_to_keycache status OK
update t2 set p=p+5000 where a='zzzz';
select * from t2 where p between 1010 and 1020;
p i a
1010 1 pppp
1011 1 yyyy
1014 1 pppp
1015 1 yyyy
1018 1 pppp
1019 1 yyyy
explain select p from t2 where p between 1010 and 1020;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 7 Using where; Using index
select p from t2 where p between 1010 and 1020;
p
1010
1011
1014
1015
1018
1019
explain select i from t2 where a='yyyy' and i=3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref k1,k2 k1 5 const 188 Using where
select i from t2 where a='yyyy' and i=3;
i
3
explain select a from t2 where a='yyyy' and i=3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ref k1,k2 k1 5 const 188 Using where
select a from t2 where a='yyyy' and i=3 ;
a
yyyy
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 1 37449 2048 # # 0 85 6 68 3
keycache1 7 2 37449 2048 # # 0 122 6 102 2
keycache1 7 3 37449 2048 # # 0 271 8 254 6
keycache1 7 4 37449 2048 # # 0 179 6 170 4
keycache1 7 5 37449 2048 # # 0 1445 7 416 6
keycache1 7 6 37449 2048 # # 0 863 6 345 5
keycache1 7 7 37449 2048 # # 0 236 4 239 4
keycache1 7 NULL 262143 2048 # # 0 3201 43 1594 30
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 1 37449 2048 # # 0 1 1 1 1
keycache1 7 2 37449 2048 # # 0 1 1 0 0
keycache1 7 3 37449 2048 # # 0 0 0 0 0
keycache1 7 4 37449 2048 # # 0 1 1 1 1
keycache1 7 5 37449 2048 # # 0 1 1 0 0
keycache1 7 6 37449 2048 # # 0 2 2 1 1
keycache1 7 7 37449 2048 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 6 6 3 3
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=8*1024;
insert into t2 values (8000, 3, 'yyyy');
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 3 1 87381 8192 # # 0 1 1 1 1
keycache1 3 2 87381 8192 # # 0 3 2 1 1
keycache1 3 3 87381 8192 # # 0 2 2 1 1
keycache1 3 NULL 262143 8192 # # 0 6 5 3 3
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=64*1024;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=2*1024;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 3 1 21845 2048 # # 0 0 0 0 0
keycache1 3 2 21845 2048 # # 0 0 0 0 0
keycache1 3 3 21845 2048 # # 0 0 0 0 0
keycache1 3 NULL 65535 2048 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=8*1024;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=0;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=8*1024;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=0;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_buffer_size=128*1024;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 1 1 131072 8192 # # 0 0 0 0 0
keycache1 1 NULL 131072 8192 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
set global keycache1.key_cache_block_size=1024;
select * from information_schema.key_caches;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 1 16384 1024 # # 0 966 12 939 10
default 2 2 16384 1024 # # 0 2206 12 613 8
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 1 18724 1024 # # 0 0 0 0 0
keycache1 7 2 18724 1024 # # 0 0 0 0 0
keycache1 7 3 18724 1024 # # 0 0 0 0 0
keycache1 7 4 18724 1024 # # 0 0 0 0 0
keycache1 7 5 18724 1024 # # 0 0 0 0 0
keycache1 7 6 18724 1024 # # 0 0 0 0 0
keycache1 7 7 18724 1024 # # 0 0 0 0 0
keycache1 7 NULL 131068 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 0 0 0 0
drop table t1,t2;
set global keycache1.key_buffer_size=0;
set global keycache2.key_buffer_size=0;
set global key_buffer_size=@save_key_buffer_size;
set global key_cache_partitions=@save_key_cache_partitions;

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,13 @@
#
# Test of multiple key caches
# Test of multiple key caches, simple an partitioned
#
--disable_warnings
drop table if exists t1, t2, t3;
--enable_warnings
SET @save_key_buffer=@@key_buffer_size;
SET @save_key_buffer_size=@@key_buffer_size;
SET @save_key_cache_block_size=@@key_cache_block_size;
SET @save_key_cache_partitions=@@key_cache_partitions;
SELECT @@key_buffer_size, @@small.key_buffer_size;
@ -33,7 +35,7 @@ SELECT @@`default`.key_buffer_size;
SELECT @@small.key_buffer_size;
SELECT @@medium.key_buffer_size;
SET @@global.key_buffer_size=@save_key_buffer;
SET @@global.key_buffer_size=@save_key_buffer_size;
#
# Errors
@ -247,3 +249,263 @@ SET GLOBAL key_cache_block_size= @bug28478_key_cache_block_size;
DROP TABLE t1;
# End of 4.1 tests
#
# Test cases for partitioned key caches
#
# Test usage of the KEY_CACHE table from information schema
# for a simple key cache
set global key_buffer_size=@save_key_buffer_size;
set global key_cache_block_size=@save_key_cache_block_size;
select @@key_buffer_size;
select @@key_cache_block_size;
select @@key_cache_partitions;
create table t1 (
p int not null auto_increment primary key,
a char(10));
create table t2 (
p int not null auto_increment primary key,
i int, a char(10), key k1(i), key k2(a));
select @@key_cache_partitions;
--replace_column 7 #
select * from information_schema.key_caches;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
select * from t2;
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
--replace_column 7 #
select * from information_schema.key_caches;
delete from t2 where a='zzzz';
--replace_column 7 #
select * from information_schema.key_caches;
delete from t1;
delete from t2;
--replace_column 7 #
select * from information_schema.key_caches;
# For the key cache with 2 partitions execute the same sequence of
# statements as for the simple cache above.
# The statistical information on the number of i/o requests and
# the number of is expected to be the same.
set global key_cache_partitions=2;
select @@key_cache_partitions;
--replace_column 7 #
select * from information_schema.key_caches;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
select * from t2;
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
--replace_column 7 #
select * from information_schema.key_caches;
delete from t1;
delete from t2;
--replace_column 7 #
select * from information_schema.key_caches;
# Check that we can work with one partition with the same results
set global key_cache_partitions=1;
select @@key_cache_partitions;
--replace_column 7 #
select * from information_schema.key_caches;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
select * from t2;
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
--replace_result 1808 KEY_BLOCKS_UNUSED 1670 KEY_BLOCKS_UNUSED
show status like 'key_%';
--replace_column 7 #
select * from information_schema.key_caches;
delete from t1;
delete from t2;
--replace_column 7 #
select * from information_schema.key_caches;
flush tables; flush status;
--replace_column 7 #
select * from information_schema.key_caches;
# Switch back to 2 partitions
set global key_buffer_size=32*1024;
select @@key_buffer_size;
set global key_cache_partitions=2;
select @@key_cache_partitions;
--replace_column 7 #
select * from information_schema.key_caches;
insert into t1 values (1, 'qqqq'), (2, 'yyyy');
insert into t2 values (1, 1, 'qqqq'), (2, 1, 'pppp'),
(3, 1, 'yyyy'), (4, 3, 'zzzz');
select * from t1;
select * from t2;
update t1 set p=3 where p=1;
update t2 set i=2 where i=1;
--replace_column 7 #
select * from information_schema.key_caches;
# Add more rows to tables t1 and t2
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t1(a) select a from t1;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
insert into t2(i,a) select i,a from t2;
--replace_column 6 # 7 # 10 #
select * from information_schema.key_caches;
select * from t1 where p between 1010 and 1020 ;
select * from t2 where p between 1010 and 1020 ;
--replace_column 6 # 7 # 10 #
select * from information_schema.key_caches;
flush tables; flush status;
update t1 set a='zzzz' where a='qqqq';
update t2 set i=1 where i=2;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
# Now test how we can work with 7 partitions
set global keycache1.key_buffer_size=256*1024;
select @@keycache1.key_buffer_size;
set global keycache1.key_cache_partitions=7;
select @@keycache1.key_cache_partitions;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%";
cache index t1 key (`primary`) in keycache1;
explain select p from t1 where p between 1010 and 1020;
select p from t1 where p between 1010 and 1020;
explain select i from t2 where p between 1010 and 1020;
select i from t2 where p between 1010 and 1020;
explain select count(*) from t1, t2 where t1.p = t2.i;
select count(*) from t1, t2 where t1.p = t2.i;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%";
cache index t2 in keycache1;
update t2 set p=p+3000, i=2 where a='qqqq';
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%";
set global keycache2.key_buffer_size=1024*1024;
cache index t2 in keycache2;
insert into t2 values (2000, 3, 'yyyy');
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "keycache2";
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%";
cache index t2 in keycache1;
update t2 set p=p+5000 where a='zzzz';
select * from t2 where p between 1010 and 1020;
explain select p from t2 where p between 1010 and 1020;
select p from t2 where p between 1010 and 1020;
explain select i from t2 where a='yyyy' and i=3;
select i from t2 where a='yyyy' and i=3;
explain select a from t2 where a='yyyy' and i=3;
select a from t2 where a='yyyy' and i=3 ;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=8*1024;
insert into t2 values (8000, 3, 'yyyy');
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_buffer_size=64*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=2*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_buffer_size=0;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_buffer_size=0;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_buffer_size=128*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
set global keycache1.key_cache_block_size=1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches;
drop table t1,t2;
set global keycache1.key_buffer_size=0;
set global keycache2.key_buffer_size=0;
set global key_buffer_size=@save_key_buffer_size;
set global key_cache_partitions=@save_key_cache_partitions;
#End of 5.1 tests

View file

@ -0,0 +1 @@
--key_cache_partitions=7

View file

@ -0,0 +1,8 @@
#
# Run select.test partitioned default key cache (with 7 partitions)
# (see setting the number of partitions in select_pkecache-master.opt)
# The result is expected the same as for select.test
#
--source t/select.test

File diff suppressed because it is too large Load diff

View file

@ -3828,11 +3828,13 @@ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache)
uint tmp_block_size= (uint) key_cache->param_block_size;
uint division_limit= key_cache->param_division_limit;
uint age_threshold= key_cache->param_age_threshold;
uint partitions= key_cache->param_partitions;
pthread_mutex_unlock(&LOCK_global_system_variables);
DBUG_RETURN(!init_key_cache(key_cache,
tmp_block_size,
tmp_buff_size,
division_limit, age_threshold));
division_limit, age_threshold,
partitions));
}
DBUG_RETURN(0);
}
@ -3862,10 +3864,12 @@ int ha_resize_key_cache(KEY_CACHE *key_cache)
/**
Change parameters for key cache (like size)
Change parameters for key cache (like division_limit)
*/
int ha_change_key_cache_param(KEY_CACHE *key_cache)
{
DBUG_ENTER("ha_change_key_cache_param");
if (key_cache->key_cache_inited)
{
pthread_mutex_lock(&LOCK_global_system_variables);
@ -3874,9 +3878,35 @@ int ha_change_key_cache_param(KEY_CACHE *key_cache)
pthread_mutex_unlock(&LOCK_global_system_variables);
change_key_cache_param(key_cache, division_limit, age_threshold);
}
return 0;
DBUG_RETURN(0);
}
/**
Repartition key cache
*/
int ha_repartition_key_cache(KEY_CACHE *key_cache)
{
DBUG_ENTER("ha_repartition_key_cache");
if (key_cache->key_cache_inited)
{
pthread_mutex_lock(&LOCK_global_system_variables);
size_t tmp_buff_size= (size_t) key_cache->param_buff_size;
long tmp_block_size= (long) key_cache->param_block_size;
uint division_limit= key_cache->param_division_limit;
uint age_threshold= key_cache->param_age_threshold;
uint partitions= key_cache->param_partitions;
pthread_mutex_unlock(&LOCK_global_system_variables);
DBUG_RETURN(!repartition_key_cache(key_cache, tmp_block_size,
tmp_buff_size,
division_limit, age_threshold,
partitions));
}
DBUG_RETURN(0);
}
/**
Free memory allocated by a key cache.
*/

View file

@ -2188,6 +2188,7 @@ int ha_table_exists_in_engine(THD* thd, const char* db, const char* name);
extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache);
int ha_resize_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache_param(KEY_CACHE *key_cache);
int ha_repartition_key_cache(KEY_CACHE *key_cache);
int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache);
int ha_end_key_cache(KEY_CACHE *key_cache);

View file

@ -5825,6 +5825,7 @@ enum options_mysqld
OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE,
OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE,
OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD,
OPT_KEY_CACHE_PARTITIONS,
OPT_LONG_QUERY_TIME,
OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET,
OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE,
@ -6915,6 +6916,12 @@ log and this option does nothing anymore.",
(uchar**) 0,
0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
1, 100, 0, 1, 0},
{"key_cache_partitions", OPT_KEY_CACHE_PARTITIONS,
"The number of partitions in key cache",
(uchar**) &dflt_key_cache_var.param_partitions,
(uchar**) 0,
0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, DEFAULT_KEY_CACHE_PARTITIONS,
0, MAX_KEY_CACHE_PARTITIONS, 0, 1, 0},
{"log-slow-filter", OPT_LOG_SLOW_FILTER,
"Log only the queries that followed certain execution plan. Multiple flags allowed in a comma-separated string. [admin, filesort, filesort_on_disk, full_join, full_scan, query_cache, query_cache_miss, tmp_table, tmp_table_on_disk]. Sets log-slow-admin-command to ON",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, QPLAN_ALWAYS_SET, 0, 0},
@ -8837,6 +8844,7 @@ mysql_getopt_value(const char *keyname, uint key_length,
case OPT_KEY_CACHE_BLOCK_SIZE:
case OPT_KEY_CACHE_DIVISION_LIMIT:
case OPT_KEY_CACHE_AGE_THRESHOLD:
case OPT_KEY_CACHE_PARTITIONS:
{
KEY_CACHE *key_cache;
if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
@ -8854,6 +8862,8 @@ mysql_getopt_value(const char *keyname, uint key_length,
return (uchar**) &key_cache->param_division_limit;
case OPT_KEY_CACHE_AGE_THRESHOLD:
return (uchar**) &key_cache->param_age_threshold;
case OPT_KEY_CACHE_PARTITIONS:
return (uchar**) &key_cache->param_partitions;
}
}
}

View file

@ -317,15 +317,18 @@ static sys_var_thd_ulong sys_interactive_timeout(&vars, "interactive_timeout",
static sys_var_thd_ulong sys_join_buffer_size(&vars, "join_buffer_size",
&SV::join_buff_size);
static sys_var_key_buffer_size sys_key_buffer_size(&vars, "key_buffer_size");
static sys_var_key_cache_long sys_key_cache_block_size(&vars, "key_cache_block_size",
offsetof(KEY_CACHE,
param_block_size));
static sys_var_key_cache_long sys_key_cache_division_limit(&vars, "key_cache_division_limit",
offsetof(KEY_CACHE,
param_division_limit));
static sys_var_key_cache_long sys_key_cache_age_threshold(&vars, "key_cache_age_threshold",
offsetof(KEY_CACHE,
param_age_threshold));
static sys_var_key_cache_long sys_key_cache_block_size(&vars,
"key_cache_block_size",
offsetof(KEY_CACHE,param_block_size));
static sys_var_key_cache_long sys_key_cache_division_limit(&vars,
"key_cache_division_limit",
offsetof(KEY_CACHE, param_division_limit));
static sys_var_key_cache_long sys_key_cache_age_threshold(&vars,
"key_cache_age_threshold",
offsetof(KEY_CACHE, param_age_threshold));
static sys_var_key_cache_long sys_key_cache_partitions(&vars,
"key_cache_partitions",
offsetof(KEY_CACHE, param_partitions));
static sys_var_const sys_language(&vars, "language",
OPT_GLOBAL, SHOW_CHAR,
(uchar*) language);
@ -2540,7 +2543,21 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var)
pthread_mutex_unlock(&LOCK_global_system_variables);
error= (bool) (ha_resize_key_cache(key_cache));
switch (offset) {
case offsetof(KEY_CACHE, param_block_size):
error= (bool) (ha_resize_key_cache(key_cache));
break;
case offsetof(KEY_CACHE, param_division_limit):
case offsetof(KEY_CACHE, param_age_threshold):
error= (bool) (ha_change_key_cache_param(key_cache));
break;
case offsetof(KEY_CACHE, param_partitions):
error= (bool) (ha_repartition_key_cache(key_cache));
break;
}
pthread_mutex_lock(&LOCK_global_system_variables);
key_cache->in_init= 0;
@ -4142,6 +4159,7 @@ static KEY_CACHE *create_key_cache(const char *name, uint length)
key_cache->param_block_size= dflt_key_cache_var.param_block_size;
key_cache->param_division_limit= dflt_key_cache_var.param_division_limit;
key_cache->param_age_threshold= dflt_key_cache_var.param_age_threshold;
key_cache->param_partitions= dflt_key_cache_var.param_partitions;
}
}
DBUG_RETURN(key_cache);

View file

@ -1427,6 +1427,7 @@ public:
my_free((uchar*) name, MYF(0));
}
friend bool process_key_caches(process_key_cache_t func);
friend int fill_key_cache_tables(THD *thd, TABLE_LIST *tables, COND *cond);
friend void delete_elements(I_List<NAMED_LIST> *list,
void (*free_element)(const char*, uchar*));
};

View file

@ -2220,6 +2220,31 @@ void remove_status_vars(SHOW_VAR *list)
}
static void update_key_cache_stat_var(KEY_CACHE *key_cache, size_t ofs)
{
uint var_no;
switch (ofs) {
case offsetof(KEY_CACHE, blocks_used):
case offsetof(KEY_CACHE, blocks_unused):
case offsetof(KEY_CACHE, global_blocks_changed):
var_no= (ofs-offsetof(KEY_CACHE, blocks_used))/sizeof(ulong);
*(ulong *)((char *) key_cache + ofs)=
(ulong) get_key_cache_stat_value(key_cache, var_no);
break;
case offsetof(KEY_CACHE, global_cache_r_requests):
case offsetof(KEY_CACHE, global_cache_read):
case offsetof(KEY_CACHE, global_cache_w_requests):
case offsetof(KEY_CACHE, global_cache_write):
var_no= 3+(ofs-offsetof(KEY_CACHE, global_cache_w_requests))/
sizeof(ulonglong);
*(ulonglong *)((char *) key_cache + ofs)=
get_key_cache_stat_value(key_cache, var_no);
break;
}
}
static bool show_status_array(THD *thd, const char *wild,
SHOW_VAR *variables,
enum enum_var_type value_type,
@ -2352,10 +2377,12 @@ static bool show_status_array(THD *thd, const char *wild,
break;
}
case SHOW_KEY_CACHE_LONG:
update_key_cache_stat_var(dflt_key_cache, (size_t) value);
value= (char*) dflt_key_cache + (ulong)value;
end= int10_to_str(*(long*) value, buff, 10);
break;
case SHOW_KEY_CACHE_LONGLONG:
update_key_cache_stat_var(dflt_key_cache, (size_t) value);
value= (char*) dflt_key_cache + (ulong)value;
end= longlong10_to_str(*(longlong*) value, buff, 10);
break;
@ -6611,6 +6638,90 @@ int fill_schema_files(THD *thd, TABLE_LIST *tables, COND *cond)
}
static
int store_key_cache_table_record(THD *thd, TABLE *table,
const char *name, uint name_length,
KEY_CACHE *key_cache,
uint partitions, uint partition_no)
{
KEY_CACHE_STATISTICS key_cache_stats;
uint err;
DBUG_ENTER("store_key_cache_table_record");
get_key_cache_statistics(key_cache, partition_no, &key_cache_stats);
if (key_cache_stats.mem_size == 0)
DBUG_RETURN(0);
restore_record(table, s->default_values);
table->field[0]->store(name, name_length, system_charset_info);
if (partitions == 0)
table->field[1]->set_null();
else
{
table->field[1]->set_notnull();
table->field[1]->store((long) partitions, TRUE);
}
if (partition_no == 0)
table->field[2]->set_null();
else
{
table->field[2]->set_notnull();
table->field[2]->store((long) partition_no, TRUE);
}
table->field[3]->store(key_cache_stats.mem_size, TRUE);
table->field[4]->store(key_cache_stats.block_size, TRUE);
table->field[5]->store(key_cache_stats.blocks_used, TRUE);
table->field[6]->store(key_cache_stats.blocks_unused, TRUE);
table->field[7]->store(key_cache_stats.blocks_changed, TRUE);
table->field[8]->store(key_cache_stats.read_requests, TRUE);
table->field[9]->store(key_cache_stats.reads, TRUE);
table->field[10]->store(key_cache_stats.write_requests, TRUE);
table->field[11]->store(key_cache_stats.writes, TRUE);
err= schema_table_store_record(thd, table);
DBUG_RETURN(err);
}
int fill_key_cache_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
TABLE *table= tables->table;
I_List_iterator<NAMED_LIST> it(key_caches);
NAMED_LIST *element;
DBUG_ENTER("fill_key_cache_tables");
while ((element= it++))
{
KEY_CACHE *key_cache= (KEY_CACHE *) element->data;
if (!key_cache->key_cache_inited)
continue;
uint partitions= key_cache->partitions;
DBUG_ASSERT(partitions <= MAX_KEY_CACHE_PARTITIONS);
if (partitions)
{
for (uint i= 0; i < partitions; i++)
{
if (store_key_cache_table_record(thd, table,
element->name, element->name_length,
key_cache, partitions, i+1))
DBUG_RETURN(1);
}
}
if (store_key_cache_table_record(thd, table,
element->name, element->name_length,
key_cache, partitions, 0))
DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
ST_FIELD_INFO schema_fields_info[]=
{
{"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE},
@ -7188,6 +7299,35 @@ ST_FIELD_INFO referential_constraints_fields_info[]=
};
ST_FIELD_INFO keycache_fields_info[]=
{
{"KEY_CACHE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE},
{"PARTITIONS", 3, MYSQL_TYPE_LONG, 0,
(MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED) , 0, SKIP_OPEN_TABLE},
{"PARTITION_NUMBER", 3, MYSQL_TYPE_LONG, 0,
(MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
{"FULL_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE},
{"BLOCK_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), 0, SKIP_OPEN_TABLE },
{"USED_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_blocks_used", SKIP_OPEN_TABLE},
{"UNUSED_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_blocks_unused", SKIP_OPEN_TABLE},
{"DIRTY_BLOCKS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_blocks_not_flushed", SKIP_OPEN_TABLE},
{"READ_REQUESTS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_read_requests", SKIP_OPEN_TABLE},
{"READS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_reads", SKIP_OPEN_TABLE},
{"WRITE_REQUESTS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_write_requests", SKIP_OPEN_TABLE},
{"WRITES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_UNSIGNED), "Key_writes", SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
/*
Description of ST_FIELD_INFO in table.h
@ -7227,6 +7367,8 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_variables, make_old_format, 0, 0, -1, 0, 0},
{"INDEX_STATISTICS", index_stats_fields_info, create_schema_table,
fill_schema_index_stats, make_old_format, 0, -1, -1, 0, 0},
{"KEY_CACHES", keycache_fields_info, create_schema_table,
fill_key_cache_tables, make_old_format, 0, -1,-1, 0, 0},
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
OPEN_TABLE_ONLY},

View file

@ -435,7 +435,8 @@ static int print_key_cache_status(const char *name, KEY_CACHE *key_cache)
Buffer_size: %10lu\n\
Block_size: %10lu\n\
Division_limit: %10lu\n\
Age_limit: %10lu\n\
Age_threshold: %10lu\n\
Partitions: %10lu\n\
blocks used: %10lu\n\
not flushed: %10lu\n\
w_requests: %10s\n\
@ -445,6 +446,7 @@ reads: %10s\n\n",
name,
(ulong) key_cache->param_buff_size, key_cache->param_block_size,
key_cache->param_division_limit, key_cache->param_age_threshold,
key_cache->param_partitions,
key_cache->blocks_used,key_cache->global_blocks_changed,
llstr(key_cache->global_cache_w_requests,llbuff1),
llstr(key_cache->global_cache_write,llbuff2),

View file

@ -953,6 +953,7 @@ enum enum_schema_tables
SCH_GLOBAL_STATUS,
SCH_GLOBAL_VARIABLES,
SCH_INDEX_STATS,
SCH_KEY_CACHES,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
SCH_PARTITIONS,

View file

@ -332,7 +332,8 @@ int chk_size(HA_CHECK *param, register MI_INFO *info)
/* The following is needed if called externally (not from myisamchk) */
flush_key_blocks(info->s->key_cache,
info->s->kfile, FLUSH_FORCE_WRITE);
info->s->kfile, &info->s->dirty_part_map,
FLUSH_FORCE_WRITE);
size= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
if ((skr=(my_off_t) info->state->key_file_length) != size)
@ -1474,6 +1475,7 @@ static int mi_drop_all_indexes(HA_CHECK *param, MI_INFO *info, my_bool force)
*/
DBUG_PRINT("repair", ("all disabled are empty: create missing"));
error= flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
FLUSH_FORCE_WRITE);
goto end;
}
@ -1488,6 +1490,7 @@ static int mi_drop_all_indexes(HA_CHECK *param, MI_INFO *info, my_bool force)
/* Remove all key blocks of this index file from key cache. */
if ((error= flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
FLUSH_IGNORE_CHANGED)))
goto end; /* purecov: inspected */
@ -1549,7 +1552,7 @@ int mi_repair(HA_CHECK *param, register MI_INFO *info,
if (!param->using_global_keycache)
VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size,
(size_t) param->use_buffers, 0, 0));
(size_t) param->use_buffers, 0, 0, 0));
if (init_io_cache(&param->read_cache,info->dfile,
(uint) param->read_buffer_length,
@ -1762,7 +1765,8 @@ err:
VOID(end_io_cache(&param->read_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
VOID(end_io_cache(&info->rec_cache));
got_error|=flush_blocks(param, share->key_cache, share->kfile);
got_error|=flush_blocks(param, share->key_cache, share->kfile,
&share->dirty_part_map);
if (!got_error && param->testflag & T_UNPACK)
{
share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
@ -1908,9 +1912,10 @@ void lock_memory(HA_CHECK *param __attribute__((unused)))
/* Flush all changed blocks to disk */
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file)
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
ulonglong *dirty_part_map)
{
if (flush_key_blocks(key_cache, file, FLUSH_RELEASE))
if (flush_key_blocks(key_cache, file, dirty_part_map, FLUSH_RELEASE))
{
mi_check_print_error(param,"%d when trying to write bufferts",my_errno);
return(1);
@ -1977,7 +1982,8 @@ int mi_sort_index(HA_CHECK *param, register MI_INFO *info, char * name)
}
/* Flush key cache for this file if we are calling this outside myisamchk */
flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_IGNORE_CHANGED);
share->state.version=(ulong) time((time_t*) 0);
old_state= share->state; /* save state if not stored */
@ -2535,7 +2541,8 @@ int mi_repair_by_sort(HA_CHECK *param, register MI_INFO *info,
memcpy( &share->state.state, info->state, sizeof(*info->state));
err:
got_error|= flush_blocks(param, share->key_cache, share->kfile);
got_error|= flush_blocks(param, share->key_cache, share->kfile,
&share->dirty_part_map);
VOID(end_io_cache(&info->rec_cache));
if (!got_error)
{
@ -3059,7 +3066,8 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
memcpy(&share->state.state, info->state, sizeof(*info->state));
err:
got_error|= flush_blocks(param, share->key_cache, share->kfile);
got_error|= flush_blocks(param, share->key_cache, share->kfile,
&share->dirty_part_map);
/*
Destroy the write cache. The master thread did already detach from
the share by remove_io_thread() or it was not yet started (if the

View file

@ -64,6 +64,7 @@ int mi_close(register MI_INFO *info)
if (share->kfile >= 0) abort(););
if (share->kfile >= 0 &&
flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
((share->temporary || share->deleting) ?
FLUSH_IGNORE_CHANGED :
FLUSH_RELEASE)))

View file

@ -52,7 +52,8 @@ int mi_delete_all_rows(MI_INFO *info)
If we are using delayed keys or if the user has done changes to the tables
since it was locked then there may be key blocks in the key cache
*/
flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED);
flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_IGNORE_CHANGED);
#ifdef HAVE_MMAP
if (share->file_map)
_mi_unmap_file(info);

View file

@ -268,6 +268,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
pthread_mutex_lock(&share->intern_lock);
/* Flush pages that we don't need anymore */
if (flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map,
(function == HA_EXTRA_PREPARE_FOR_DROP ?
FLUSH_IGNORE_CHANGED : FLUSH_RELEASE)))
{
@ -326,7 +327,8 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
break;
case HA_EXTRA_FLUSH:
if (!share->temporary)
flush_key_blocks(share->key_cache, share->kfile, FLUSH_KEEP);
flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_KEEP);
#ifdef HAVE_PWRITE
_mi_decrement_open_count(info);
#endif

View file

@ -75,7 +75,8 @@ int mi_assign_to_key_cache(MI_INFO *info,
in the old key cache.
*/
if (flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE))
if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_RELEASE))
{
error= my_errno;
mi_print_error(info->s, HA_ERR_CRASHED);
@ -90,7 +91,8 @@ int mi_assign_to_key_cache(MI_INFO *info,
(This can never fail as there is never any not written data in the
new key cache)
*/
(void) flush_key_blocks(key_cache, share->kfile, FLUSH_RELEASE);
(void) flush_key_blocks(key_cache, share->kfile, &share->dirty_part_map,
FLUSH_RELEASE);
/*
ensure that setting the key cache and changing the multi_key_cache
@ -102,6 +104,7 @@ int mi_assign_to_key_cache(MI_INFO *info,
This should be seen at the lastes for the next call to an myisam function.
*/
share->key_cache= key_cache;
share->dirty_part_map= 0;
/* store the key cache in the global hash structure for future opens */
if (multi_key_cache_set((uchar*) share->unique_file_name,

View file

@ -68,7 +68,9 @@ int mi_lock_database(MI_INFO *info, int lock_type)
--share->tot_locks;
if (info->lock_type == F_WRLCK && !share->w_locks &&
!share->delay_key_write && flush_key_blocks(share->key_cache,
share->kfile,FLUSH_KEEP))
share->kfile,
&share->dirty_part_map,
FLUSH_KEEP))
{
error=my_errno;
mi_print_error(info->s, HA_ERR_CRASHED);
@ -513,7 +515,8 @@ int _mi_test_if_changed(register MI_INFO *info)
{ /* Keyfile has changed */
DBUG_PRINT("info",("index file changed"));
if (share->state.process != share->this_process)
VOID(flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE));
VOID(flush_key_blocks(share->key_cache, share->kfile,
&share->dirty_part_map, FLUSH_RELEASE));
share->last_process=share->state.process;
info->last_unique= share->state.unique;
info->last_loop= share->state.update_count;

View file

@ -94,10 +94,11 @@ int _mi_write_keypage(register MI_INFO *info, register MI_KEYDEF *keyinfo,
}
#endif
DBUG_RETURN((key_cache_write(info->s->key_cache,
info->s->kfile,page, level, (uchar*) buff,length,
(uint) keyinfo->block_length,
(int) ((info->lock_type != F_UNLCK) ||
info->s->delay_key_write))));
info->s->kfile, &info->s->dirty_part_map,
page, level, (uchar*) buff, length,
(uint) keyinfo->block_length,
(int) ((info->lock_type != F_UNLCK) ||
info->s->delay_key_write))));
} /* mi_write_keypage */
@ -116,7 +117,8 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos,
mi_sizestore(buff,old_link);
info->s->state.changed|= STATE_NOT_SORTED_PAGES;
DBUG_RETURN(key_cache_write(info->s->key_cache,
info->s->kfile, pos , level, buff,
info->s->kfile, &info->s->dirty_part_map,
pos , level, buff,
sizeof(buff),
(uint) keyinfo->block_length,
(int) (info->lock_type != F_UNLCK)));

View file

@ -47,7 +47,8 @@ int mi_panic(enum ha_panic_function flag)
if (info->s->options & HA_OPTION_READ_ONLY_DATA)
break;
#endif
if (flush_key_blocks(info->s->key_cache, info->s->kfile, FLUSH_RELEASE))
if (flush_key_blocks(info->s->key_cache, info->s->kfile,
&info->s->dirty_part_map, FLUSH_RELEASE))
error=my_errno;
if (info->opt_flag & WRITE_CACHE_USED)
if (flush_io_cache(&info->rec_cache))

View file

@ -65,7 +65,7 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
}
}
else
block_length= share->key_cache->key_cache_block_size;
block_length= share->key_cache->param_block_size;
length= info->preload_buff_size/block_length * block_length;
set_if_bigger(length, block_length);
@ -73,7 +73,8 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM);
if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_RELEASE))
if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_RELEASE))
goto err;
do

View file

@ -49,7 +49,8 @@ int main(int argc,char *argv[])
MY_INIT(argv[0]);
my_init();
if (key_cacheing)
init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0,0);
init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,IO_SIZE*16,0,0,
DEFAULT_KEY_CACHE_PARTITIONS);
get_options(argc,argv);
exit(run_test("test1"));

View file

@ -215,7 +215,8 @@ int main(int argc, char *argv[])
if (!silent)
printf("- Writing key:s\n");
if (key_cacheing)
init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0);
init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0,
DEFAULT_KEY_CACHE_PARTITIONS);
if (do_locking)
mi_lock_database(file,F_WRLCK);
if (write_cacheing)

View file

@ -177,7 +177,8 @@ void start_test(int id)
exit(1);
}
if (key_cacheing && rnd(2) == 0)
init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0);
init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0,
DEFAULT_KEY_CACHE_PARTITIONS);
printf("Process %d, pid: %ld\n", id, (long) getpid());
fflush(stdout);

View file

@ -83,7 +83,7 @@ int main(int argc,char *argv[])
usage();
}
init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0);
init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0, 0);
if (!(info=mi_open(argv[0], O_RDONLY,
HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER)))

View file

@ -1102,7 +1102,7 @@ static int myisamchk(HA_CHECK *param, char * filename)
{
if (param->testflag & (T_EXTEND | T_MEDIUM))
VOID(init_key_cache(dflt_key_cache,opt_key_cache_block_size,
(size_t) param->use_buffers, 0, 0));
(size_t) param->use_buffers, 0, 0, 0));
VOID(init_io_cache(&param->read_cache,datafile,
(uint) param->read_buffer_length,
READ_CACHE,
@ -1116,7 +1116,8 @@ static int myisamchk(HA_CHECK *param, char * filename)
HA_OPTION_COMPRESS_RECORD)) ||
(param->testflag & (T_EXTEND | T_MEDIUM)))
error|=chk_data_link(param, info, test(param->testflag & T_EXTEND));
error|=flush_blocks(param, share->key_cache, share->kfile);
error|=flush_blocks(param, share->key_cache, share->kfile,
&share->dirty_part_map);
VOID(end_io_cache(&param->read_cache));
}
if (!error)
@ -1526,7 +1527,7 @@ static int mi_sort_records(HA_CHECK *param,
DBUG_RETURN(0); /* Nothing to do */
init_key_cache(dflt_key_cache, opt_key_cache_block_size,
(size_t) param->use_buffers, 0, 0);
(size_t) param->use_buffers, 0, 0, 0);
if (init_io_cache(&info->rec_cache,-1,(uint) param->write_buffer_length,
WRITE_CACHE,share->pack.header_length,1,
MYF(MY_WME | MY_WAIT_IF_FULL)))
@ -1641,8 +1642,8 @@ err:
my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
sort_info.buff=0;
share->state.sortkey=sort_key;
DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile) |
got_error);
DBUG_RETURN(flush_blocks(param, share->key_cache, share->kfile,
&share->dirty_part_map) | got_error);
} /* sort_records */

View file

@ -174,6 +174,8 @@ typedef struct st_mi_isam_share
*index_file_name;
uchar *file_map; /* mem-map of file if possible */
KEY_CACHE *key_cache; /* ref to the current key cache */
/* To mark the key cache partitions containing dirty pages for this file */
ulonglong dirty_part_map;
MI_DECODE_TREE *decode_trees;
uint16 *decode_tables;
/* Function to use for a row checksum. */
@ -733,7 +735,8 @@ void mi_check_print_info _VARARGS((HA_CHECK *param, const char *fmt, ...));
#ifdef THREAD
pthread_handler_t thr_find_all_keys(void *arg);
#endif
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file);
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
ulonglong *dirty_part_map);
#ifdef __cplusplus
}
#endif

View file

@ -333,7 +333,7 @@ static int examine_log(char * file_name, char **table_names)
init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
(tree_element_free) file_info_free, NULL);
VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
0, 0));
0, 0, 0));
files_open=0; access_time=0;
while (access_time++ != number_of_commands &&