diff options
author | Michael Widenius <monty@mariadb.org> | 2014-03-26 21:58:27 +0200 |
---|---|---|
committer | Michael Widenius <monty@mariadb.org> | 2014-03-26 21:58:27 +0200 |
commit | ded448d1d035d211c8146141546a08126bb728b6 (patch) | |
tree | 0ebba8935193517995519651885a34e46ff53515 | |
parent | 99316b51b6e78191eca303dc35ae5a204f8b5c4f (diff) | |
download | mariadb-git-ded448d1d035d211c8146141546a08126bb728b6.tar.gz |
MDEV-5905: Creating tmp. memory table kills the server
The reason was that a couple of variables that hold number of rows that was used to calculate buffers was uint and caused an overflow.
Fixed by changing variables that could hold number of rows from uint to ulong and also added a cast for this test.
include/heap.h:
Reorder to get better alignment. Changed variables that could hold number of rows from uint to ulong
mysql-test/suite/heap/heap.result:
Added test case
mysql-test/suite/heap/heap.test:
Added test case
mysql-test/suite/plugins/t/server_audit.test:
Added sleep as we want to have disconnect logged before we try a new connect
storage/heap/ha_heap.cc:
Changed variables that could hold number of rows from uint to ulong
Limit number of rows to 4G (as most of the variables that holds rows are ulong anyway)
reset records_changed when key_stat_version is changed to not cause increments for every row changed
storage/heap/ha_heap.h:
changed records_changed to ulong as this can get big
storage/heap/hp_create.c:
Changed variables that could hold number of rows from uint to ulong
Added cast (fixed the original bug)
storage/heap/hp_delete.c:
Changed variables that could hold number of rows from uint to ulong
storage/heap/hp_open.c:
Removed not needed cast
storage/heap/hp_write.c:
Changed variables that could hold number of rows from uint to ulong
support-files/compiler_warnings.supp:
Removed extra : from supression
-rw-r--r-- | include/heap.h | 16 | ||||
-rw-r--r-- | mysql-test/suite/heap/heap.result | 8 | ||||
-rw-r--r-- | mysql-test/suite/heap/heap.test | 15 | ||||
-rw-r--r-- | mysql-test/suite/plugins/t/server_audit.test | 1 | ||||
-rw-r--r-- | storage/heap/ha_heap.cc | 9 | ||||
-rw-r--r-- | storage/heap/ha_heap.h | 2 | ||||
-rw-r--r-- | storage/heap/hp_create.c | 4 | ||||
-rw-r--r-- | storage/heap/hp_delete.c | 2 | ||||
-rw-r--r-- | storage/heap/hp_open.c | 4 | ||||
-rw-r--r-- | storage/heap/hp_write.c | 2 | ||||
-rw-r--r-- | support-files/compiler_warnings.supp | 2 |
11 files changed, 46 insertions, 19 deletions
diff --git a/include/heap.h b/include/heap.h index 10b165d89c6..2b7fd28699d 100644 --- a/include/heap.h +++ b/include/heap.h @@ -102,8 +102,8 @@ typedef struct st_heap_block HP_PTRS *root; /* Top-level block */ struct st_level_info level_info[HP_MAX_LEVELS+1]; uint levels; /* number of used levels */ - uint records_in_block; /* Records in one heap-block */ uint recbuffer; /* Length of one saved record */ + ulong records_in_block; /* Records in one heap-block */ ulong last_allocated; /* number of records there is allocated space for */ } HP_BLOCK; @@ -134,14 +134,15 @@ typedef struct st_heap_share { HP_BLOCK block; HP_KEYDEF *keydef; - ulong min_records,max_records; /* Params to open */ ulonglong data_length,index_length,max_table_size; + ulonglong auto_increment; + ulong min_records,max_records; /* Params to open */ + ulong records; /* records */ + ulong blength; /* records rounded up to 2^n */ + ulong deleted; /* Deleted records in database */ uint key_stat_version; /* version to indicate insert/delete */ uint key_version; /* Updated on key change */ uint file_version; /* Update on clear */ - uint records; /* records */ - uint blength; /* records rounded up to 2^n */ - uint deleted; /* Deleted records in database */ uint reclength; /* Length of one record */ uint changed; uint keys,max_key_length; @@ -156,7 +157,6 @@ typedef struct st_heap_share LIST open_list; uint auto_key; uint auto_key_type; /* real type of the auto key segment */ - ulonglong auto_increment; } HP_SHARE; struct st_hp_hash_info; @@ -187,12 +187,12 @@ typedef struct st_heap_info typedef struct st_heap_create_info { HP_KEYDEF *keydef; - ulong max_records; - ulong min_records; uint auto_key; /* keynr [1 - maxkey] for auto key */ uint auto_key_type; uint keys; uint reclength; + ulong max_records; + ulong min_records; ulonglong max_table_size; ulonglong auto_increment; my_bool with_auto_increment; diff --git a/mysql-test/suite/heap/heap.result b/mysql-test/suite/heap/heap.result index e61b9bcc2bf..878b4aa7749 100644 --- a/mysql-test/suite/heap/heap.result +++ b/mysql-test/suite/heap/heap.result @@ -810,3 +810,11 @@ select data_length,index_length from information_schema.tables where table_schem data_length index_length 81024 121024 drop table t1; +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); +SET @@max_heap_table_size = 1024*1024*1024*20; +CREATE TEMPORARY TABLE tmp ENGINE=MEMORY +SELECT id FROM t1; +DROP TEMPORARY TABLE tmp; +drop table t1; diff --git a/mysql-test/suite/heap/heap.test b/mysql-test/suite/heap/heap.test index ab2a4f0a6d6..106ece540a4 100644 --- a/mysql-test/suite/heap/heap.test +++ b/mysql-test/suite/heap/heap.test @@ -563,3 +563,18 @@ insert into t1 select rand(100000000) from t1; --replace_result 40512 81024 60512 121024 select data_length,index_length from information_schema.tables where table_schema="test" and table_name="t1"; drop table t1; + +# +# MDEV-5905 Creating tmp. memory table kills the server +# + +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1); +INSERT INTO t1 VALUES (2); + +SET @@max_heap_table_size = 1024*1024*1024*20; + +CREATE TEMPORARY TABLE tmp ENGINE=MEMORY + SELECT id FROM t1; +DROP TEMPORARY TABLE tmp; +drop table t1; diff --git a/mysql-test/suite/plugins/t/server_audit.test b/mysql-test/suite/plugins/t/server_audit.test index f62980259c0..f63c8022392 100644 --- a/mysql-test/suite/plugins/t/server_audit.test +++ b/mysql-test/suite/plugins/t/server_audit.test @@ -14,6 +14,7 @@ set global server_audit_logging=on; connect (con1,localhost,root,,mysql); connection default; disconnect con1; +--sleep 2 --replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT --error ER_ACCESS_DENIED_ERROR connect (con1,localhost,no_such_user,,mysql); diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc index 305a8cae720..ec219c1590d 100644 --- a/storage/heap/ha_heap.cc +++ b/storage/heap/ha_heap.cc @@ -225,7 +225,7 @@ void ha_heap::update_key_stats() else { ha_rows hash_buckets= file->s->keydef[i].hash_buckets; - uint no_records= hash_buckets ? (uint) (file->s->records/hash_buckets) : 2; + ha_rows no_records= hash_buckets ? (file->s->records/hash_buckets) : 2; if (no_records < 2) no_records= 2; key->rec_per_key[key->key_parts-1]= no_records; @@ -256,6 +256,7 @@ int ha_heap::write_row(uchar * buf) We can perform this safely since only one writer at the time is allowed on the table. */ + records_changed= 0; file->s->key_stat_version++; } return res; @@ -274,6 +275,7 @@ int ha_heap::update_row(const uchar * old_data, uchar * new_data) We can perform this safely since only one writer at the time is allowed on the table. */ + records_changed= 0; file->s->key_stat_version++; } return res; @@ -290,6 +292,7 @@ int ha_heap::delete_row(const uchar * buf) We can perform this safely since only one writer at the time is allowed on the table. */ + records_changed= 0; file->s->key_stat_version++; } return res; @@ -740,8 +743,8 @@ heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table, if (share->max_rows && share->max_rows < max_rows) max_rows= share->max_rows; - hp_create_info->max_records= (ulong) max_rows; - hp_create_info->min_records= (ulong) share->min_rows; + hp_create_info->max_records= (ulong) min(max_rows, ULONG_MAX); + hp_create_info->min_records= (ulong) min(share->min_rows, ULONG_MAX); hp_create_info->keys= share->keys; hp_create_info->reclength= share->reclength; hp_create_info->keydef= keydef; diff --git a/storage/heap/ha_heap.h b/storage/heap/ha_heap.h index c5b8a09b216..9216e2e45b4 100644 --- a/storage/heap/ha_heap.h +++ b/storage/heap/ha_heap.h @@ -31,7 +31,7 @@ class ha_heap: public handler HP_SHARE *internal_share; key_map btree_keys; /* number of records changed since last statistics update */ - uint records_changed; + ulong records_changed; uint key_stat_version; my_bool internal_table; public: diff --git a/storage/heap/hp_create.c b/storage/heap/hp_create.c index d170d1abc65..5e0caf2fa24 100644 --- a/storage/heap/hp_create.c +++ b/storage/heap/hp_create.c @@ -243,7 +243,7 @@ static int keys_compare(heap_rb_param *param, uchar *key1, uchar *key2) static void init_block(HP_BLOCK *block, uint reclength, ulong min_records, ulong max_records) { - uint i,recbuffer,records_in_block; + ulong i,recbuffer,records_in_block; /* If not min_records and max_records are given, optimize for 1000 rows @@ -271,7 +271,7 @@ static void init_block(HP_BLOCK *block, uint reclength, ulong min_records, The + 1 is there to ensure that we get at least 1 row per level (for the exceptional case of very long rows) */ - if (records_in_block*recbuffer > + if ((ulonglong) records_in_block*recbuffer > (my_default_record_cache_size-sizeof(HP_PTRS)*HP_MAX_LEVELS)) records_in_block= (my_default_record_cache_size - sizeof(HP_PTRS) * HP_MAX_LEVELS) / recbuffer + 1; diff --git a/storage/heap/hp_delete.c b/storage/heap/hp_delete.c index fe71b14a30a..1cbfe7408d4 100644 --- a/storage/heap/hp_delete.c +++ b/storage/heap/hp_delete.c @@ -68,7 +68,7 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, const uchar *record, uchar *recpos, int flag) { heap_rb_param custom_arg; - uint old_allocated; + ulong old_allocated; int res; if (flag) diff --git a/storage/heap/hp_open.c b/storage/heap/hp_open.c index c456dbdfc84..854a8b05698 100644 --- a/storage/heap/hp_open.c +++ b/storage/heap/hp_open.c @@ -30,7 +30,7 @@ HP_INFO *heap_open_from_share(HP_SHARE *share, int mode) HP_INFO *info; DBUG_ENTER("heap_open_from_share"); - if (!(info= (HP_INFO*) my_malloc((uint) sizeof(HP_INFO) + + if (!(info= (HP_INFO*) my_malloc(sizeof(HP_INFO) + 2 * share->max_key_length, MYF(MY_ZEROFILL)))) { @@ -47,7 +47,7 @@ HP_INFO *heap_open_from_share(HP_SHARE *share, int mode) #ifndef DBUG_OFF info->opt_flag= READ_CHECK_USED; /* Check when changing */ #endif - DBUG_PRINT("exit",("heap: 0x%lx reclength: %d records_in_block: %d", + DBUG_PRINT("exit",("heap: 0x%lx reclength: %d records_in_block: %lu", (long) info, share->reclength, share->block.records_in_block)); DBUG_RETURN(info); diff --git a/storage/heap/hp_write.c b/storage/heap/hp_write.c index 8bfecc7747c..a7543ea5768 100644 --- a/storage/heap/hp_write.c +++ b/storage/heap/hp_write.c @@ -400,7 +400,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block, ulong records) { - uint block_pos; + ulong block_pos; size_t length; if (records < block->last_allocated) diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp index 17021bc4ddc..6a31ff21c55 100644 --- a/support-files/compiler_warnings.supp +++ b/support-files/compiler_warnings.supp @@ -49,7 +49,7 @@ ibuf/ibuf0ibuf.c: null argument where non-null required: 700-1000 fsp0fsp\.c: result of 32-bit shift implicitly converted to 64 bits log/log0log\.c : passing arg 1 of `atomic_add_64_nv' from incompatible pointer type log/log0online\.c : passing arg 1 of `atomic_add_64_nv' from incompatible pointer type -buf/buf0buf\.c : warning: label.*loop2.* defined but not used +buf/buf0buf\.c : label.*loop2.* defined but not used # # bdb is not critical to keep up to date |