Search code examples
cassandradatastax-java-driver

Datastax cassandra seem to cache preparestatent


When my application runs a long time, everything works as well. But when I change type a column from int to text(Drop table and recreate), I caught a Exception:

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)

This exception appears occasionally. I'm using PreparedStatement to execute the query, I think it is cached from DataStax's driver.

I'm using AWS Keyspaces(Cassandra version 3.11.2), DataStax driver 4.6. Here is my 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
}

Solution

  • Yes, Java driver 4.x caches prepared statement - it's a difference from the driver 3.x. From 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.

    I'm not sure 100% about the source code, but the relevant entries in the cache may not be cleared up on the table drop. I suggest to open the JIRA against Java driver, although, such type changes are often not really recommended - it's better to introduce new field with new type, even if it's possible to re-create table.