diff options
author | Teemu Ollakka <teemu.ollakka@galeracluster.com> | 2020-10-30 13:48:21 +0200 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2020-11-03 09:11:04 +0200 |
commit | 4489b66afbe2f8f589d83ea77e36cc879117f1ad (patch) | |
tree | cf3658c6f4a94d6fefa75a79288ac797419bc210 /sql/sql_prepare.cc | |
parent | 9e14a2df8c03bb06336fb5c174af52da00fe70e9 (diff) | |
download | mariadb-git-4489b66afbe2f8f589d83ea77e36cc879117f1ad.tar.gz |
MDEV-23872 Crash in galera::TrxHandle::state()
Prepared statements which were run over binary protocol crashed
a server if the statement did not have CF_PS_ARRAY_BINDING_OPTIMIZED
flag and the statement was executed in bulk mode and a BF abort occrurred.
This was because the bulk execution resulted in several statements without
calling wsrep_after_statement() between, which confused wsrep transaction
state tracking.
As a fix, call wsrep_after_statement() in bulk loop after each execution
if CF_PS_ARRAY_BINDING_OPTIMIZED is not set.
Reviewed-by: Jan Lindström <jan.lindstrom@mariadb.com>
Diffstat (limited to 'sql/sql_prepare.cc')
-rw-r--r-- | sql/sql_prepare.cc | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 518df6eb6a2..bf011bd2236 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -122,7 +122,10 @@ When one supplies long data for a placeholder: #include "lock.h" // MYSQL_OPEN_FORCE_SHARED_MDL #include "sql_handler.h" #include "transaction.h" // trans_rollback_implicit +#ifdef WITH_WSREP #include "wsrep_mysqld.h" +#include "wsrep_trans_observer.h" +#endif /* WITH_WSREP */ /** A result class used to send cursor rows using the binary protocol. @@ -4414,6 +4417,23 @@ reexecute: thd->m_reprepare_observer= NULL; +#ifdef WITH_WSREP + if (!(sql_command_flags[lex->sql_command] & CF_PS_ARRAY_BINDING_OPTIMIZED) && + WSREP(thd)) + { + if (wsrep_after_statement(thd)) + { + /* + Re-execution success is unlikely after an error from + wsrep_after_statement(), so retrun error immediately. + */ + thd->get_stmt_da()->reset_diagnostics_area(); + wsrep_override_error(thd, thd->wsrep_cs().current_error(), + thd->wsrep_cs().current_error_status()); + } + } + else +#endif /* WITH_WSREP */ if (unlikely(error) && (sql_command_flags[lex->sql_command] & CF_REEXECUTION_FRAGILE) && !thd->is_fatal_error && !thd->killed && |