mirror of
https://github.com/MariaDB/server.git
synced 2025-07-26 07:02:12 +03:00
MDEV-26597 : Assertion `!wsrep_has_changes(thd) || (thd->lex->sql_command == SQLCOM_CREATE_TABLE && !thd->is_current_stmt_binlog_format_row())' failed.
If repl.max_ws_size is set too low following CREATE TABLE could fail during commit. In this case wsrep_commit_empty should allow rolling it back if provider state is s_aborted. Furhermore, original ER_ERROR_DURING_COMMIT does not really tell anything clear for user. Therefore, this commit adds a new error ER_TOO_BIG_WRITESET. This will change some test cases output.
This commit is contained in:
19
mysql-test/suite/galera/r/MDEV-26597.result
Normal file
19
mysql-test/suite/galera/r/MDEV-26597.result
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
connection node_2;
|
||||||
|
connection node_1;
|
||||||
|
connection node_1;
|
||||||
|
connection node_2;
|
||||||
|
connection node_2;
|
||||||
|
CREATE TABLE t3 (c1 INTEGER NOT NULL PRIMARY KEY, c2 FLOAT(3,2));
|
||||||
|
SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=512';
|
||||||
|
SET @@autocommit=0;
|
||||||
|
INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00),(1009,1.25),(1010,1.50),(1011,1.75);
|
||||||
|
CREATE TABLE t1 ( pk int primary key) ENGINE=INNODB;
|
||||||
|
ERROR HY000: Maximum writeset size exceeded
|
||||||
|
SHOW WARNINGS;
|
||||||
|
Level Code Message
|
||||||
|
Error 4160 Maximum writeset size exceeded
|
||||||
|
connection node_2;
|
||||||
|
SET SESSION wsrep_sync_wait = 0;
|
||||||
|
Killing server ...
|
||||||
|
connection node_1;
|
||||||
|
DROP TABLE t3;
|
@ -4,7 +4,7 @@ connection node_1;
|
|||||||
CREATE TABLE t1 (f1 VARCHAR(512)) ENGINE=InnoDB;
|
CREATE TABLE t1 (f1 VARCHAR(512)) ENGINE=InnoDB;
|
||||||
SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=512';
|
SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=512';
|
||||||
INSERT INTO t1 VALUES (REPEAT('a', 512));
|
INSERT INTO t1 VALUES (REPEAT('a', 512));
|
||||||
ERROR HY000: Got error 5 "Input/output error" during COMMIT
|
ERROR HY000: Maximum writeset size exceeded
|
||||||
SELECT COUNT(*) = 0 FROM t1;
|
SELECT COUNT(*) = 0 FROM t1;
|
||||||
COUNT(*) = 0
|
COUNT(*) = 0
|
||||||
1
|
1
|
||||||
|
@ -4,7 +4,7 @@ connection node_1;
|
|||||||
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(1024)) Engine=InnoDB;
|
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(1024)) Engine=InnoDB;
|
||||||
SET GLOBAL wsrep_max_ws_size = 1024;
|
SET GLOBAL wsrep_max_ws_size = 1024;
|
||||||
INSERT INTO t1 VALUES (DEFAULT, REPEAT('X', 1024));
|
INSERT INTO t1 VALUES (DEFAULT, REPEAT('X', 1024));
|
||||||
ERROR HY000: Got error 5 "Input/output error" during COMMIT
|
ERROR HY000: Maximum writeset size exceeded
|
||||||
SELECT COUNT(*) = 0 FROM t1;
|
SELECT COUNT(*) = 0 FROM t1;
|
||||||
COUNT(*) = 0
|
COUNT(*) = 0
|
||||||
1
|
1
|
||||||
|
32
mysql-test/suite/galera/t/MDEV-26597.test
Normal file
32
mysql-test/suite/galera/t/MDEV-26597.test
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
--source include/galera_cluster.inc
|
||||||
|
|
||||||
|
# Save original auto_increment_offset values.
|
||||||
|
--let $node_1=node_1
|
||||||
|
--let $node_2=node_2
|
||||||
|
--source include/auto_increment_offset_save.inc
|
||||||
|
|
||||||
|
--connection node_2
|
||||||
|
CREATE TABLE t3 (c1 INTEGER NOT NULL PRIMARY KEY, c2 FLOAT(3,2));
|
||||||
|
SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=512';
|
||||||
|
SET @@autocommit=0;
|
||||||
|
INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00),(1009,1.25),(1010,1.50),(1011,1.75);
|
||||||
|
--error ER_TOO_BIG_WRITESET
|
||||||
|
CREATE TABLE t1 ( pk int primary key) ENGINE=INNODB;
|
||||||
|
SHOW WARNINGS;
|
||||||
|
|
||||||
|
--connection node_2
|
||||||
|
SET SESSION wsrep_sync_wait = 0;
|
||||||
|
--source include/kill_galera.inc
|
||||||
|
|
||||||
|
--let $start_mysqld_params = ""
|
||||||
|
--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
--source include/start_mysqld.inc
|
||||||
|
|
||||||
|
#
|
||||||
|
# Cleanup
|
||||||
|
#
|
||||||
|
--source ../../galera/include/auto_increment_offset_restore.inc
|
||||||
|
--connection node_1
|
||||||
|
DROP TABLE t3;
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ CREATE TABLE t1 (f1 VARCHAR(512)) ENGINE=InnoDB;
|
|||||||
|
|
||||||
SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=512';
|
SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=512';
|
||||||
|
|
||||||
--error ER_ERROR_DURING_COMMIT
|
--error ER_TOO_BIG_WRITESET
|
||||||
INSERT INTO t1 VALUES (REPEAT('a', 512));
|
INSERT INTO t1 VALUES (REPEAT('a', 512));
|
||||||
|
|
||||||
SELECT COUNT(*) = 0 FROM t1;
|
SELECT COUNT(*) = 0 FROM t1;
|
||||||
|
@ -12,7 +12,7 @@ CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(1024)) Engine
|
|||||||
--let $wsrep_max_ws_size_orig = `SELECT @@wsrep_max_ws_size`
|
--let $wsrep_max_ws_size_orig = `SELECT @@wsrep_max_ws_size`
|
||||||
SET GLOBAL wsrep_max_ws_size = 1024;
|
SET GLOBAL wsrep_max_ws_size = 1024;
|
||||||
|
|
||||||
--error ER_ERROR_DURING_COMMIT
|
--error ER_TOO_BIG_WRITESET
|
||||||
INSERT INTO t1 VALUES (DEFAULT, REPEAT('X', 1024));
|
INSERT INTO t1 VALUES (DEFAULT, REPEAT('X', 1024));
|
||||||
SELECT COUNT(*) = 0 FROM t1;
|
SELECT COUNT(*) = 0 FROM t1;
|
||||||
|
|
||||||
|
@ -9090,3 +9090,5 @@ ER_PERIOD_CONSTRAINT_DROP
|
|||||||
ER_TOO_LONG_KEYPART 42000 S1009
|
ER_TOO_LONG_KEYPART 42000 S1009
|
||||||
chi "指定的索引部分太长;最大索引部分长度为 %u 个字节"
|
chi "指定的索引部分太长;最大索引部分长度为 %u 个字节"
|
||||||
eng "Specified key part was too long; max key part length is %u bytes"
|
eng "Specified key part was too long; max key part length is %u bytes"
|
||||||
|
ER_TOO_BIG_WRITESET
|
||||||
|
eng "Maximum writeset size exceeded"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2008-2021 Codership Oy <http://www.codership.com>
|
/* Copyright 2008-2022 Codership Oy <http://www.codership.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -2153,7 +2153,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
|
|||||||
ret,
|
ret,
|
||||||
(thd->db.str ? thd->db.str : "(null)"),
|
(thd->db.str ? thd->db.str : "(null)"),
|
||||||
wsrep_thd_query(thd));
|
wsrep_thd_query(thd));
|
||||||
my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED);
|
my_error(ER_TOO_BIG_WRITESET, MYF(0));
|
||||||
break;
|
break;
|
||||||
case wsrep::e_deadlock_error:
|
case wsrep::e_deadlock_error:
|
||||||
WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. "
|
WSREP_WARN("TO isolation failed for: %d, schema: %s, sql: %s. "
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2013-2021 Codership Oy <info@codership.com>
|
/* Copyright (C) 2013-2022 Codership Oy <info@codership.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -210,7 +210,6 @@ static inline void wsrep_override_error(THD *thd, uint error,
|
|||||||
!da->is_set() ||
|
!da->is_set() ||
|
||||||
(da->is_error() &&
|
(da->is_error() &&
|
||||||
da->sql_errno() != error &&
|
da->sql_errno() != error &&
|
||||||
da->sql_errno() != ER_ERROR_DURING_COMMIT &&
|
|
||||||
da->sql_errno() != ER_LOCK_DEADLOCK))
|
da->sql_errno() != ER_LOCK_DEADLOCK))
|
||||||
{
|
{
|
||||||
da->reset_diagnostics_area();
|
da->reset_diagnostics_area();
|
||||||
@ -226,7 +225,10 @@ static inline void wsrep_override_error(THD* thd,
|
|||||||
switch (ce)
|
switch (ce)
|
||||||
{
|
{
|
||||||
case wsrep::e_error_during_commit:
|
case wsrep::e_error_during_commit:
|
||||||
wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status);
|
if (status == wsrep::provider::error_size_exceeded)
|
||||||
|
wsrep_override_error(thd, ER_TOO_BIG_WRITESET);
|
||||||
|
else
|
||||||
|
wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status);
|
||||||
break;
|
break;
|
||||||
case wsrep::e_deadlock_error:
|
case wsrep::e_deadlock_error:
|
||||||
wsrep_override_error(thd, ER_LOCK_DEADLOCK);
|
wsrep_override_error(thd, ER_LOCK_DEADLOCK);
|
||||||
@ -235,7 +237,7 @@ static inline void wsrep_override_error(THD* thd,
|
|||||||
wsrep_override_error(thd, ER_QUERY_INTERRUPTED);
|
wsrep_override_error(thd, ER_QUERY_INTERRUPTED);
|
||||||
break;
|
break;
|
||||||
case wsrep::e_size_exceeded_error:
|
case wsrep::e_size_exceeded_error:
|
||||||
wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status);
|
wsrep_override_error(thd, ER_TOO_BIG_WRITESET);
|
||||||
break;
|
break;
|
||||||
case wsrep::e_append_fragment_error:
|
case wsrep::e_append_fragment_error:
|
||||||
/* TODO: Figure out better error number */
|
/* TODO: Figure out better error number */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2016-2019 Codership Oy <http://www.codership.com>
|
/* Copyright 2016-2022 Codership Oy <http://www.codership.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -531,18 +531,28 @@ wsrep_current_error_status(THD* thd)
|
|||||||
static inline void wsrep_commit_empty(THD* thd, bool all)
|
static inline void wsrep_commit_empty(THD* thd, bool all)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("wsrep_commit_empty");
|
DBUG_ENTER("wsrep_commit_empty");
|
||||||
WSREP_DEBUG("wsrep_commit_empty(%llu)", thd->thread_id);
|
WSREP_DEBUG("wsrep_commit_empty for %llu client_state %s client_mode"
|
||||||
|
" %s trans_state %s sql %s",
|
||||||
|
thd_get_thread_id(thd),
|
||||||
|
wsrep::to_c_string(thd->wsrep_cs().state()),
|
||||||
|
wsrep::to_c_string(thd->wsrep_cs().mode()),
|
||||||
|
wsrep::to_c_string(thd->wsrep_cs().transaction().state()),
|
||||||
|
wsrep_thd_query(thd));
|
||||||
|
|
||||||
if (wsrep_is_real(thd, all) &&
|
if (wsrep_is_real(thd, all) &&
|
||||||
wsrep_thd_is_local(thd) &&
|
wsrep_thd_is_local(thd) &&
|
||||||
thd->wsrep_trx().active() &&
|
thd->wsrep_trx().active() &&
|
||||||
thd->wsrep_trx().state() != wsrep::transaction::s_committed)
|
thd->wsrep_trx().state() != wsrep::transaction::s_committed)
|
||||||
{
|
{
|
||||||
/* @todo CTAS with STATEMENT binlog format and empty result set
|
/* Here transaction is either empty (i.e. no changes) or
|
||||||
seems to be committing empty. Figure out why and try to fix
|
it was CREATE TABLE with no row binlog format or
|
||||||
elsewhere. */
|
we have already aborted transaction e.g. because max writeset size
|
||||||
|
has been reached. */
|
||||||
DBUG_ASSERT(!wsrep_has_changes(thd) ||
|
DBUG_ASSERT(!wsrep_has_changes(thd) ||
|
||||||
(thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
|
(thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
|
||||||
!thd->is_current_stmt_binlog_format_row()));
|
!thd->is_current_stmt_binlog_format_row()) ||
|
||||||
|
thd->wsrep_cs().transaction().state() == wsrep::transaction::s_aborted);
|
||||||
|
|
||||||
bool have_error= wsrep_current_error(thd);
|
bool have_error= wsrep_current_error(thd);
|
||||||
int ret= wsrep_before_rollback(thd, all) ||
|
int ret= wsrep_before_rollback(thd, all) ||
|
||||||
wsrep_after_rollback(thd, all) ||
|
wsrep_after_rollback(thd, all) ||
|
||||||
|
Reference in New Issue
Block a user