当前位置: 首页 > 知识库问答 >
问题:

Datastax Cassandra似乎缓存了准备状态

澹台岳
2023-03-14

当我的应用程序长时间运行时,一切都会正常运行。但当我将列类型从int更改为text(删除表并重新创建)时,我发现了一个异常:

com.datastax.oss.driver.api.core.type.codec.CodecNotFoundException: Codec not found for requested operation: [INT <-> java.lang.String]
    at com.datastax.oss.driver.internal.core.type.codec.registry.CachingCodecRegistry.createCodec(CachingCodecRegistry.java:609)
    at com.datastax.oss.driver.internal.core.type.codec.registry.DefaultCodecRegistry$1.load(DefaultCodecRegistry.java:95)
    at com.datastax.oss.driver.internal.core.type.codec.registry.DefaultCodecRegistry$1.load(DefaultCodecRegistry.java:92)
    at com.datastax.oss.driver.shaded.guava.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3527)
    at com.datastax.oss.driver.shaded.guava.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2276)
    at com.datastax.oss.driver.shaded.guava.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2154)
    at com.datastax.oss.driver.shaded.guava.common.cache.LocalCache$Segment.get(LocalCache.java:2044)
    at com.datastax.oss.driver.shaded.guava.common.cache.LocalCache.get(LocalCache.java:3951)
    at com.datastax.oss.driver.shaded.guava.common.cache.LocalCache.getOrLoad(LocalCache.java:3973)
    at com.datastax.oss.driver.shaded.guava.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4957)
    at com.datastax.oss.driver.shaded.guava.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4963)
    at com.datastax.oss.driver.internal.core.type.codec.registry.DefaultCodecRegistry.getCachedCodec(DefaultCodecRegistry.java:117)
    at com.datastax.oss.driver.internal.core.type.codec.registry.CachingCodecRegistry.codecFor(CachingCodecRegistry.java:215)
    at com.datastax.oss.driver.api.core.data.SettableByIndex.set(SettableByIndex.java:132)
    at com.datastax.oss.driver.api.core.data.SettableByIndex.setString(SettableByIndex.java:338)

这个异常偶尔会出现。我正在使用准备语句执行查询,我认为它是从DataStax的驱动程序缓存的。

我正在使用AWS Keyspace(Cassandra版本3.11.2),DataStax驱动程序4.6。这是我的application.conf:

  basic.request {
    timeout = 5 seconds
    consistency = LOCAL_ONE
  }
  advanced.connection {
    max-requests-per-connection = 1024
    pool {
      local.size = 1
      remote.size = 1
    }
  }
  advanced.reconnect-on-init = true
  advanced.reconnection-policy {
    class = ExponentialReconnectionPolicy
    base-delay = 1 second
    max-delay = 60 seconds
  }
  advanced.retry-policy {
    class = DefaultRetryPolicy
  }
  advanced.protocol {
    version = V4
  }
  advanced.heartbeat {
   interval = 30 seconds
   timeout = 1 second
  }
  advanced.session-leak.threshold = 8
  advanced.metadata.token-map.enabled = false
}

共有2个答案

陶树
2023-03-14

没错。准备好的语句被缓存——如果准备好的语句被重用,这种优化会使它们更高效,因为它们只需要准备一次(查询不需要再次解析)。

但我怀疑您案例中的潜在问题是您的查询涉及 SELECT *。最佳做法建议(无论使用哪种数据库)是显式枚举要从表中检索的列。

在准备好的语句中,每一列都绑定到一个数据类型。当您通过添加/删除列来更改架构时,列的顺序(及其数据类型)不再与结果集的数据类型匹配,因此您最终会遇到驱动程序在期望text时获得int的情况,反之亦然。干杯!

万俟宜修
2023-03-14

是的,Java驱动程序4. x缓存准备好的语句-它与驱动程序3. x不同。从留档:

会话具有内置缓存,可以准备两次相同的字符串。

...

请注意,缓存基于:与您提供的查询字符串完全相同:驱动程序不执行任何类型的修剪或清理。

我不能百分之百确定源代码,但是缓存中的相关条目可能不会在表拖放中清除。我建议打开JIRAJava驱动程序,尽管这种类型更改通常不太推荐——最好用新类型引入新字段,即使可以重新创建表。

 类似资料:
  • 防止在ASP.NET MVC中对使用属性的特定操作进行缓存 ASP.NET MVC如何禁用自动缓存选项?

  • 我一直在读一些较新的JDBC连接池(如Tomcat)不支持客户端语句池。我已经读到,这是因为大多数JDBC驱动程序都维护自己的语句缓存。然而,我不认为PostgreSQL会发生这种情况。 我说的对吗?如果是这样,我应该使用一个连接池来缓存准备好的语句,以获得最佳的批插入性能吗? 谢谢

  • 我读到MySQL不支持服务器端查询计划缓存。所以如果我想使用PreparedStatements来获得性能优势,我能做的就是在JDBC连接中启用语句缓存。因此,根据文档,它将允许缓存每个连接基础上准备好的语句。 与如果MySQL有服务器端查询计划缓存相比,JDBC连接的PreparedStatement缓存的性能增益是什么?因此,如果PreparedStatement确实在物理连接的缓存中找到,这

  • 以上代码,点击 checkbox 后(此时 run_task 还未完成)快速再次点击,run_task 会执行两次,请问大家这是为什么呢?

  • 问题内容: 我正在比较测试程序上的两个变体。两者都在具有四个内核的计算机上以4线程运行。 在“模式1”下,我非常类似于执行程序服务来使用池。我把一堆任务扔了进去。与普通的固定线程执行器服务相比,我获得了更好的性能(即使有对Lucene的调用,该调用在其中执行了一些I / O)。 这里没有分而治之。从字面上看,我知道 在“模式2”中,我向池提交一个任务,然后在该任务中调用ForkJoinTask.i

  • 问题内容: 如果我在节点中编写以下程序: 然后在服务器上单击两次,在服务器上看到两次- 我不确定为什么单个HTTP请求导致两次执行。 问题答案: 那是正常现象-您的浏览器拨打了多个电话。 例如,大多数浏览器都会呼叫来获取。 尝试记录网址: 然后您会看到正在调用的内容。