【问题标题】:Cassandra Datastax BatchStatement with Lightweight Transactions具有轻量级事务的 Cassandra Datastax BatchStatement
【发布时间】:2014-07-02 23:09:36
【问题描述】:

我在使用 Datastax java 驱动程序结合 BatchStatement 和轻量级事务时遇到了困难。

考虑以下几点:

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" 结果为空,无法执行最后的 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!");
}

我做错了吗?或者这是 datastax BatchStatement 的限制?

【问题讨论】:

    标签: cassandra datastax


    【解决方案1】:

    第二个代码 sn-p 在我看来不正确(没有构造函数采用字符串,或者您错过了准备好的语句)。

    您可以尝试以下方法吗:

    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!");
    }
    

    【讨论】:

    • 是的,很抱歉 - 准备好的语句的实例化不清楚,因为它是作为全局成员创建的,我未能在示例代码中演示这一点。基本上,我的原始代码完全按照您的建议进行,除了它还在 PreparedStatement 周围合并了一个 BoundStatement 包装器。我用一个简单的准备好的语句(没有 BoundStatement)尝试了你的建议,但发现了同样的问题。
    【解决方案2】:

    我遇到了同样的问题。我昨天开了一张 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"); 
    

    【讨论】:

    • 非常感谢您运行过去的 DataStax...尽管我认为他们的回答非常不幸。我认为这个用例对于轻量级事务的使用非常重要。
    • 现在好像有一个错误提交:datastax-oss.atlassian.net/browse/JAVA-337
    【解决方案3】:

    更新:

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

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

    【讨论】:

    • 好发现!如果我每次在这里告诉别人升级 Cassandra 是他们最好的计划时都能得到一美元,我就不必工作了。
    猜你喜欢
    • 1970-01-01
    • 2018-05-08
    • 2022-01-08
    • 1970-01-01
    • 2021-10-17
    • 2014-09-19
    • 2016-10-06
    • 2019-01-12
    • 2014-05-04
    相关资源
    最近更新 更多