Skip to content

Commit 9c22450

Browse files
committed
Bug#27447958 SCHEMA INCONSISTENCY AFTER CREATE DATABASE WITH LONG NAME
There is a limitation of 63 bytes for identifiers that can be distributed in MySQL Cluster. The limitation is is caused by two columns in ndb_schema table which are 63 bytes long. This is lower than the MySQL limit and thus makes it impossible to distribute schema objects with longer names. Fix by changing the length of "db" and "name" column of ndb_schema table to 255 bytes. Changing the schema of ndb_schema will cause a small hickup when the binlog thread restart, but this is safe as the problem of how to upgrade ndb_schema has been solved by WL#10162 which already added another schema change in 8.0. The implementation of WL#10162 also changed the code working with ndb_schema to dynamically adapt to the table schema, thus it's mainly a matter of using a new higher limit when the ndb_schema table is created. Adapting ndb_ddl.identifier_limits test to the new increased limits, asically changing it to test that long identifers now work. The legacy 63 bytes limit is still checked by the ndb_ddl.identifier_limits63_debug test, making sure that code still works with non upgraded ndb_schema. Change-Id: Ic10f7e9f6760fe6081a2cece00064b9b2f1466cd
1 parent 91f6d7f commit 9c22450

File tree

3 files changed

+56
-73
lines changed

3 files changed

+56
-73
lines changed

mysql-test/suite/ndb_ddl/identifier_limits.result

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,13 @@
55
create table abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123(
66
id int primary key
77
) engine=ndb;
8-
ERROR 42000: Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
9-
show warnings;
10-
Level Code Message
11-
Warning 1296 [mysql.ndb_schema] Identifier length exceeds the 63 byte limit
12-
Error 1059 Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
13-
Error 1031 Table storage engine for 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' doesn't have this option
8+
drop table abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
149
# ############################################################
1510
# Bug19550973: CREATE/DROP DATABASE STATEMENT SEGFAULTS IF
1611
# IDENTIFIER LENGTH IS >=64
1712
# ############################################################
1813
#
1914
# 1. Testing schema identifier with length 63
20-
# NOTE! ndb_schema identifier length limit is currently 63
2115
#
2216
CREATE DATABASE
2317
abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz12;
@@ -30,76 +24,52 @@ DROP TABLE abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz12.t1;
3024
DROP DATABASE abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz12;
3125
#
3226
# 2. Testing schema identifier with length 64
33-
# NOTE! MySQL Server allows 64, but ndb_schema limit is currently 63
3427
#
3528
CREATE DATABASE
3629
abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
37-
Warnings:
38-
Warning 1296 [mysql.ndb_schema] Identifier length exceeds the 63 byte limit
39-
Warning 1296 Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
4030
# Verify database existence
4131
USE abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
4232
# Create non NDB table
4333
CREATE TABLE t1 (
4434
a int
4535
);
46-
# Create NDB table should fail
36+
# Create NDB table
4737
CREATE TABLE t2 (
4838
a int
4939
) ENGINE=NDB;
50-
ERROR 42000: Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
51-
show warnings;
52-
Level Code Message
53-
Warning 1296 [mysql.ndb_schema] Identifier length exceeds the 63 byte limit
54-
Error 1059 Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
55-
Error 1031 Table storage engine for 't2' doesn't have this option
5640
#
57-
# 3. Databases with identifier length = 64 won't be replicated to other
58-
# MySQL Servers. Verify that the above created dabatase is not present
41+
# 3. Databases with identifier length = 64 is synchronized to other
42+
# MySQL Servers. Verify that the above created dabatase is present
5943
# in the other Server
44+
# NOTE! This testcase was fixed by BUG#27447958 which extended ndb_schema
45+
# to support identifiers > 63
6046
#
6147
USE abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
62-
ERROR 42000: Unknown database 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123'
6348
#
6449
# 4. Testing alter database
6550
#
6651
ALTER DATABASE
6752
abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123
6853
character set=utf8mb4;
69-
Warnings:
70-
Warning 1296 [mysql.ndb_schema] Identifier length exceeds the 63 byte limit
71-
Warning 1296 Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
7254
CREATE DATABASE db1;
7355
CREATE TABLE db1.t1 (
7456
a int
7557
) ENGINE=NDB;
58+
CREATE TABLE db1.t2 (
59+
a int
60+
) ENGINE=NDB;
7661
#
77-
# 4.1 Renaming table to too long database name should fail
62+
# 4.1 Renaming table to long database name
7863
#
7964
ALTER TABLE db1.t1
8065
RENAME abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123.t3;
81-
ERROR 42000: Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
82-
SHOW WARNINGS;
83-
Level Code Message
84-
Warning 1296 [mysql.ndb_schema] Identifier length exceeds the 63 byte limit
85-
Error 1059 Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
86-
Error 1025 Error on rename of './db1/t1' to './abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123/t3' (errno: 140 - Wrong create options)
8766
#
88-
# 4.2 Renaming table to too long table name should fail
67+
# 4.2 Renaming table to long table name
8968
#
90-
ALTER TABLE db1.t1
69+
ALTER TABLE db1.t2
9170
RENAME db1.abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
92-
ERROR 42000: Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
93-
SHOW WARNINGS;
94-
Level Code Message
95-
Warning 1296 [mysql.ndb_schema] Identifier length exceeds the 63 byte limit
96-
Error 1059 Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
97-
Error 1025 Error on rename of './db1/t1' to './db1/abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' (errno: 140 - Wrong create options)
9871
DROP DATABASE db1;
9972
DROP DATABASE abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
100-
Warnings:
101-
Warning 1296 [mysql.ndb_schema] Identifier length exceeds the 63 byte limit
102-
Warning 1296 Identifier name 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123' is too long
10373
# Checking that database doesn't exists
10474
USE abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
10575
ERROR 42000: Unknown database 'abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123'

