From: Jan Wedvik Date: April 25 2012 9:23am Subject: bzr push into mysql-5.5-cluster-7.2 branch (jan.wedvik:3900 to 3901) Bug#13984817 List-Archive: http://lists.mysql.com/commits/143651 X-Bug: 13984817 Message-Id: <20120425092340.985511458@atum17.no.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3901 Jan Wedvik 2012-04-25 Fix for Bug#13984817 (DATA NODE CRASHES DURING 7.0.16 TO 7.2.4 ONLINE UPGRADE/DOWNGRADE). This commit adds versions check that will prevent or abort execution of pushed queries if there are data nodes that do not support this (i.e. nodes running software version < 7.2). modified: sql/ha_ndbcluster.cc storage/ndb/include/ndb_version.h.in storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp storage/ndb/src/ndbapi/NdbQueryOperation.cpp 3900 Ole John Aske 2012-04-25 Fix for Bug#13990924 '64865: LARGE WHERE IN WITH SPJ LEADS TO CLUSTER SHUTDOWN' As part of developing the SPJ feature, the macro DEBUG_CRASH() was used several places where an error occured. I assume the intention has been to only (permanently) use this macro in places where we did not handle the error gracefully. However, use of this macro has been exaggerated such that it is even used when we catch API errors in the SPJ block which we *do* handle by returning an error code. Furthermore this macro was defined as ndbrequire(false), such that we always crash when we hit it - even in GA code. For this particular bug, the SPJ block detected the condition: err = DbspjErr::QueryNodeParametersTooBig; if (unlikely(param_len >= NDB_ARRAY_SIZE(m_buffer1))) { DEBUG_CRASH(); goto error; } Furthermore, there was a check in the SPJ API which was intended to prevent sending 'too big' parameters to the SPJ node. However, this check was 'size <= 64k', while the actual size limit in SPJ block was 32K! This fix: - Redefined DEBUG_CRASH to an ndbassert(false) which will not fail in production code. - Replaced lots of these DEBUG_CRASH() with a jam() in places where we do handle the error. - Increase buffer sizes in SPJ block from 32K -> 64K. modified: mysql-test/suite/ndb/r/ndb_join_pushdown_default.result mysql-test/suite/ndb/t/ndb_join_pushdown.inc storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp === modified file 'sql/ha_ndbcluster.cc' --- a/sql/ha_ndbcluster.cc 2012-04-18 11:34:20 +0000 +++ b/sql/ha_ndbcluster.cc 2012-04-25 09:22:21 +0000 @@ -14426,8 +14426,10 @@ int ndbcluster_make_pushed_join(handlert DBUG_ENTER("ndbcluster_make_pushed_join"); (void)ha_ndb_ext; // prevents compiler warning. *pushed= 0; - - if (THDVAR(thd, join_pushdown)) + + if (THDVAR(thd, join_pushdown) && + // Check for online upgrade/downgrade. + ndb_join_pushdown(g_ndb_cluster_connection->get_min_db_version())) { ndb_pushed_builder_ctx pushed_builder(*plan); === modified file 'storage/ndb/include/ndb_version.h.in' --- a/storage/ndb/include/ndb_version.h.in 2012-02-23 15:41:31 +0000 +++ b/storage/ndb/include/ndb_version.h.in 2012-04-25 09:22:21 +0000 @@ -756,4 +756,22 @@ ndbd_fixed_lookup_query_abort(Uint32 x) return x >= NDBD_FIXED_LOOKUP_QUERY_ABORT_72; } +/** + * NOTE1: + * Even though pushed join support wasn't GA intil 7.2.4 + * we claim support for it in all 7.2.x versions. + * NOTE2: + * By a mistake this online upgrade check was not + * added until version 7.2.6 + */ +#define NDBD_JOIN_PUSHDOWN NDB_MAKE_VERSION(7,2,0) + +static +inline +int +ndb_join_pushdown(Uint32 x) +{ + return x >= NDBD_JOIN_PUSHDOWN; +} + #endif === modified file 'storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp' --- a/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp 2012-04-25 06:24:54 +0000 +++ b/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp 2012-04-25 09:22:21 +0000 @@ -3198,6 +3198,15 @@ Dbspj::lookup_send(Signal* signal, err = DbspjErr::NodeFailure; break; } + // Test for online downgrade. + if (unlikely(!ndb_join_pushdown(getNodeInfo(Tnode).m_version))) + { + jam(); + releaseSections(handle); + err = 4003; // Function not implemented. + break; + } + if (unlikely(!c_alive_nodes.get(Tnode))) { jam(); @@ -5612,6 +5621,15 @@ Dbspj::scanIndex_send(Signal* signal, req->senderData = fragPtr.i; req->fragmentNoKeyLen = fragPtr.p->m_fragId; + // Test for online downgrade. + if (unlikely(ref != 0 && + !ndb_join_pushdown(getNodeInfo(refToNode(ref)).m_version))) + { + jam(); + err = 4003; // Function not implemented. + break; + } + if (prune) { jam(); === modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp' --- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2012-04-24 14:41:37 +0000 +++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2012-04-25 09:22:21 +0000 @@ -1856,6 +1856,14 @@ start_failure: abortErrorLab(signal); return; } + case 66: + { + jam(); + /* Function not implemented yet */ + terrorCode = 4003; + abortErrorLab(signal); + return; + } default: jam(); systemErrorLab(signal, __LINE__); @@ -2924,6 +2932,17 @@ void Dbtc::execTCKEYREQ(Signal* signal) return; } + if (unlikely(TViaSPJFlag && + /* Check that all nodes can handle SPJ requests. */ + !ndb_join_pushdown(getNodeVersionInfo().m_type[NodeInfo::DB] + .m_min_version))) + { + jam(); + releaseSections(handle); + TCKEY_abort(signal, 66); + return; + } + /* KeyInfo and AttrInfo are buffered in segmented sections * If they arrived in segmented sections then there's nothing to do * If they arrived in short signals then they are appended into @@ -10506,6 +10525,16 @@ void Dbtc::execSCAN_TABREQ(Signal* signa goto SCAN_TAB_error; } + if (unlikely (ScanTabReq::getViaSPJFlag(ri) && + /* Check that all nodes can handle SPJ requests. */ + !ndb_join_pushdown(getNodeVersionInfo().m_type[NodeInfo::DB] + .m_min_version))) + { + jam(); + errCode = 4003; // Function not implemented + goto SCAN_TAB_error; + } + ptrAss(tabptr, tableRecord); if ((aiLength == 0) || (!tabptr.p->checkTable(schemaVersion)) || === modified file 'storage/ndb/src/ndbapi/NdbQueryOperation.cpp' --- a/storage/ndb/src/ndbapi/NdbQueryOperation.cpp 2012-04-18 11:34:20 +0000 +++ b/storage/ndb/src/ndbapi/NdbQueryOperation.cpp 2012-04-25 09:22:21 +0000 @@ -1907,6 +1907,12 @@ NdbQueryImpl::buildQuery(NdbTransaction& const NdbQueryDefImpl& queryDef) { assert(queryDef.getNoOfOperations() > 0); + // Check for online upgrade/downgrade. + if (unlikely(!ndb_join_pushdown(trans.getNdb()->getMinDbNodeVersion()))) + { + trans.setOperationErrorCodeAbort(Err_FunctionNotImplemented); + return NULL; + } NdbQueryImpl* const query = new NdbQueryImpl(trans, queryDef); if (unlikely(query==NULL)) { trans.setOperationErrorCodeAbort(Err_MemoryAlloc); No bundle (reason: useless for push emails).