Как создать PreparedStatements в многопоточном окружении? - PullRequest
2 голосов
/ 21 октября 2011

У меня была рабочая версия многопоточного кода, однако я был недоволен тем, что мой PreparedStatement-wrapperclass не является потокобезопасным. Поэтому я решил сгенерировать PreparedStatements в ThreadLocal, чтобы сделать упаковщик потокобезопасным.

Мгновенно SQLExceptions начали приветствовать меня. Основная ошибка Oracle - ORA-00060 deadlock detected, которая, согласно Интернету, должна происходить только в сценариях записи. Мои заявления только для чтения. Это происходит в каком-то непонятном ACL-пакете, о котором я не слышал и сознательно не обращался.

Я с некоторым временем и усилием подготовил и проверил гипотезу, заключающуюся в том, что генерация объекта Connection и подготовка оператора из этого объекта из объекта DataSource не должны происходить в одно и то же время, поскольку контроль доступа базы данных не может быть «потокобезопасным» (хотя DataSource наверняка так и есть). Может ли кто-то подтвердить или опровергнуть это открытие?

Если это действительно так, то есть ли лучший способ избежать одновременного генерирования PreparedStatements в многопоточном приложении?

РЕДАКТИРОВАТЬ: Как просили текст исключения:

Caused by: java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1
ORA-00060: deadlock detected while waiting for resource
ORA-06512: at "XXX.PKG_ACL", line 129
ORA-06512: at "XXX.PKG_ACL", line 459
ORA-06512: at "XXX.PKG_UTILS", line 1933
ORA-06512: at line 6

Ответы [ 2 ]

2 голосов
/ 21 октября 2011

Оператор принадлежит соединению, и соединение не может быть использовано одновременно.Поток обычно должен «владеть» соединением, прежде чем выполнять на нем операторы.Так что просто следуйте идиоме

1 check out connection
2 prepare statement
3 execute query
4 return connection

Вы не можете избежать [1] и [4], они необходимы;В любом случае, не слишком дорого, если объединено.

Вы хотите кешировать [2], в этом тоже нет необходимости, драйвер, вероятно, уже выполняет кеширование.

2 голосов
/ 21 октября 2011

Может ли кто-то подтвердить или опровергнуть это обнаружение?

Я не слышал ничего подобного, и если он существует, это может быть просто деталь реализации.Можете ли вы опубликовать свою трассировку стека (конечно, удалив личную информацию)?

Кроме того, есть ли причина, по которой вы пытаетесь сделать поток PreparedStatement безопасным, а не полагаться на пул / кэш подготовленных операторов?Или, точнее, какой анализ побуждает вас внедрять ThreadLocal PreparedStatement?

...