Commit d5a15f04 authored by sjaakola's avatar sjaakola Committed by Jan Lindström

MDEV-24978 crash with transaction on table with no PK and long fulltext column

If a table has no unique indexes, write set key information will be collected on all columns in the table.
The write set key information has space only for max 3500 bytes for individual column, and if a varchar colummn of such non-primary key table is longer than
 this limit, currently a crash follows.
The fix in this commit, is to truncate key values extracted from such long varhar columns to max 3500 bytes.
This may potentially lead to false positive certification failures for transactions, which operate on separate cluster nodes, and update/insert/delete table rows, which differ only in the part of such long columns after 3500 bytes border.
Reviewed-by: default avatarJan Lindström <jan.lindstrom@mariadb.com>
parent b2a5e0f2
...@@ -34,3 +34,59 @@ COUNT(f1) = 1000 ...@@ -34,3 +34,59 @@ COUNT(f1) = 1000
1 1
DROP TABLE t1; DROP TABLE t1;
DROP TABLE ten; DROP TABLE ten;
connection node_1;
SET @value=REPEAT (1,5001);
CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb;
INSERT IGNORE INTO t VALUES(@value);
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
SELECT COUNT(*) FROM t;
COUNT(*)
1
connection node_2;
SELECT COUNT(*) FROM t;
COUNT(*)
1
connection node_1;
DROP TABLE t;
CREATE TABLE t (a VARCHAR(5000)) engine=innodb;
INSERT IGNORE INTO t VALUES(@value);
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
SELECT COUNT(*) FROM t;
COUNT(*)
1
connection node_2;
SELECT COUNT(*) FROM t;
COUNT(*)
1
connection node_1;
DROP TABLE t;
connection node_1;
SET @value=REPEAT (1,5001);
CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb DEFAULT CHARSET=utf8;
INSERT IGNORE INTO t VALUES(@value);
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
SELECT COUNT(*) FROM t;
COUNT(*)
1
connection node_2;
SELECT COUNT(*) FROM t;
COUNT(*)
1
connection node_1;
DROP TABLE t;
CREATE TABLE t (a VARCHAR(5000)) engine=innodb DEFAULT CHARSET=utf8;
INSERT IGNORE INTO t VALUES(@value);
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
SELECT COUNT(*) FROM t;
COUNT(*)
1
connection node_2;
SELECT COUNT(*) FROM t;
COUNT(*)
1
connection node_1;
DROP TABLE t;
...@@ -58,28 +58,50 @@ SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk'); ...@@ -58,28 +58,50 @@ SELECT COUNT(f1) = 1000 FROM t1 WHERE MATCH(f1) AGAINST ('abcdefjhk');
DROP TABLE t1; DROP TABLE t1;
DROP TABLE ten; DROP TABLE ten;
#
# Case 2: UTF-8
# TODO: MDEV-24978
# #
#--connection node_1 # MDEV-24978 : SIGABRT in __libc_message
#SET @value=REPEAT (1,5001);
#CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb DEFAULT CHARSET=utf8;
#INSERT IGNORE INTO t VALUES(@value);
#SELECT COUNT(*) FROM t;
# #
#--connection node_2 --connection node_1
#SELECT COUNT(*) FROM t; SET @value=REPEAT (1,5001);
# CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb;
#--connection node_1 INSERT IGNORE INTO t VALUES(@value);
#DROP TABLE t; SELECT COUNT(*) FROM t;
#CREATE TABLE t (a VARCHAR(5000)) engine=innodb DEFAULT CHARSET=utf8;
#INSERT IGNORE INTO t VALUES(@value); --connection node_2
#SELECT COUNT(*) FROM t; SELECT COUNT(*) FROM t;
--connection node_1
DROP TABLE t;
CREATE TABLE t (a VARCHAR(5000)) engine=innodb;
INSERT IGNORE INTO t VALUES(@value);
SELECT COUNT(*) FROM t;
--connection node_2
SELECT COUNT(*) FROM t;
--connection node_1
DROP TABLE t;
# #
#--connection node_2 # Case 2: UTF-8
#SELECT COUNT(*) FROM t;
# #
#--connection node_1 --connection node_1
#DROP TABLE t; SET @value=REPEAT (1,5001);
CREATE TABLE t (a VARCHAR(5000),FULLTEXT (a)) engine=innodb DEFAULT CHARSET=utf8;
INSERT IGNORE INTO t VALUES(@value);
SELECT COUNT(*) FROM t;
--connection node_2
SELECT COUNT(*) FROM t;
--connection node_1
DROP TABLE t;
CREATE TABLE t (a VARCHAR(5000)) engine=innodb DEFAULT CHARSET=utf8;
INSERT IGNORE INTO t VALUES(@value);
SELECT COUNT(*) FROM t;
--connection node_2
SELECT COUNT(*) FROM t;
--connection node_1
DROP TABLE t;
...@@ -7218,10 +7218,14 @@ wsrep_store_key_val_for_row( ...@@ -7218,10 +7218,14 @@ wsrep_store_key_val_for_row(
/* In a column prefix index, we may need to truncate /* In a column prefix index, we may need to truncate
the stored value: */ the stored value: */
if (true_len > key_len) { if (true_len > key_len) {
true_len = key_len; true_len = key_len;
} }
/* cannot exceed max column lenght either, we may need to truncate
the stored value: */
if (true_len > sizeof(sorted)) {
true_len = sizeof(sorted);
}
memcpy(sorted, data, true_len); memcpy(sorted, data, true_len);
true_len = wsrep_innobase_mysql_sort( true_len = wsrep_innobase_mysql_sort(
...@@ -7234,8 +7238,8 @@ wsrep_store_key_val_for_row( ...@@ -7234,8 +7238,8 @@ wsrep_store_key_val_for_row(
actual data. The rest of the space was reset to zero actual data. The rest of the space was reset to zero
in the bzero() call above. */ in the bzero() call above. */
if (true_len > buff_space) { if (true_len > buff_space) {
fprintf (stderr, WSREP_DEBUG (
"WSREP: key truncated: %s\n", "write set key truncated for: %s\n",
wsrep_thd_query(thd)); wsrep_thd_query(thd));
true_len = buff_space; true_len = buff_space;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment