Skip to content

Commit cf0162a

Browse files
author
Priyanka Sangam
committed
Bug #25476474 SIGNAL 11 AT HA_NDBCLUSTER::EXEC_BULK_UPDATE
A bulk update is executed by reading records and executing a transaction on the set of records. The transaction is started while reading the set of records. In this case, the transaction start fails. The transaction execution code then attempts to dereference the NULL transaction pointer, which causes a segfault. The mysql update function does not exit on fatal errors. The approach is to save all errors, continue execution and evaluate success/failure after the execution completes. With this approach, it is not guaranteed that the necessary init work is successfully completed before calling the bulk update executor. So it is necessary to have more error-handling in the ndb bulk update executor. Fixed by adding some error-handling in the ndb bulk update executor.
1 parent 7b43e09 commit cf0162a

File tree

4 files changed

+62
-1
lines changed

4 files changed

+62
-1
lines changed

mysql-test/suite/ndb/r/ndb_err4012.result

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,18 @@ Warning 1297 Got temporary error 4013 'Request timed out in waiting for node fai
308308
Error 1297 Got temporary error 4013 'Request timed out in waiting for node failure' from NDBCLUSTER
309309
SET SESSION debug=@save_debug;
310310
drop table t1;
311+
# mysqld gets timeout error 4009 while creating transaction for bulk update
312+
create table t1(id int primary key, val int) engine=ndb;
313+
insert into t1 values(1,1), (2,2), (3,3), (4,4), (5,5);
314+
set @save_debug = @@session.debug;
315+
SET SESSION debug="+d,ndb_start_transaction_fail";
316+
update t1 set val = 11111 where id > 0;
317+
ERROR HY000: Got error 4009 'Cluster Failure' from NDBCLUSTER
318+
show warnings;
319+
Level Code Message
320+
Warning 1296 Got error 4009 'Cluster Failure' from NDB
321+
Error 1296 Got error 4009 'Cluster Failure' from NDBCLUSTER
322+
Warning 1296 Got error 4009 'Cluster Failure' from NDB
323+
Error 1296 Got error 4009 'Cluster Failure' from NDBCLUSTER
324+
SET SESSION debug=@save_debug;
325+
drop table t1;

mysql-test/suite/ndb/t/ndb_err4012.test

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,14 @@ show create table t1;
310310
show warnings;
311311
SET SESSION debug=@save_debug;
312312
drop table t1;
313+
314+
--echo # mysqld gets timeout error 4009 while creating transaction for bulk update
315+
create table t1(id int primary key, val int) engine=ndb;
316+
insert into t1 values(1,1), (2,2), (3,3), (4,4), (5,5);
317+
set @save_debug = @@session.debug;
318+
SET SESSION debug="+d,ndb_start_transaction_fail";
319+
--error 1296
320+
update t1 set val = 11111 where id > 0;
321+
show warnings;
322+
SET SESSION debug=@save_debug;
323+
drop table t1;

sql/ha_ndbcluster.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6063,9 +6063,35 @@ int ha_ndbcluster::exec_bulk_update(uint *dup_key_found)
60636063
DBUG_ENTER("ha_ndbcluster::exec_bulk_update");
60646064
*dup_key_found= 0;
60656065

6066+
/* If a fatal error is encountered during an update op, the error
6067+
* is saved and exec continues. So exec_bulk_update may be called
6068+
* even when init functions fail. Check for error conditions like
6069+
* an uninit'ed transaction.
6070+
*/
6071+
if(unlikely(!m_thd_ndb->trans))
6072+
{
6073+
DBUG_PRINT("exit", ("Transaction was not started"));
6074+
int error = 0;
6075+
ERR_SET(m_thd_ndb->ndb->getNdbError(), error);
6076+
DBUG_RETURN(error);
6077+
}
6078+
60666079
// m_handler must be NULL or point to _this_ handler instance
60676080
assert(m_thd_ndb->m_handler == NULL || m_thd_ndb->m_handler == this);
60686081

6082+
/*
6083+
* Normal bulk update execution, driven by mysql_update() in sql_update.cc
6084+
* - read_record calls start_transaction and inits m_thd_ndb->trans.
6085+
* - ha_bulk_update calls ha_ndbcluster::bulk_update_row().
6086+
* - ha_ndbcluster::bulk_update_row calls ha_ndbcluster::ndb_update_row().
6087+
* with flag is_bulk_update = 1.
6088+
* - ndb_update_row sets up update, sets various flags and options,
6089+
* but does not execute_nocommit() because of batched exec.
6090+
* - after read_record processes all rows, exec_bulk_update checks for
6091+
* rbwr and does an execute_commit() if rbwr enabled. If rbwr is
6092+
* enabled, exec_bulk_update does an execute_nocommit().
6093+
* - if rbwr not enabled, execute_commit() done in ndbcluster_commit().
6094+
*/
60696095
if (m_thd_ndb->m_handler &&
60706096
m_read_before_write_removal_possible)
60716097
{

storage/ndb/src/ndbapi/Ndb.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
2+
Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
33
44
This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -945,6 +945,15 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId, Uint32 instance)
945945
DBUG_ENTER("Ndb::startTransactionLocal");
946946
DBUG_PRINT("enter", ("nodeid: %d", nodeId));
947947

948+
#ifdef VM_TRACE
949+
DBUG_EXECUTE_IF("ndb_start_transaction_fail",
950+
{
951+
/* Cluster failure */
952+
theError.code = 4009;
953+
DBUG_RETURN(0);
954+
};);
955+
#endif
956+
948957
if(unlikely(theRemainingStartTransactions == 0))
949958
{
950959
theError.code = 4006;

0 commit comments

Comments
 (0)