summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/ndb_lock.result15
-rw-r--r--mysql-test/t/ndb_lock.test15
-rw-r--r--ndb/include/ndbapi/NdbConnection.hpp4
-rw-r--r--sql/ha_ndbcluster.cc34
-rw-r--r--sql/ha_ndbcluster.h2
5 files changed, 64 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 = 2 for update;
+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
-2 two 2
+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
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,12 +82,23 @@ 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;
# table scan
diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp
index 75c3f80121d..c367e156f08 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:
/**
@@ -675,6 +676,7 @@ private:
// optim: any blobs
bool theBlobFlag;
Uint8 thePendingBlobOps;
+ inline bool hasBlobOperation() { return theBlobFlag; }
static void sendTC_COMMIT_ACK(NdbApiSignal *,
Uint32 transId1, Uint32 transId2,
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 10240e597bf..e4c20de2390 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,19 @@ int ha_ndbcluster::write_ndb_file()
DBUG_RETURN(error);
}
+void
+ha_ndbcluster::release_completed_operations(NdbConnection *trans)
+{
+ if (trans->hasBlobOperation())
+ {
+ /* We are reading/writing BLOB fields,
+ releasing operation records is unsafe
+ */
+ return;
+ }
+ 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*);