mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Bug#21205695 DROP TABLE MAY CAUSE SLAVES TO BREAK
Problem:
========
1) Drop table queries are re-generated by server
before writing the events(queries) into binlog
for various reasons. If table name/db name contains
a non regular characters (like latin characters),
the generated query is wrong. Hence it breaks the
replication.
2) In the edge case, when table name/db name contains
64 characters, server is throwing an assert
assert(M_TBLLEN < 128)
3) In the edge case, when db name contains 64 latin
characters, binlog content is interpreted badly
which is leading replication failure.
Analysis & Fix :
================
1) Parser reads the table name from the query and converts
it to standard charset(utf8) and stores it in table_name variable.
When drop table query is regenerated with the same table_name
variable, it should be converted back to the original charset
from standard charset(utf8).
2) Latin character takes two bytes for each character. Limit
of the identifier is 64. SYSTEM_CHARSET_MBMAXLEN is set to '3'.
So there is a possiblity that tablename/dbname contains 3 * 64.
Hence assert is changed to
(M_TBLLEN <= NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN)
3) db_len in the binlog event header is taking 1 byte.
db_len is ranged from 0 to 192 bytes (3 * 64).
While reading the db_len from the event, server
is casting to uint instead of uchar which is leading
to bad db_len. This problem is fixed by changing the
cast type to uchar.
This commit is contained in:
@@ -2138,11 +2138,13 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
if (thd->db == NULL || strcmp(db,thd->db) != 0
|
||||
|| is_drop_tmp_if_exists_added )
|
||||
{
|
||||
append_identifier(thd, built_ptr_query, db, db_len);
|
||||
append_identifier(thd, built_ptr_query, db, db_len,
|
||||
system_charset_info, thd->charset());
|
||||
built_ptr_query->append(".");
|
||||
}
|
||||
append_identifier(thd, built_ptr_query, table->table_name,
|
||||
strlen(table->table_name));
|
||||
strlen(table->table_name), system_charset_info,
|
||||
thd->charset());
|
||||
built_ptr_query->append(",");
|
||||
}
|
||||
/*
|
||||
@@ -2204,12 +2206,14 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
*/
|
||||
if (thd->db == NULL || strcmp(db,thd->db) != 0)
|
||||
{
|
||||
append_identifier(thd, &built_query, db, db_len);
|
||||
append_identifier(thd, &built_query, db, db_len,
|
||||
system_charset_info, thd->charset());
|
||||
built_query.append(".");
|
||||
}
|
||||
|
||||
append_identifier(thd, &built_query, table->table_name,
|
||||
strlen(table->table_name));
|
||||
strlen(table->table_name), system_charset_info,
|
||||
thd->charset());
|
||||
built_query.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user