SQL тупик в потоке ColdFusion

Я пытаюсь выяснить, почему я получаю ошибку взаимоблокировки при выполнении простого запроса в потоке. Я использую CF10 с SQL Server 2008 R2 на сервере Windows 2012.

Раз в день у меня есть процесс, который кэширует кучу блогов в базе данных. Для каждого блога я создаю тему и делаю всю работу внутри нее. Иногда он работает без ошибок, иногда я получаю следующую ошибку в одном или нескольких потоках:

[Macromedia] [Драйвер JSBC SQLServer][SQLServer] Транзакция (идентификатор процесса 57) заблокирована для ресурсов блокировки другого процесса и выбрана в качестве жертвы тупика. Перезапустите транзакцию.

Это условие взаимоблокировки возникает, когда я запускаю запрос, который устанавливает флаг, указывающий, что канал обновляется. Очевидно, что этот запрос может происходить одновременно с другими потоками, которые обновляют другие каналы.

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

Поскольку слишком много кода для публикации, вот грубый алгоритм:

thread name="#createUUID()#" action="run" idBlog=idBlog {

   try {

       var feedResults = getFeed(idBlog);
       if (feedResults.errorCode != 0)
          throw(message="failed to get feed");

       transaction {
           /* just a simple query to set a flag */
           dirtyBlogCache(idBlog); /* this is where i get the deadlock */
           cacheFeedResults(idBlog, feedResults);
       }

       } catch (any e) {
           reportError(e);
       }
   }

} /* thread */

1 ответ

Этот подход хорошо работает для меня.

 <cffunction name="runQuery" access="private" returntype="query">
 arguments if necessary
 <cfset var whatever = QueryNew("a")>
 <cfquery name="whatever">
 sql
 </cfquery>
 <cfreturn whatever>
 </cffunction>

 attempts = 0;
 myQuery = "not a query";
 while (attempts <= 3 && isQuery(myQuery) == false) {
 attempts += 1;
 try {
 myQuery = runQuery();
 }
 catch (any e) {
 } 

}  

В конце концов, в сообщении говорится о повторном запуске транзакции.

Другие вопросы по тегам