如何解决Datastax Cassandra似乎缓存了preparestatent
当我的应用程序长时间运行时,一切也正常运行。但是,当我将类型从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)
该异常偶尔出现。我正在使用PreparedStatement执行查询,我认为它是从DataStax的驱动程序缓存的。
我正在使用AWS Keyspaces(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
}
解决方法
是的,Java驱动程序4.x缓存了准备好的语句-与驱动程序3.x有所不同。来自documentation:
该会话具有内置的缓存,可以两次准备相同的字符串。
...
请注意,缓存基于:与您提供的查询字符串完全相同:驱动程序不执行任何修整或清理操作。
我不确定源代码的100%,但是缓存中的相关条目可能无法在表放置时清除。我建议打开JIRA against Java driver,尽管通常不建议这样更改类型-最好使用新类型引入新字段,即使可以重新创建表也是如此。
,是的。缓存已准备好的语句-通过优化,如果重新使用已准备好的语句,效率更高,因为它们只需要准备一次(查询无需再次解析)。
但是我怀疑您的情况的根本问题是您的查询涉及SELECT *
。最佳实践建议(无论使用何种数据库)都是明确枚举要从表中检索的列。
在prepared语句中,每个列都绑定到一个数据类型。当您通过添加/删除列来更改架构时,列的顺序(及其数据类型)将不再与结果集的数据类型匹配,因此您最终会遇到以下情况:驱动程序获取int
期望text
,反之亦然。干杯!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。