mysql-test/suite/ndb_ddl/identifier_limits.test

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@
99
--echo # Bug11753491: MYSQLD CRASHES WHEN CREATING A CLUSTER TABLE WITH 64
1010
--echo # CHARACTER TABLE NAME
1111
--echo # ####################################################################
12-
--error ER_TOO_LONG_IDENT
1312
create table abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123(
1413
id int primary key
1514
) engine=ndb;
16-
show warnings;
17-
15+
drop table abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
1816

1917
--echo # ############################################################
2018
--echo # Bug19550973: CREATE/DROP DATABASE STATEMENT SEGFAULTS IF
@@ -28,7 +26,6 @@ call mtr.add_suppression("Failed to distribute");
2826

2927
--echo #
3028
--echo # 1. Testing schema identifier with length 63
31-
--echo # NOTE! ndb_schema identifier length limit is currently 63
3229
--echo #
3330
CREATE DATABASE
3431
abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz12;
@@ -43,7 +40,6 @@ DROP DATABASE abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz12;
4340

4441
--echo #
4542
--echo # 2. Testing schema identifier with length 64
46-
--echo # NOTE! MySQL Server allows 64, but ndb_schema limit is currently 63
4743
--echo #
4844
CREATE DATABASE
4945
abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
@@ -54,20 +50,19 @@ USE abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
5450
CREATE TABLE t1 (
5551
a int
5652
);
57-
--echo # Create NDB table should fail
58-
--error ER_TOO_LONG_IDENT
53+
--echo # Create NDB table
5954
CREATE TABLE t2 (
6055
a int
6156
) ENGINE=NDB;
62-
show warnings;
6357

6458
--echo #
65-
--echo # 3. Databases with identifier length = 64 won't be replicated to other
66-
--echo # MySQL Servers. Verify that the above created dabatase is not present
59+
--echo # 3. Databases with identifier length = 64 is synchronized to other
60+
--echo # MySQL Servers. Verify that the above created dabatase is present
6761
--echo # in the other Server
62+
--echo # NOTE! This testcase was fixed by BUG#27447958 which extended ndb_schema
63+
--echo # to support identifiers > 63
6864
--echo #
6965
--connection mysqld2
70-
--error ER_BAD_DB_ERROR
7166
USE abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
7267
--connection mysqld1
7368

@@ -82,26 +77,21 @@ CREATE DATABASE db1;
8277
CREATE TABLE db1.t1 (
8378
a int
8479
) ENGINE=NDB;
80+
CREATE TABLE db1.t2 (
81+
a int
82+
) ENGINE=NDB;
8583

8684
--echo #
87-
--echo # 4.1 Renaming table to too long database name should fail
85+
--echo # 4.1 Renaming table to long database name
8886
--echo #
89-
--error ER_TOO_LONG_IDENT
9087
ALTER TABLE db1.t1
9188
RENAME abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123.t3;
92-
# replace win slashes since not using default database
93-
--replace_regex /[\\]/\//
94-
SHOW WARNINGS;
9589

9690
--echo #
97-
--echo # 4.2 Renaming table to too long table name should fail
91+
--echo # 4.2 Renaming table to long table name
9892
--echo #
99-
--error ER_TOO_LONG_IDENT
100-
ALTER TABLE db1.t1
93+
ALTER TABLE db1.t2
10194
RENAME db1.abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;
102-
# replace win slashes since not using default database
103-
--replace_regex /[\\]/\//
104-
SHOW WARNINGS;
10595

10696
DROP DATABASE db1;
10797
DROP DATABASE abcdefghijklmnopqrstuvwxyz1234567890bcdefghijklmnopqrstuvwxyz123;

storage/ndb/plugin/ndb_schema_dist_table.cc

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ static const char *COL_EPOCH = "epoch";
4343
static const char *COL_TYPE = "type";
4444
static const char *COL_SCHEMA_OP_ID = "schema_op_id";
4545

