Почему бьются данные, получаемые из PostgreSQL?

Приветствую всех.
Исчерпал свои возможности по поиску решения проблемы и очень прошу помочь :)

Есть проект, урезанный до минимальной конфигурации, позволяющей воспроизвести баг: https://github.com/TerminusMKB/moidelishki
В проекте один единственный контроллер, который при запросе к себе запрашивает и возвращает данные о единственном же пользователе в БД. При первом запросе к себе он возвращает корректные данные:
{"id":2,"testArray":"{1,2,3}","testTimestamp":"2016-01-01 00:00:00+03"}

При десятом же (условно, но где-то в том районе) начинает выдавать такое:
{"id":2,"testArray":"{\"1\",\"2\",\"3\"}","testTimestamp":"2016-01-01 00:00:00+03"}

Т.е. начинает зачем-то оборачивать в кавычки элементы массива.

Что известно:
1) Воспроизводится с PostgreSQL 9.3 и 9.4
2) Воспроизводится только при использовании jdbc драйвера старше 9.4-1201-jdbc41. С этой версией проблем нет никаких.
3) Менял пул соединений с c3p0 на Vibur - не помогло
4) Менял версии Spring и Hibernate - не помогло
5) Проблема точно не в отдаче данных самим контроллером, т.к. проявилась вначале в собственном определённом UserType. Там я смотрел, что приходит в класс из базы и в определённый момент видел битые данные. Сейчас у проблемного поля тип String просто для удобства просмотра.

Есть как бы планы обновления БД на версию посвежее, да драйвер, соответственно, поактуальнее, то данный вопрос ставит просто в тупик.

В чём может быть беда?
  • Вопрос задан
  • 576 просмотров
Решения вопроса 1
TerminusMKB
@TerminusMKB Автор вопроса
Сниффер (Wireshark) показал следующее:
1) При jdbc 9.4-1201-jdbc41 каждый раз отправляется один запрос. И каждый раз из БД приходит полный корректный ответ.
Выглядит запрос в дампе сниффера так:
Type: Parse
Length: 169
Statement:
Query: select user0_."id" as id1_0_, user0_."testArray" as testArra2_0_, user0_."testTimestamp" as testTime3_0_ from "public"."users" user0_ where user0_."id" in (2)
Parameters: 0

2) При более старших версиях jdbc вначале (при первых попытках) идёт такой же запрос, только с указанием Statement:
Type: Parse
Length: 169
Statement: S_2
Query: select user0_."id" as id1_0_, user0_."testArray" as testArra2_0_, user0_."testTimestamp" as testTime3_0_ from "public"."users" user0_ where user0_."id" in (2)
Parameters: 0

3) В ситуации, когда виден баг, jdbc отправляет уже не вышеприведённый запрос, а следующее (как я понял - несколько команд за раз):
Type: Bind
Length: 21
Portal:
Statement: S_2
Parameter formats: 0
Parameter values: 0
Result formats: 3
   Format: Binary (1)
   Format: Binary (1)
   Format: Binary (1)

Type: Execute
Length: 9
Portal:
Returns: all rows

Type: Sync
Length: 4

И в ответ получает данные, которые глазами в дампе оценить уже сложно - идут не текстом.

P.S.: Проблема решилась выставлением параметра jdbc драйвера preparedStatementCacheQueries в 0. Отключение кеша привело к тому, что драйвер перестал использовать prepared statements при запросах вообще и каждый раз отправляет запрос полностью, как в версии 9.4-1201-jdbc41. Так себе решение, на самом деле, т.к. надо будет пробовать еще, что получится, если я захочу сам использовать prepared statements.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
jamakasi666
@jamakasi666 Куратор тега Java
Просто IT'шник.
1) Попробуйте выкинуть lombok, вдруг проблема в нем и хрен его знает как он там повесил геттер\сеттер.
2) Попробуйте посмотреть снифером трафик между явой и базой. Точно ли запрос и ответ каждый раз абсолютно одинаковый?
2.1) Если проблема с тем что прилетает из базы такой битый ответ то копать в сторону проблемы с базой.
2.2) Если прилетает в определенный момент кривой запрос от явы то копать дальше саму яву.
Ответ написан
ValorVl
@ValorVl
DevOps
Поздравляю. Это баг JDBC и дисериализации ARRAY, было в свое время тоже самое, но давно.
Первое время решал костылем, потом обновил драйвер до 9.4.1210. Сейчас вроде все норм.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы