Где запрос создает неправильный SQL на производстве

Мне пришлось обновить Spring с 1.2.7 до 2.0, а также Grails с 2.2.0 до 2.3.11. Решив несколько типичных проблем с обновлением, я начал создавать WAR на тестовом сервере. Все казалось в порядке. Но после нескольких развертываний я столкнулся с проблемой.

Иногда (правила нет) у сервера 100% загрузка процессора -> OutOfMemeryError или приложение выдает ошибку 500. После отладки я заметил, что причиной этих проблем является некорректный SQL-запрос.

Где запрос:

UserRole.find{role.authority =~ "%${authTxt}" && user.id == currentUser.id}

создает такой SQL:

select this_.id as id1_35_2_, this_.payment_enabled as payment_2_35_2_, this_.role_id as role_id3_35_2_, this_.user_id as user_id4_35_2_,
role_alias1_.id as id1_29_0_, role_alias1_.version as version2_29_0_, role_alias1_.authority as authorit3_29_0_, user_alias2_.id as id1_36_1_,
user_alias2_.version as version2_36_1_, user_alias2_.account_expired as account
... inner join role role_alias1_ on this_.role_id=role_alias1_.id inner join users user_alias2_ on this_.user_id=user_alias2_.id 
where ((role_alias1_.authority ilike ?) and (user_alias2_.id=?)) 
36_1_, user_alias2_.account_locked as account
User.findAll {id == userid} 
36_1_, user_alias2_.auto_password_flag as auto_pas5_36_1_, user_alias2_.email as email6_36_1_, user_alias2_.enabled as enabled7_36_1_, user_alias2_."password" as password8_36_1_, user_alias2_.password_expired as password9_36_1_, user_alias2_.user_info_id as user_in10_36_1_, user_alias2_.username as usernam11_36_1_ from user_role this_ inner join role role_alias1_ on this_.role_id=role_alias1_.id inner join users user_alias2_ on this_.user_id=user_alias2_.id where (1=1 and 1=1)

и здесь правильный SQL:

... inner join role role_alias1_ on this_.role_id=role_alias1_.id inner join users user_alias2_ on this_.user_id=user_alias2_.id 
where ((role_alias1_.authority ilike ?) and (user_alias2_.id=?)) 

Очевидная проблема заключается в том, что выражение "(1 = 1 и 1 = 1)". На самом деле такой запрос:

User.findAll {id == userid} 

получить всю таблицу. Динамические средства поиска или критерии не вызывают этой проблемы.

Я нашел двух человек, у которых была похожая проблема:

https://zenofchicken.wordpress.com/2016/01/06/freaky-grails-where-clauses-dont-work-anymore/

http://grails.1312388.n4.nabble.com/Finder-not-applying-criteria-td4655689.html

Плагины, которые я использую:

  • весна-безопасность-ядро: 2.0-RC5
  • весна-безопасность-Oauth: 2.0.2
  • весна-безопасность-oauth-facebook: 0.1
  • спящий режим: 3.6.10.16
  • исполнитель: 0.3
  • экспорт: 1,6
  • CSV:0.3.1
  • миграция базы данных: 1.2.1
  • кварц: 1.0-RC7
  • актив-конвейер: 1.9.6
  • грааль-мелодия: 1.57.0

База данных: PostgreSQL 8.4.20

Я пробовал много решений:

  • Я изменил версию Grails на 2.4.
  • Я изменил Hibernate3 на Hibernate4
  • Я сменил коннектор на Postgres с 9.0-801.jdbc3 на 9.1-901-1.jdbc4
  • Я удалил зависимости, чтобы увидеть, не вызывает ли какая-либо из них проблему.
  • Проверил, не отличается ли извлеченный WAR ни в одном файле
  • Я изменил версию Java
  • Я изменил версию Tomcat
  • я проверял на другой системе

Из того, что я прочитал в блоге, ссылку на который я дал выше, Graeme Rocher написал, что проблема может быть связана с отсутствием GORM в приложении. Однако проблема была во время сборки WAR - зависимости были неправильно упакованы (?). Но вот проблема возникает при распаковке WAR или при загрузке классов. Глядя на источник проблемы из записи в блоге, видно, что проблема может быть связана с какой-то нелепой причиной...

