驱动程序中的预处理语句缓存问题

驱动程序中的预处理语句缓存问题

本文介绍了Cassandra Csharp 驱动程序中的预处理语句缓存问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我相信我在 Cassandra csharp 驱动程序(版本 2.7.3)的 StatementFactory 中缓存准备好的语句的逻辑中发现了一个错误.这是用例.

I believe I have found a bug with the logic of how a prepared statement is cached in the StatementFactory in the Cassandra csharp driver (version 2.7.3). Here is the use case.

Guid key = Guid.NewGuid(); // your key

ISession session_foo = new Session("foo"); //This is pseudo code
ISession session_bar = new Session("bar");

var foo_mapper = new Mapper(session_foo); //table foo_bar
var bar_mapper = new Mapper(session_bar); //table foo_bar

await Task.WhenAll(
   foo_mapper.DeleteAsync<Foo>("WHERE id = ?", key),
   bar_mapper.DeleteAsync<Bar>("WHERE id = ?", key));

我们发现运行这个delete后,只有第一个请求成功.深入StatementFactory的源代码后

We have found that after running this deletes, only the first request is succeeding. After diving in the the source code of StatementFactory

public Task<Statement> GetStatementAsync(ISession session, Cql cql)
    {
        if (cql.QueryOptions.NoPrepare)
        {
            // Use a SimpleStatement if we're not supposed to prepare
            Statement statement = new SimpleStatement(cql.Statement, cql.Arguments);
            SetStatementProperties(statement, cql);
            return TaskHelper.ToTask(statement);
        }
        return _statementCache
            .GetOrAdd(cql.Statement, session.PrepareAsync)
            .Continue(t =>
            {
                if (_statementCache.Count > MaxPreparedStatementsThreshold)
                {
                    Logger.Warning(String.Format("The prepared statement cache contains {0} queries. Use parameter markers for queries. You can configure this warning threshold using MappingConfiguration.SetMaxStatementPreparedThreshold() method.", _statementCache.Count));
                }
                Statement boundStatement = t.Result.Bind(cql.Arguments);
                SetStatementProperties(boundStatement, cql);
                return boundStatement;
            });
    }

可以看到缓存只使用了cql语句.在我们的例子中,我们在不同的键空间(又名会话)中有相同的表名.我们在两个查询中的 cql 语句看起来相同.即 DELETE FROM foo_bar WHERE id =?.

You can see that the cache only uses the cql statement. In our case, we have the same table names in different keyspaces (aka sessions). Our cql statement in both queries look the same. ie DELETE FROM foo_bar WHERE id =?.

如果我不得不猜测,我会说一个简单的解决方法是将 cql 语句和键空间组合在一起作为缓存键.

If I had to guess, I would say that a simple fix would be to combine the cql statement and keyspace together as the cache key.

有没有其他人遇到过这个问题?

Has anyone else run into this issue before?

推荐答案

作为一个简单的解决方法,我使用 DoNotPrepare 跳过缓存

As a simple workaround, I am skipping the cache by using the DoNotPrepare

await _mapper.DeleteAsync<Foo>(Cql.New("WHERE id = ?", key).WithOptions(opt => opt.DoNotPrepare()));

我还发现了一个未解决的问题 Datastax

I also found an open issue with Datastax

这篇关于Cassandra Csharp 驱动程序中的预处理语句缓存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 08:43