mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01: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:
parent
ab3ec013c4
commit
e8acec8974
10 changed files with 81 additions and 16 deletions
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;
|
||||
SET GLOBAL wsrep_provider_options = 'repl.max_ws_size=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;
|
||||
COUNT(*) = 0
|
||||
1
|
||||
|
|
|
@ -4,7 +4,7 @@ connection node_1;
|
|||
CREATE TABLE t1 (f1 INTEGER AUTO_INCREMENT PRIMARY KEY, f2 VARCHAR(1024)) Engine=InnoDB;
|
||||
SET GLOBAL wsrep_max_ws_size = 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;
|
||||
COUNT(*) = 0
|
||||
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';
|
||||
|
||||
--error ER_ERROR_DURING_COMMIT
|
||||
--error ER_TOO_BIG_WRITESET
|
||||
INSERT INTO t1 VALUES (REPEAT('a', 512));
|
||||
|
||||
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`
|
||||
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));
|
||||
SELECT COUNT(*) = 0 FROM t1;
|
||||
|
||||
|
|
|
@ -9090,3 +9090,5 @@ ER_PERIOD_CONSTRAINT_DROP
|
|||
ER_TOO_LONG_KEYPART 42000 S1009
|
||||
chi "指定的索引部分太长;最大索引部分长度为 %u 个字节"
|
||||
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
|
||||
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,
|
||||
(thd->db.str ? thd->db.str : "(null)"),
|
||||
wsrep_thd_query(thd));
|
||||
my_error(ER_ERROR_DURING_COMMIT, MYF(0), WSREP_SIZE_EXCEEDED);
|
||||
my_error(ER_TOO_BIG_WRITESET, MYF(0));
|
||||
break;
|
||||
case wsrep::e_deadlock_error:
|
||||
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
|
||||
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_error() &&
|
||||
da->sql_errno() != error &&
|
||||
da->sql_errno() != ER_ERROR_DURING_COMMIT &&
|
||||
da->sql_errno() != ER_LOCK_DEADLOCK))
|
||||
{
|
||||
da->reset_diagnostics_area();
|
||||
|
@ -226,6 +225,9 @@ static inline void wsrep_override_error(THD* thd,
|
|||
switch (ce)
|
||||
{
|
||||
case wsrep::e_error_during_commit:
|
||||
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;
|
||||
case wsrep::e_deadlock_error:
|
||||
|
@ -235,7 +237,7 @@ static inline void wsrep_override_error(THD* thd,
|
|||
wsrep_override_error(thd, ER_QUERY_INTERRUPTED);
|
||||
break;
|
||||
case wsrep::e_size_exceeded_error:
|
||||
wsrep_override_error(thd, ER_ERROR_DURING_COMMIT, status);
|
||||
wsrep_override_error(thd, ER_TOO_BIG_WRITESET);
|
||||
break;
|
||||
case wsrep::e_append_fragment_error:
|
||||
/* 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
|
||||
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)
|
||||
{
|
||||
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) &&
|
||||
wsrep_thd_is_local(thd) &&
|
||||
thd->wsrep_trx().active() &&
|
||||
thd->wsrep_trx().state() != wsrep::transaction::s_committed)
|
||||
{
|
||||
/* @todo CTAS with STATEMENT binlog format and empty result set
|
||||
seems to be committing empty. Figure out why and try to fix
|
||||
elsewhere. */
|
||||
/* Here transaction is either empty (i.e. no changes) or
|
||||
it was CREATE TABLE with no row binlog format or
|
||||
we have already aborted transaction e.g. because max writeset size
|
||||
has been reached. */
|
||||
DBUG_ASSERT(!wsrep_has_changes(thd) ||
|
||||
(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);
|
||||
int ret= wsrep_before_rollback(thd, all) ||
|
||||
wsrep_after_rollback(thd, all) ||
|
||||
|
|
Loading…
Reference in a new issue