From 2d16aa579619e1dc292b4026a7fb24ab2a8b0828 Mon Sep 17 00:00:00 2001 From: "mskold/marty@mysql.com/linux.site" <> Date: Tue, 15 Aug 2006 09:38:21 +0200 Subject: [PATCH] ndb_lock.test, ndb_lock.result: bug #18184 SELECT ... FOR UPDATE does not work..: New test case ha_ndbcluster.h, ha_ndbcluster.cc, NdbConnection.hpp: Fix for bug #21059 Server crashes on join query with large dataset with NDB tables: Releasing operation for each intermediate batch, before next call to trans->execute(NoCommit); --- mysql-test/r/ndb_lock.result | 15 ++++++++++++--- mysql-test/t/ndb_lock.test | 15 +++++++++++++-- ndb/include/ndbapi/NdbConnection.hpp | 3 ++- sql/ha_ndbcluster.cc | 27 +++++++++++++++++++++++++++ sql/ha_ndbcluster.h | 2 ++ 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/ndb_lock.result b/mysql-test/r/ndb_lock.result index 875dcd775e6..c7413949f42 100644 --- a/mysql-test/r/ndb_lock.result +++ b/mysql-test/r/ndb_lock.result @@ -64,17 +64,26 @@ pk u o insert into t1 values (1,1,1); drop table t1; create table t1 (x integer not null primary key, y varchar(32), z integer, key(z)) engine = ndb; -insert into t1 values (1,'one',1), (2,'two',2),(3,"three",3); +insert into t1 values (1,'one',1); begin; select * from t1 where x = 1 for update; x y z 1 one 1 begin; +select * from t1 where x = 1 for update; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +rollback; +rollback; +insert into t1 values (2,'two',2),(3,"three",3); +begin; +select * from t1 where x = 1 for update; +x y z +1 one 1 +select * from t1 where x = 1 for update; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction select * from t1 where x = 2 for update; x y z 2 two 2 -select * from t1 where x = 1 for update; -ERROR HY000: Lock wait timeout exceeded; try restarting transaction rollback; commit; begin; diff --git a/mysql-test/t/ndb_lock.test b/mysql-test/t/ndb_lock.test index e8f7c57ac96..3804782b150 100644 --- a/mysql-test/t/ndb_lock.test +++ b/mysql-test/t/ndb_lock.test @@ -73,7 +73,7 @@ drop table t1; create table t1 (x integer not null primary key, y varchar(32), z integer, key(z)) engine = ndb; -insert into t1 values (1,'one',1), (2,'two',2),(3,"three",3); +insert into t1 values (1,'one',1); # PK access connection con1; @@ -82,11 +82,22 @@ select * from t1 where x = 1 for update; connection con2; begin; -select * from t1 where x = 2 for update; --error 1205 select * from t1 where x = 1 for update; rollback; +connection con1; +rollback; +insert into t1 values (2,'two',2),(3,"three",3); +begin; +select * from t1 where x = 1 for update; + +connection con2; +--error 1205 +select * from t1 where x = 1 for update; +select * from t1 where x = 2 for update; +rollback; + connection con1; commit; diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp index 75c3f80121d..8d7735c9300 100644 --- a/ndb/include/ndbapi/NdbConnection.hpp +++ b/ndb/include/ndbapi/NdbConnection.hpp @@ -163,7 +163,8 @@ class NdbConnection friend class NdbIndexOperation; friend class NdbIndexScanOperation; friend class NdbBlob; - + friend class ha_ndbcluster; + public: /** diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 10240e597bf..a79ffd0907e 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -161,6 +161,7 @@ int execute_no_commit(ha_ndbcluster *h, NdbConnection *trans) if (m_batch_execute) return 0; #endif + h->release_completed_operations(trans); return trans->execute(NoCommit,AbortOnError,h->m_force_send); } @@ -194,6 +195,7 @@ int execute_no_commit_ie(ha_ndbcluster *h, NdbConnection *trans) if (m_batch_execute) return 0; #endif + h->release_completed_operations(trans); return trans->execute(NoCommit, AO_IgnoreError,h->m_force_send); } @@ -2747,6 +2749,25 @@ int ha_ndbcluster::close_scan() if (!cursor) DBUG_RETURN(1); + if (m_lock_tuple) + { + /* + Lock level m_lock.type either TL_WRITE_ALLOW_WRITE + (SELECT FOR UPDATE) or TL_READ_WITH_SHARED_LOCKS (SELECT + LOCK WITH SHARE MODE) and row was not explictly unlocked + with unlock_row() call + */ + NdbOperation *op; + // Lock row + DBUG_PRINT("info", ("Keeping lock on scanned row")); + + if (!(op= m_active_cursor->lockTuple())) + { + m_lock_tuple= false; + ERR_RETURN(trans->getNdbError()); + } + m_ops_pending++; + } m_lock_tuple= false; if (m_ops_pending) { @@ -5350,6 +5371,12 @@ int ha_ndbcluster::write_ndb_file() DBUG_RETURN(error); } +void +ha_ndbcluster::release_completed_operations(NdbConnection *trans) +{ + trans->releaseCompletedOperations(); +} + int ndbcluster_show_status(THD* thd) { diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 313e497f9b5..4a53b4007fe 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -262,6 +262,8 @@ class ha_ndbcluster: public handler void no_uncommitted_rows_init(THD *); void no_uncommitted_rows_reset(THD *); + void release_completed_operations(NdbConnection*); + friend int execute_no_commit(ha_ndbcluster*, NdbConnection*); friend int execute_commit(ha_ndbcluster*, NdbConnection*); friend int execute_no_commit_ie(ha_ndbcluster*, NdbConnection*);