Datastax cassandra, похоже, кэширует preparestatent

#cassandra #datastax-java-driver

#cassandra #datastax-java-driver

Вопрос:

Когда мое приложение работает долгое время, все также работает. Но когда я меняю тип столбца с 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. Вот мое приложение.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
}
  

Ответ №1:

Да, драйвер Java 4.x кэширует подготовленную инструкцию — это отличие от драйвера 3.x. Из документации:

сеанс имеет встроенный кэш, можно подготовить одну и ту же строку дважды.

Обратите внимание, что кэширование основано на: строке запроса в точности такой, какой вы ее предоставили: драйвер не выполняет никакого вида обрезки или очистки.

Я не уверен на 100% в исходном коде, но соответствующие записи в кэше могут не быть очищены при удалении таблицы. Я предлагаю открыть JIRA в драйвере Java, хотя такие изменения типа часто на самом деле не рекомендуются — лучше ввести новое поле с новым типом, даже если возможно воссоздать таблицу.

Ответ №2:

Это правильно. Подготовленные инструкции кэшируются — это оптимизация, которая делает подготовленные инструкции более эффективными, если они используются повторно, поскольку их нужно подготовить только один раз (запрос не нужно повторно анализировать).

Но я подозреваю, что основная проблема в вашем случае заключается в том, что ваши запросы связаны SELECT * . Наилучшая практическая рекомендация (независимо от используемой вами базы данных) — явно перечислять столбцы, которые вы извлекаете из таблицы.

В подготовленном операторе каждый из столбцов привязан к типу данных. Когда вы изменяете схему, добавляя / удаляя столбцы, порядок столбцов (и их типы данных) больше не соответствуют типам данных результирующего набора, поэтому вы оказываетесь в ситуациях, когда драйвер получает, int когда он ожидает text , или наоборот. Приветствия!