Datastax cassandra 似乎缓存了 preparestatent
Datastax cassandra seem to cache preparestatent
当我的应用程序运行很长时间时,一切正常。但是当我将一列的类型从 int 更改为 text(删除 table 并重新创建)时,我发现了一个异常:
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.load(DefaultCodecRegistry.java:95)
at com.datastax.oss.driver.internal.core.type.codec.registry.DefaultCodecRegistry.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:
the session has a built-in cache, it’s OK to prepare the same string twice.
...
Note that caching is based on: the query string exactly as you provided it: the driver does not perform any kind of trimming or sanitizing.
我不能 100% 确定源代码,但缓存中的相关条目可能不会在 table 删除时被清除。我建议打开 JIRA against Java driver,虽然这样的类型更改通常不被真正推荐 - 最好引入新类型的新字段,即使可以 re-create table.
没错。准备好的语句被缓存——这是使准备好的语句在被重用时更高效的优化,因为它们只需要准备一次(查询不需要再次解析)。
但我怀疑您案例中的潜在问题是您的查询涉及 SELECT *
。最佳实践建议(无论您使用的是什么数据库)是 显式 枚举您从 table.
检索的列
在准备好的语句中,每个列都绑定到一个数据类型。当您通过 adding/dropping 列更改架构时,列的顺序(及其数据类型)不再与结果集的数据类型匹配,因此您最终会遇到驱动程序获得 int
当它期待 text
或 vice-versa 时。干杯!
当我的应用程序运行很长时间时,一切正常。但是当我将一列的类型从 int 更改为 text(删除 table 并重新创建)时,我发现了一个异常:
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.load(DefaultCodecRegistry.java:95)
at com.datastax.oss.driver.internal.core.type.codec.registry.DefaultCodecRegistry.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:
the session has a built-in cache, it’s OK to prepare the same string twice.
...
Note that caching is based on: the query string exactly as you provided it: the driver does not perform any kind of trimming or sanitizing.
我不能 100% 确定源代码,但缓存中的相关条目可能不会在 table 删除时被清除。我建议打开 JIRA against Java driver,虽然这样的类型更改通常不被真正推荐 - 最好引入新类型的新字段,即使可以 re-create table.
没错。准备好的语句被缓存——这是使准备好的语句在被重用时更高效的优化,因为它们只需要准备一次(查询不需要再次解析)。
但我怀疑您案例中的潜在问题是您的查询涉及 SELECT *
。最佳实践建议(无论您使用的是什么数据库)是 显式 枚举您从 table.
在准备好的语句中,每个列都绑定到一个数据类型。当您通过 adding/dropping 列更改架构时,列的顺序(及其数据类型)不再与结果集的数据类型匹配,因此您最终会遇到驱动程序获得 int
当它期待 text
或 vice-versa 时。干杯!