Кто-нибудь знает, что может вызвать эту проблему или что я могу отладить, чтобы определить источник ошибки? И вопрос к разработчикам Grails: что изменилось между версиями 2.2 и 2.3, что теоретически могло вызвать такую ​​проблему?


person user2040547    schedule 01.02.2016    source источник
comment
Мы сталкиваемся с похожей проблемой и не можем с ней справиться. У нас было 3 запроса, которые перестали работать и были преобразованы в неудавшийся where 1=1 and 1=1 запрос sql. Не одновременно! В разный момент после перезагрузки сервера, после релиза. Код, который отлично работал до этого момента, не менялся месяцами и который снова работал после перезагрузки... Странный, причудливый и не решенный. Три дня назад у нас возникла большая проблема с запросом, который должен был удалить только часть коллекции сущностей, но удалил всю коллекцию. Это был день перезагрузки резервной копии... Grails 2.4.4, Hibernate 4   -  person Grooveek    schedule 04.02.2016
comment
Та же проблема с запросами в grails 2.4.4. Запрос, который должен был отменить членов с истекшим сроком действия, сумел отменить всю нашу базу пользователей! Это очень недетерминировано и зависит от того, как запускается приложение.   -  person Tomas Bartalos    schedule 31.05.2016


Ответы (2)


Проблема возникла из-за AbstractHibernateCriterionAdapter в grails-datastore-gorm-hibernate-core JAR.
criterionAdaptors HashMap заполнен неправильно.

Эта карта представляет собой final static HashMap, используемую для сопоставления критериев GORM с критериями Hibernate.

Проблема возникает случайным образом при запуске приложения.
Иногда HashMap заполняется без каких-либо проблем, иногда возникают проблемы...
Это Hashmap static final и остается поврежденным до конца срока службы приложения. Вот почему вы когда-нибудь сталкиваетесь с этой проблемой, и после перезагрузки все идет хорошо.

HashMap может быть поврежден, когда несколько потоков одновременно создают объект AbstractHibernateCriterionAdapter.
Каждый поток вызывает конструктор и метод initialize().
Это метод synchronized, но идиома synchronized эффективна только для нескольких потоков, обращающихся к объекту. тот же объект (https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html)

В результате synchronized не блокирует должным образом метод initialize(), и несколько потоков могут одновременно пытаться заполнить criterionAdaptors HashMap.
HashMap не является потокобезопасным, в результате HashMap повреждается и некоторые критерии отсутствуют. .

Если критерий GORM не найден в этой HashMap, критерий молча игнорируется... Что объясняет, почему он исчезает из сгенерированного запроса.

Я создал задачу Github: https://github.com/grails/grails-data-mapping/issues/643

person Guigoz    schedule 08.02.2016
comment
Ну наконец-то логичное объяснение этой проблемы :). Но одно заставляет меня задуматься, почему проблема возникает только у некоторых людей? Невозможно, чтобы это была общая проблема Grails 2.3/2.4. Обнаружил еще одну закономерность, на виртуалке проблема не возникает... - person user2040547; 14.02.2016
comment
AbstractHibernateCriterionAdapter заполняется при первом выполнении запроса критериев. Таким образом, это может зависеть от запросов первых критериев приложения. Если два запроса выполняются синхронно при запуске приложения (Bootstrap.groovy?), проблема может возникнуть, в противном случае вероятность возникновения этой проблемы исключена. Это может объяснить, почему затронуты только некоторые приложения. - person Guigoz; 15.02.2016
comment
Вам нужна дополнительная информация, чтобы принять этот ответ? - person Guigoz; 24.02.2016
comment
Ой, простите. Спасибо за вашу помощь - person user2040547; 26.02.2016

Это странный способ получить все экземпляры пользователя таким образом по идентификатору.

Вы пробовали это?

User.findAllById(userid)
person quindimildev    schedule 08.02.2016
comment
Это был просто пример. Основная проблема заключается в том, что все запросы в проекте создают некорректный SQL. - person user2040547; 14.02.2016
comment
Если вы выполняете соединение, метод использует соединение по критерию внутри закрытия withcriteria. - person quindimildev; 14.02.2016