Commit be129162 authored by Igor Babaev's avatar Igor Babaev

Merge of the code for partitioned key cache (mwl#85) into 5.2.

parents fedbda3f a37899a8
......@@ -19,96 +19,156 @@
#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
{
struct st_my_thread_var *last_thread; /* circular list of waiting threads */
} 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 CHANGED_BLOCKS_HASH 128 /* must be power of 2 */
#define DEFAULT_KEY_CACHE_PARTITIONS 0
/*
The key cache structure
It also contains read-only statistics parameters.
MAX_KEY_CACHE_PARTITIONS cannot be greater than
sizeof(MYISAM_SHARE::dirty_part_map)
Currently sizeof(MYISAM_SHARE::dirty_part_map)=sizeof(ulonglong)
*/
typedef struct st_key_cache
#define MAX_KEY_CACHE_PARTITIONS 64
/* The structure to get statistical data about a key cache */
typedef struct st_key_cache_statistics
{
my_bool key_cache_inited;
my_bool in_resize; /* true during resize operation */
my_bool resize_in_flush; /* true during flush of resize operation */
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 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;
#define NUM_LONG_KEY_CACHE_STAT_VARIABLES 3
/* The type of a key cache object */
typedef enum key_cache_type
{
SIMPLE_KEY_CACHE,
PARTITIONED_KEY_CACHE
} KEY_CACHE_TYPE;
typedef
int (*INIT_KEY_CACHE)
(void *, uint key_cache_block_size,
size_t use_mem, uint division_limit, uint age_threshold);
typedef
int (*RESIZE_KEY_CACHE)
(void *, uint key_cache_block_size,
size_t use_mem, uint division_limit, uint age_threshold);
typedef
void (*CHANGE_KEY_CACHE_PARAM)
(void *keycache_cb,
uint division_limit, uint age_threshold);
typedef
uchar* (*KEY_CACHE_READ)
(void *keycache_cb,
File file, my_off_t filepos, int level,
uchar *buff, uint length,
uint block_length, int return_buffer);
typedef
int (*KEY_CACHE_INSERT)
(void *keycache_cb,
File file, my_off_t filepos, int level,
uchar *buff, uint length);
typedef
int (*KEY_CACHE_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);
typedef
int (*FLUSH_KEY_BLOCKS)
(void *keycache_cb,
int file, void *file_extra,
enum flush_type type);
typedef
int (*RESET_KEY_CACHE_COUNTERS)
(const char *name, void *keycache_cb);
typedef
void (*END_KEY_CACHE)
(void *keycache_cb, my_bool cleanup);
typedef
void (*GET_KEY_CACHE_STATISTICS)
(void *keycache_cb, uint partition_no,
KEY_CACHE_STATISTICS *key_cache_stats);
typedef
ulonglong (*GET_KEY_CACHE_STAT_VALUE)
(void *keycache_cb, uint var_no);
/*
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
{
INIT_KEY_CACHE init;
RESIZE_KEY_CACHE resize;
CHANGE_KEY_CACHE_PARAM change_param;
KEY_CACHE_READ read;
KEY_CACHE_INSERT insert;
KEY_CACHE_WRITE write;
FLUSH_KEY_BLOCKS flush;
RESET_KEY_CACHE_COUNTERS reset_counters;
END_KEY_CACHE end;
GET_KEY_CACHE_STATISTICS get_stats;
GET_KEY_CACHE_STAT_VALUE get_stat_val;
} KEY_CACHE_FUNCS;
typedef struct st_key_cache
{
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 */
/* Statistics variables. These are reset in reset_key_cache_counters(). */
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 */
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 +182,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 +206,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 */
......@@ -69,6 +69,7 @@ INNODB_LOCK_WAITS
INNODB_RSEG
INNODB_TABLE_STATS
INNODB_TRX
KEY_CACHES
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
......
......@@ -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
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,432 @@ 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 where partition_number is null;
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 where partition_number is null;
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 where partition_number is null;
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 where partition_number is null;
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3076 18 1552 18
small NULL NULL 1048576 1024 # # 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%"
and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 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%"
and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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%"
and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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"
and partition_number is null;
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 6 # 0 6 6 3 3
select * from information_schema.key_caches where key_cache_name like "key%"
and partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
keycache1 7 NULL 262143 2048 25 # 0 2082 25 1071 19
keycache2 NULL NULL 1048576 1024 6 # 0 6 6 3 3
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 where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 3201 43 1594 30
keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 NULL 262143 2048 # # 0 6 6 3 3
keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=8*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 3 NULL 262143 8192 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
insert into t2 values (8000, 3, 'yyyy');
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 3 NULL 262143 8192 # # 0 6 5 3 3
keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_buffer_size=64*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 6 6 3 3
set global keycache1.key_cache_block_size=2*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 3 NULL 65535 2048 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=8*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 6 6 3 3
set global keycache1.key_buffer_size=0;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 6 6 3 3
set global keycache1.key_cache_block_size=8*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 6 6 3 3
set global keycache1.key_buffer_size=0;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
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 6 6 3 3
set global keycache1.key_buffer_size=128*1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 1 NULL 131072 8192 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=1024;
select * from information_schema.key_caches where partition_number is null;
KEY_CACHE_NAME PARTITIONS PARTITION_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3172 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
keycache1 7 NULL 131068 1024 # # 0 0 0 0 0
keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
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;
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -230,6 +230,18 @@ NULL information_schema INNODB_TRX trx_started 3 0000-00-00 00:00:00 NO datetime
NULL information_schema INNODB_TRX trx_state 2 NO varchar 13 39 NULL NULL utf8 utf8_general_ci varchar(13) select
NULL information_schema INNODB_TRX trx_wait_started 5 NULL YES datetime NULL NULL NULL NULL NULL NULL datetime select
NULL information_schema INNODB_TRX trx_weight 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_CACHES BLOCK_SIZE 5 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_CACHES DIRTY_BLOCKS 8 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_CACHES FULL_SIZE 4 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_CACHES KEY_CACHE_NAME 1 NO varchar 192 576 NULL NULL utf8 utf8_general_ci varchar(192) select
NULL information_schema KEY_CACHES PARTITIONS 2 NULL YES int NULL NULL 10 0 NULL NULL int(3) unsigned select
NULL information_schema KEY_CACHES PARTITION_NUMBER 3 NULL YES int NULL NULL 10 0 NULL NULL int(3) unsigned select
NULL information_schema KEY_CACHES READS 10 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_CACHES READ_REQUESTS 9 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_CACHES UNUSED_BLOCKS 7 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_CACHES USED_BLOCKS 6 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_CACHES WRITES 12 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_CACHES WRITE_REQUESTS 11 0 NO bigint NULL NULL 19 0 NULL NULL bigint(21) unsigned select
NULL information_schema KEY_COLUMN_USAGE COLUMN_NAME 7 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
NULL information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG 1 NULL YES varchar 512 1536 NULL NULL utf8 utf8_general_ci varchar(512) select
NULL information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME 3 NO varchar 64 192 NULL NULL utf8 utf8_general_ci varchar(64) select
......@@ -743,6 +755,18 @@ NULL information_schema INNODB_TRX trx_wait_started datetime NULL NULL NULL NULL
NULL information_schema INNODB_TRX trx_weight bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema INNODB_TRX trx_mysql_thread_id bigint NULL NULL NULL NULL bigint(21) unsigned
3.0000 information_schema INNODB_TRX trx_query varchar 1024 3072 utf8 utf8_general_ci varchar(1024)
3.0000 information_schema KEY_CACHES KEY_CACHE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192)
NULL information_schema KEY_CACHES PARTITIONS int NULL NULL NULL NULL int(3) unsigned
NULL information_schema KEY_CACHES PARTITION_NUMBER int NULL NULL NULL NULL int(3) unsigned
NULL information_schema KEY_CACHES FULL_SIZE bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema KEY_CACHES BLOCK_SIZE bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema KEY_CACHES USED_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema KEY_CACHES UNUSED_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema KEY_CACHES DIRTY_BLOCKS bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema KEY_CACHES READ_REQUESTS bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema KEY_CACHES READS bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema KEY_CACHES WRITE_REQUESTS bigint NULL NULL NULL NULL bigint(21) unsigned
NULL information_schema KEY_CACHES WRITES bigint NULL NULL NULL NULL bigint(21) unsigned
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512)
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64)
3.0000 information_schema KEY_COLUMN_USAGE CONSTRAINT_NAME varchar 64 192 utf8 utf8_general_ci varchar(64)
......
......@@ -590,6 +590,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
TABLE_NAME KEY_CACHES
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
MAX_DATA_LENGTH #MDL#
INDEX_LENGTH #IL#
DATA_FREE #DF#
AUTO_INCREMENT NULL
CREATE_TIME #CRT#
UPDATE_TIME #UT#
CHECK_TIME #CT#
TABLE_COLLATION utf8_general_ci
CHECKSUM NULL
CREATE_OPTIONS #CO#
TABLE_COMMENT #TC#
user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
TABLE_NAME KEY_COLUMN_USAGE
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
......@@ -1688,6 +1711,29 @@ user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
TABLE_NAME KEY_CACHES
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
VERSION 10
ROW_FORMAT Fixed
TABLE_ROWS #TBLR#
AVG_ROW_LENGTH #ARL#
DATA_LENGTH #DL#
MAX_DATA_LENGTH #MDL#
INDEX_LENGTH #IL#
DATA_FREE #DF#
AUTO_INCREMENT NULL
CREATE_TIME #CRT#
UPDATE_TIME #UT#
CHECK_TIME #CT#
TABLE_COLLATION utf8_general_ci
CHECKSUM NULL
CREATE_OPTIONS #CO#
TABLE_COMMENT #TC#
user_comment
Separator -----------------------------------------------------
TABLE_CATALOG NULL
TABLE_SCHEMA information_schema
TABLE_NAME KEY_COLUMN_USAGE
TABLE_TYPE SYSTEM VIEW
ENGINE MEMORY
......
......@@ -91,6 +91,7 @@ Database: information_schema
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
......@@ -144,6 +145,7 @@ Database: INFORMATION_SCHEMA
| GLOBAL_STATUS |
| GLOBAL_VARIABLES |
| INDEX_STATISTICS |
| KEY_CACHES |
| KEY_COLUMN_USAGE |
| PARTITIONS |
| PLUGINS |
......
#
# 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,270 @@ 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 where partition_number is null;
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 where partition_number is null;
delete from t2 where a='zzzz';
--replace_column 7 #
select * from information_schema.key_caches where partition_number is null;
delete from t1;
delete from t2;
--replace_column 7 #
select * from information_schema.key_caches where partition_number is null;
# 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 where partition_number is null;
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 where partition_number is null;
delete from t1;
delete from t2;
--replace_column 7 #
select * from information_schema.key_caches where partition_number is null;
# 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 where partition_number is null;
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 where partition_number is null;
delete from t1;
delete from t2;
--replace_column 7 #
select * from information_schema.key_caches where partition_number is null;
flush tables; flush status;
--replace_column 7 #
select * from information_schema.key_caches where partition_number is null;
# 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 where partition_number is null;
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 where partition_number is null;
# 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 where partition_number is null;
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 where partition_number is null;
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 where partition_number is null;
# 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 where partition_number is null;
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%"
and partition_number is null;
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 where partition_number is null;
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%"
and partition_number is null;
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%"
and partition_number is null;
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"
and partition_number is null;
--replace_column 7 #
select * from information_schema.key_caches where key_cache_name like "key%"
and partition_number is null;
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 where partition_number is null;
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 where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
insert into t2 values (8000, 3, 'yyyy');
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=64*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=2*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=0;
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=8*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=0;
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_buffer_size=128*1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
set global keycache1.key_cache_block_size=1024;
--replace_column 6 # 7 #
select * from information_schema.key_caches where partition_number is null;
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
#
# 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
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -3826,11 +3826,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);
}
......@@ -3860,10 +3862,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);
......@@ -3872,9 +3876,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.
*/
......
......@@ -2201,6 +2201,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);
......
......@@ -5831,6 +5831,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,
......@@ -6928,6 +6929,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},
......@@ -8910,6 +8917,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)))
......@@ -8927,6 +8935,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;
}
}
}
......
......@@ -320,15 +320,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);
......@@ -2548,7 +2551,21 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var)
pthread_mutex_unlock(&LOCK_global_system_variables);
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;
......@@ -4156,6 +4173,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);
......
......@@ -1427,6 +1427,7 @@ class NAMED_LIST :public ilink
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*));
};
......
......@@ -2249,6 +2249,32 @@ 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= NUM_LONG_KEY_CACHE_STAT_VARIABLES +
(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,
......@@ -2381,10 +2407,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;
......@@ -6640,6 +6668,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 keycache_stats;
uint err;
DBUG_ENTER("store_key_cache_table_record");
get_key_cache_statistics(key_cache, partition_no, &keycache_stats);
if (!key_cache->key_cache_inited || keycache_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(keycache_stats.mem_size, TRUE);
table->field[4]->store(keycache_stats.block_size, TRUE);
table->field[5]->store(keycache_stats.blocks_used, TRUE);
table->field[6]->store(keycache_stats.blocks_unused, TRUE);
table->field[7]->store(keycache_stats.blocks_changed, TRUE);
table->field[8]->store(keycache_stats.read_requests, TRUE);
table->field[9]->store(keycache_stats.reads, TRUE);
table->field[10]->store(keycache_stats.write_requests, TRUE);
table->field[11]->store(keycache_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},
......@@ -7219,6 +7331,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
......@@ -7258,6 +7399,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},
......
......@@ -445,7 +445,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\
......@@ -455,6 +456,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),
......
......@@ -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,
......
......@@ -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 @@ int mi_repair(HA_CHECK *param, register MI_INFO *info,
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
......
......@@ -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)))
......
......@@ -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);
......
......@@ -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
......
......@@ -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,
......
......@@ -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;
......
......@@ -94,7 +94,8 @@ 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,
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))));
......@@ -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)));
......
......@@ -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))
......
......@@ -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
......
......@@ -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"));
......
......@@ -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)
......
......@@ -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);
......
......@@ -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)))
......
......@@ -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 @@ static int mi_sort_records(HA_CHECK *param,
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 */
......
......@@ -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. */
......@@ -732,7 +734,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
......@@ -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 &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment