具有轻量级事务的Cassandra Datastax BatchStatement

时间:2014-05-14 18:29:56

标签: cassandra datastax

我在使用Datastax java驱动程序组合BatchStatement和Lightweight Transactions时遇到了困难。

请考虑以下事项:

String batch = 
"BEGIN BATCH " 
+ "Update mykeyspace.mytable set record_version = 102 where id = '" + id + "' if record_version = 101; 
" <additional batched statements>
+ "APPLY BATCH";

Row row = session.execute(batch).one();
if (! row.getBool("[applied]")) {
    throw new RuntimeException("Optimistic Lock Failure!");
}

此功能按预期运行,并指示我的轻量级事务是否成功以及我的批处理是否已应用。一切都很好。但是,如果我使用BatchStatement尝试相同的事情,我会遇到几个问题:

- 忽略我的轻量级事务“if”子句,并始终应用更新

- “Row”结果为null,因此无法执行最后的row.getBool(“[applied]”)检查。

String update = "Update mykeyspace.mytable set record_version = ? where id = ? if record_version = ?";
PreparedStatement pStmt = getSession().prepare(update);
BatchStatement batch = new BatchStatement();
batch.add(new BoundStatement(pStmt).bind(newVersion, id, oldVersion));

Row row = session.execute(batch).one();                     <------ Row is null!
if (! row.getBool("[applied]")) {
    throw new RuntimeException("Optimistic Lock Failure!");
}

我这样做错了吗?或者这是数据存储BatchStatement的限制吗?

3 个答案:

答案 0 :(得分:4)

我遇到了同样的问题。我昨天开了一张DataStax支持票,收到了以下答案:

  

目前不支持BATCH中作为PreparedStatements的轻量级事务。这就是您遇到此问题的原因。

     

立即路线图中没有任何内容可以在Cassandra中包含此功能。

这表明取消PreparedStatement将解决问题。我会亲自尝试,但还没有。

[更新]

我一直在努力解决这个问题。基于之前的反馈,我认为限制是使用PreparedStatement进行条件更新。

我尝试将代码更改为不使用PreparedStatement,但在使用包含RegularStatement而不是PreparedStatement的BatchStatement时仍然无效。

BatchStatement batchStatement = new BatchStatement(); 
batchStatement.add(conditionalRegularStatement); 
session.executeQuery(batchStatement);

他们唯一似乎工作的是使用包含批处理的原始查询字符串执行executeQuery。

session.executeQuery("BEGIN BATCH " + conditionalRegularStatement.getQueryString() + " APPLY BATCH"); 

答案 1 :(得分:3)

更新

此问题已在CASSANDRA-7337中解决,该问题已在C * 2.0.9中修复。

最新的DataStax Enterprise现在是2.0.11。如果您看到此问题==&gt;升级!

答案 2 :(得分:0)

第二个代码片段对我来说并不合适(没有构造函数带有字符串,或者您错过了准备好的语句)。

您可以尝试以下方式:

String update = "Update mykeyspace.mytable set record_version = ? where id = ? if record_version = ?";
PreparedStatement pStmt = session.prepare(update);
BatchStatement batch = new BatchStatement();
batch.add(pStmt.bind(newVersion, id, recordVersion));

Row row = session.execute(batch).one();
if (! row.getBool("[applied]")) {
    throw new RuntimeException("Optimistic Lock Failure!");
}