datastax cassandra似乎在缓存preparestatent

oogrdqng  于 2021-06-10  发布在  Cassandra
关注(0)|答案(2)|浏览(558)

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

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

此异常偶尔出现。我使用preparedstatement来执行查询,我认为它是从datastax的驱动程序缓存的。
我使用的是aws密钥空间(cassandra版本3.11.2),datastax驱动程序4.6。这是我的application.conf:

  1. basic.request {
  2. timeout = 5 seconds
  3. consistency = LOCAL_ONE
  4. }
  5. advanced.connection {
  6. max-requests-per-connection = 1024
  7. pool {
  8. local.size = 1
  9. remote.size = 1
  10. }
  11. }
  12. advanced.reconnect-on-init = true
  13. advanced.reconnection-policy {
  14. class = ExponentialReconnectionPolicy
  15. base-delay = 1 second
  16. max-delay = 60 seconds
  17. }
  18. advanced.retry-policy {
  19. class = DefaultRetryPolicy
  20. }
  21. advanced.protocol {
  22. version = V4
  23. }
  24. advanced.heartbeat {
  25. interval = 30 seconds
  26. timeout = 1 second
  27. }
  28. advanced.session-leak.threshold = 8
  29. advanced.metadata.token-map.enabled = false
  30. }
cuxqih21

cuxqih211#

没错。预处理语句是缓存的——这是一种优化方法,它使预处理语句在重用时更加高效,因为它们只需要准备一次(查询不需要再次解析)。
但我怀疑你的问题在于你的询问涉及 SELECT * . 最佳实践建议(不管您使用的是哪个数据库)是显式枚举从表中检索的列。
在prepared语句中,每一列都绑定到一个数据类型。当您通过添加/删除列来更改模式时,列的顺序(及其数据类型)不再与结果集的数据类型匹配,因此您最终会遇到驱动程序获得 int 当它期待一个 text 反之亦然。干杯!

hs1rzwqc

hs1rzwqc2#

是的,java驱动程序4.x缓存准备好的语句-这与驱动程序3.x有所不同。根据文件:
会话有一个内置的缓存,可以准备两次相同的字符串。
...
请注意,缓存的基础是:查询字符串与您提供的完全相同:驱动程序不执行任何类型的修剪或清理。
我不确定100%的源代码,但缓存中的相关条目可能不会在表上清除掉。我建议打开jira-against-java驱动程序,尽管这样的类型更改通常不太推荐——最好是使用新类型引入新字段,即使可以重新创建表。

相关问题