Bug #79805 Table with unknown collation crashes MySQL
Submitted: 29 Dec 2015 12:46 Modified: 28 Jan 2016 19:45
Reporter: Marko Mäkelä Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: DDL Severity:S3 (Non-critical)
Version:8.0.0 OS:Any
Assigned to: CPU Architecture:Any

[29 Dec 2015 12:46] Marko Mäkelä
Description:
The Global Data Dictionary seems to have reintroduced
MySQL Bug #46256 drop table with unknown collation crashes innodb

in a more widespread way, killing the whole server if any table of any storage engine refers to an unknown collation.

How to repeat:
--source include/have_innodb.inc
--source include/not_embedded.inc

--error ER_UNKNOWN_COLLATION
CREATE TABLE t1 (phone VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_phone_ci);
let $restart_parameters = restart: --character-sets-dir=$MYSQL_TEST_DIR/std_data/;
--source include/restart_mysqld.inc
CREATE TABLE t1 (
 name VARCHAR(64) PRIMARY KEY,
 phone VARCHAR(64) COLLATE utf8_phone_ci UNIQUE
) DEFAULT CHARACTER SET utf8 ENGINE=InnoDB;
INSERT INTO t1 VALUES('Bell', '+1 212 555 1212');
--error ER_DUP_ENTRY
INSERT INTO t1 VALUES('Whistle', '1-212-555-1212');
INSERT INTO t1 VALUES('Siemens+Halske', '+49 1');
INSERT INTO t1 VALUES('Ericsson', '+46 1');
let $restart_parameters=;
--source include/kill_and_restart_mysqld.inc
#--error SOME_ERROR
CHECK TABLE t1;
#--error SOME_ERROR
RENAME TABLE t1 TO t2;
DROP TABLE t1;

The server will crash while executing CHECK TABLE:

sql/dd_table_share.cc:799: bool fill_column_from_dd(TABLE_SHARE*, const dd::Column*, uchar*, uint, uchar*, uint): Assertion `charset' failed.

This happens also if ENGINE=InnoDB is substituted with ENGINE=MyISAM. handler::open() was not called yet.
It is possible that the original bug is back in some form in InnoDB, because no test case was added.

Suggested fix:
Allow handler::delete_table() on tables with missing collations, but prevent calls to handler::open() and handler::rename_table(), or any other DDL or DML methods.
[7 Jan 2016 8:34] Marko Mäkelä
Posted by developer:
 
I tested the debug builds of 5.5 and 5.7, and the test case works in both, like this:

# restart
CHECK TABLE t1;
Table   Op      Msg_type        Msg_text
test.t1 check   Error   Unknown collation '#352' in table 't1' definition
test.t1 check   error   Corrupt
RENAME TABLE t1 TO t2;
RENAME TABLE t2 TO t1;
DROP TABLE t1;
innodb.dd_restart                        [ pass ]   6012

So, also RENAME TABLE is working in 5.5 and 5.7.

In 5.8, I would want to block RENAME TABLE, and in 5.8.0 (at least in WL#7141) also the CHECK TABLE would have to be blocked, because ha_innobase::open() should not allow  to open tables with missing collations.

By the way, a missing collation could be handled more gracefully, as follows:

1. For reads, refuse to use an index that depends on a missing collation.
2. During write operations, mark corrupted any index that depends on a missing collation.

Fixing that would be a nice-to-have follow-up bug, after WL#7141 has been completed.
[28 Jan 2016 19:45] Paul DuBois
Fixed in 5.8.0.

Bug affects no released version. No changelog entry needed.
[18 Jun 2016 21:35] Omer Barnir
Posted by developer:
 
Reported version value updated to reflect release name change from 5.8 to 8.0