3739 Vasil Dimov 2012-01-17
Fix Bug#13432465 "INNODB: IGNORING STRANGE ROW FROM MYSQL.INNODB_INDEX_STATS"
IN MYSQLD ERROR LOG
There are two problems related to this bug report:
1. InnoDB persistent storage tables mysql.innodb_table_stats and
mysql.innodb_index_stats have been working case-insensitively until now wrt
their contents (and we store table and index names in VARCHAR() columns in
those tables) because they are created with options
"ENGINE=INNODB DEFAULT CHARSET=utf8" while it should be
"ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin"
in order to be case-sensitive.
Due to this, rows for table 'A' from innodb_index_stats could have been
picked while searching for stats for table 'a'.
2. In index name comparison we used the length of the value found in
innodb_index_stats and thus could have picked "c1" as a value for an index
named "c10".
The solution is to add COLLATE=utf8_bin to tables' create definitions and
to also compare lengths in addition to using strncmp().
This patch also touches 3 other places where strncmp/strncasecmp is used -
we could have picked a row from innodb_index_stats where stat_name='siz'
when searching for a row where stat_name='size'.
Reviewed by: Marko (via IM/email)
modified:
scripts/mysql_system_tables.sql
storage/innobase/dict/dict0stats.cc
3738 Alexander Barkov 2012-01-17
BUG#13545236 - ASSERT IN SEC_SINCE_EPOCH
Problem:
WL#946 introduced a new methid Item_cache_datetime::get_date().
It did not execute check_date(), so in some cases it started
to return non-NULL result when instead of expected NULL.
Before WL#946 the generic Item::get_date() was used,
which executes check_date() inside str_to_datetime_with_warn().
Fix:
adding check_date() in the new method, to reproduce the pre-WL#946 behaviour.
modified:
mysql-test/r/func_time.result
mysql-test/t/func_time.test
sql/item.cc
modified:
mysql-test/r/func_time.result
mysql-test/t/func_time.test
sql/item.cc
=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql revid:alexander.barkov@stripped
+++ b/scripts/mysql_system_tables.sql revid:vasil.dimov@stripped
@@ -117,7 +117,7 @@ CREATE TABLE IF NOT EXISTS innodb_table_
clustered_index_size BIGINT UNSIGNED NOT NULL,
sum_of_other_index_sizes BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (database_name, table_name)
-) ENGINE=INNODB DEFAULT CHARSET=utf8;
+) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS innodb_index_stats (
database_name VARCHAR(64) NOT NULL,
@@ -135,7 +135,7 @@ CREATE TABLE IF NOT EXISTS innodb_index_
PRIMARY KEY (database_name, table_name, index_name, stat_name),
FOREIGN KEY (database_name, table_name)
REFERENCES innodb_table_stats (database_name, table_name)
-) ENGINE=INNODB DEFAULT CHARSET=utf8;
+) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
SET SESSION sql_mode=@sql_mode_orig;
=== modified file 'storage/innobase/dict/dict0stats.cc'
--- a/storage/innobase/dict/dict0stats.cc revid:alexander.barkov@stripped
+++ b/storage/innobase/dict/dict0stats.cc revid:vasil.dimov@stripped
@@ -1910,10 +1910,8 @@ dict_stats_fetch_index_stats_step(
index != NULL;
index = dict_table_get_next_index(index)) {
- // FIXME: Can we use a better cast operator
- if (strncasecmp(index->name,
- (const char*) data,
- len) == 0) {
+ if (strlen(index->name) == len
+ && memcmp(index->name, data, len) == 0) {
/* the corresponding index was found */
break;
}
@@ -1999,26 +1997,29 @@ dict_stats_fetch_index_stats_step(
/* sample_size could be UINT64_UNDEFINED here, if it is NULL */
#define PFX "n_diff_pfx"
+#define PFX_LEN 10
- if (strncasecmp("size", stat_name, stat_name_len) == 0) {
+ if (stat_name_len == 4 /* strlen("size") */
+ && strncasecmp("size", stat_name, stat_name_len) == 0) {
index->stat_index_size = (ulint) stat_value;
arg->stats_were_modified = TRUE;
- } else if (strncasecmp("n_leaf_pages", stat_name, stat_name_len)
+ } else if (stat_name_len == 12 /* strlen("n_leaf_pages") */
+ && strncasecmp("n_leaf_pages", stat_name, stat_name_len)
== 0) {
index->stat_n_leaf_pages = (ulint) stat_value;
arg->stats_were_modified = TRUE;
- } else if (strncasecmp(PFX, stat_name,
- ut_min(strlen(PFX), stat_name_len)) == 0) {
+ } else if (stat_name_len > PFX_LEN /* e.g. stat_name=="n_diff_pfx01" */
+ && strncasecmp(PFX, stat_name, PFX_LEN) == 0) {
const char* num_ptr;
unsigned long n_pfx;
/* point num_ptr into "1" from "n_diff_pfx12..." */
- num_ptr = stat_name + strlen(PFX);
+ num_ptr = stat_name + PFX_LEN;
/* stat_name should have exactly 2 chars appended to PFX
and they should be digits */
- if (stat_name_len != strlen(PFX) + 2
+ if (stat_name_len != PFX_LEN + 2
|| num_ptr[0] < '0' || num_ptr[0] > '9'
|| num_ptr[1] < '0' || num_ptr[1] > '9') {
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (vasil.dimov:3738 to 3739) Bug#13432465 | vasil.dimov | 17 Jan |