46+
// Length of the schema object identifiers which can be distributed by the
47+
// ndb_schema table. The legacy limit of 63 was increased in 8.0.18 to allow for
48+
// "any" identifier to be distributed. NOTE! Code still supports working with a
49+
// ndb_schema table using the legacy length, warning will be printed suggesting
50+
// upgrade
51+
static constexpr int IDENTIFIER_LENGTH = 255;
52+
static constexpr int LEGACY_IDENTIFIER_LENGTH = 63;
53+
4654
Ndb_schema_dist_table::Ndb_schema_dist_table(Thd_ndb *thd_ndb)
4755
: Ndb_util_table(thd_ndb, DB_NAME, TABLE_NAME, true) {}
4856

@@ -56,14 +64,14 @@ bool Ndb_schema_dist_table::check_schema() const {
5664
// backwards compatiblity reasons it's allowed to use such a schema
5765
// distribution table but not all identifiers will be possible to distribute.
5866
if (!(check_column_exist(COL_DB) && check_column_varbinary(COL_DB) &&
59-
check_column_minlength(COL_DB, 63))) {
67+
check_column_minlength(COL_DB, LEGACY_IDENTIFIER_LENGTH))) {
6068
return false;
6169
}
6270

6371
// name
6472
// varbinary, at least 63 bytes long
6573
if (!(check_column_exist(COL_NAME) && check_column_varbinary(COL_NAME) &&
66-
check_column_minlength(COL_NAME, 63))) {
74+
check_column_minlength(COL_NAME, LEGACY_IDENTIFIER_LENGTH))) {
6775
return false;
6876
}
6977
// Check that db + name is the primary key, otherwise pk operations
@@ -206,21 +214,30 @@ bool Ndb_schema_dist_table::define_table_ndb(NdbDictionary::Table &new_table,
206214
// Allow table to be read+write also in single user mode
207215
new_table.setSingleUserMode(NdbDictionary::Table::SingleUserModeReadWrite);
208216

217+
// The length of "db" and "name" was adjusted in 8.0.18 to allow
218+
// passing 255 bytes long identifiers
219+
int db_and_name_length = IDENTIFIER_LENGTH;
220+
if (mysql_version < 80018) {
221+
// Use legacy identifier length when creating the table for
222+
// backwards compatibility testing
223+
db_and_name_length = LEGACY_IDENTIFIER_LENGTH;
224+
}
225+
209226
{
210-
// db VARBINARY(63) NOT NULL
227+
// db VARBINARY(255) NOT NULL
211228
NdbDictionary::Column col_db(COL_DB);
212229
col_db.setType(NdbDictionary::Column::Varbinary);
213-
col_db.setLength(63);
230+
col_db.setLength(db_and_name_length);
214231
col_db.setNullable(false);
215232
col_db.setPrimaryKey(true);
216233
if (!define_table_add_column(new_table, col_db)) return false;
217234
}
218235

219236
{
220-
// name VARBINARY(63) NOT NULL
237+
// name VARBINARY(255) NOT NULL
221238
NdbDictionary::Column col_name(COL_NAME);
222239
col_name.setType(NdbDictionary::Column::Varbinary);
223-
col_name.setLength(63);
240+
col_name.setLength(db_and_name_length);
224241
col_name.setNullable(false);
225242
col_name.setPrimaryKey(true);
226243
if (!define_table_add_column(new_table, col_name)) return false;
@@ -304,6 +321,12 @@ bool Ndb_schema_dist_table::need_upgrade() const {
304321
if (!have_schema_op_id_column()) {
305322
return true;
306323
}
324+
// The 'db' and 'name' column need to be upgrade if length is shorter than
325+
// current identifier length
326+
if (get_column_max_length(COL_DB) < IDENTIFIER_LENGTH ||
327+
get_column_max_length(COL_NAME) < IDENTIFIER_LENGTH) {
328+
return true;
329+
}
307330
return false;
308331
}
309332

@@ -321,9 +344,9 @@ bool Ndb_schema_dist_table::drop_events_in_NDB() const {
321344
std::string Ndb_schema_dist_table::define_table_dd() const {
322345
std::stringstream ss;
323346
ss << "CREATE TABLE " << db_name() << "." << table_name() << "(\n";
324-
ss << "db VARBINARY(63) NOT NULL,"
325-
"name VARBINARY(63) NOT NULL,"
326-
"slock BINARY(32) NOT NULL,"
347+
ss << "db VARBINARY(" << get_column_max_length(COL_DB) << ") NOT NULL,";
348+
ss << "name VARBINARY(" << get_column_max_length(COL_NAME) << ") NOT NULL,";
349+
ss << "slock BINARY(32) NOT NULL,"
327350
"query BLOB NOT NULL,"
328351
"node_id INT UNSIGNED NOT NULL,"
329352
"epoch BIGINT UNSIGNED NOT NULL,"

0 commit comments

Comments
 (0)