Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 deadlock при SELECT и UPDATE  [new]
dmitry_ra
Member

Откуда:
Сообщений: 1
Доброго времени суток!

Возник deadlock при следующей ситуации:
1) поток #1 выполняет обновление записи в таблице;
2) поток #2 делает выборку из этой таблицы по одному из изменяемых полей.

При тестировании через ManagementStudio SELECT ожидает пока не выполнится COMMIT транзакции в которой выполняется UPDATE. В реальной жизни _иногда_ проявляется deadlock.

В чём может быть проблема?

xml-лог:
<deadlock>
  <victim-list>
    <victimProcess id="process1f4013498" />
  </victim-list>
  <process-list>
    <process id="process1f4013498" taskpriority="0" logused="0" waitresource="KEY: 5:72057594062569472 (efd395c442f4)" waittime="1256" ownerId="151956" transactionname="SELECT" lasttranstarted="2014-09-09T17:29:00.060" XDES="0x1f4315a60" lockMode="S" schedulerid="1" kpid="188" status="suspended" spid="52" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2014-09-09T17:29:00.060" lastbatchcompleted="2014-09-09T17:29:00.060" lastattention="1900-01-01T00:00:00.060" clientapp=".Net SqlClient Data Provider" hostname="FLEX-2823411" hostpid="904" loginname="sa" isolationlevel="read committed (2)" xactid="151956" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
      <executionStack>
        <frame procname="adhoc" line="1" stmtstart="76" sqlhandle="0x0200000062908e00e9bb1fc64b12bc60a3cd2dc3a70e7d780000000000000000000000000000000000000000">SELECT * FROM HistoryReport WHERE recordVersion &gt; @recordVersion AND userId = @userId ORDER BY recordVersion</frame>
        <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">unknown</frame>
      </executionStack>
      <inputbuf>(@recordVersion bigint,@userId bigint)SELECT * FROM HistoryReport WHERE recordVersion &gt; @recordVersion AND userId = @userId ORDER BY recordVersion</inputbuf>
    </process>
    <process id="process1ec3ec558" taskpriority="0" logused="924" waitresource="KEY: 5:72057594062766080 (c3128b0e6c0e)" waittime="1286" ownerId="151945" transactionname="user_transaction" lasttranstarted="2014-09-09T17:29:00.057" XDES="0x1ec183048" lockMode="X" schedulerid="4" kpid="3812" status="suspended" spid="51" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2014-09-09T17:29:00.047" lastbatchcompleted="2014-09-09T17:29:00.047" lastattention="1900-01-01T00:00:00.047" clientapp=".Net SqlClient Data Provider" hostname="FLEX-2823411" hostpid="904" loginname="sa" isolationlevel="read committed (2)" xactid="151945" currentdb="5" lockTimeout="4294967295" clientoption1="671219744" clientoption2="128056">
      <executionStack>
        <frame procname="adhoc" line="1" stmtstart="616" stmtend="1108" sqlhandle="0x02000000d9c7371e8d0601464fa577512c22cabdbe5849de0000000000000000000000000000000000000000">UPDATE HistoryReport SET reportState=@reportState,stateText=@stateText,completePercentage=@completePercentage,stateTime=@stateTime,dateChange=@dateChange,recordVersion=(SELECT ver FROM RecordVersionCounter WHERE sid=1005) WHERE reportId=@reportId</frame>
        <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">unknown</frame>
      </executionStack>
      <inputbuf>(@reportState tinyint,@stateText nvarchar(4000),@completePercentage tinyint,@stateTime datetime,@reportId uniqueidentifier,@dateChange datetime)SET XACT_ABORT ON BEGIN TRANSACTION UPDATE RecordVersionCounter SET ver=ver+1 WHERE sid=1005 IF EXISTS (SELECT * FROM HistoryReport WHERE reportId=@reportId) BEGIN UPDATE HistoryReport SET reportState=@reportState,stateText=@stateText,completePercentage=@completePercentage,stateTime=@stateTime,dateChange=@dateChange,recordVersion=(SELECT ver FROM RecordVersionCounter WHERE sid=1005) WHERE reportId=@reportId END ELSE BEGIN INSERT INTO HistoryReport (reportState,stateText,completePercentage,stateTime,reportId,dateChange,recordVersion) VALUES (@reportState,@stateText,@completePercentage,@stateTime,@reportId,@dateChange,(SELECT ver FROM RecordVersionCounter WHERE sid=1005)) END COMMIT SELECT reportId FROM HistoryReport WHERE reportId=@reportId</inputbuf>
    </process>
  </process-list>
  <resource-list>
    <keylock hobtid="72057594062569472" dbid="5" objectname="P5Data.dbo.HistoryReport" indexname="PK_HistoryReport" id="lock1f01be100" mode="X" associatedObjectId="72057594062569472">
      <owner-list>
        <owner id="process1ec3ec558" mode="X" />
      </owner-list>
      <waiter-list>
        <waiter id="process1f4013498" mode="S" requestType="wait" />
      </waiter-list>
    </keylock>
    <keylock hobtid="72057594062766080" dbid="5" objectname="P5Data.dbo.HistoryReport" indexname="IX_HistoryReport_UserRecVer" id="lock1f01c1680" mode="S" associatedObjectId="72057594062766080">
      <owner-list>
        <owner id="process1f4013498" mode="S" />
      </owner-list>
      <waiter-list>
        <waiter id="process1ec3ec558" mode="X" requestType="wait" />
      </waiter-list>
    </keylock>
  </resource-list>
</deadlock>


К сообщению приложен файл. Размер - 54Kb
9 сен 14, 19:10    [16556282]     Ответить | Цитировать Сообщить модератору
 Re: deadlock при SELECT и UPDATE  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4804
dmitry_ra,

А проблемы мы то и нет. Вы должны реализовать логику перезапуска транзакции при DEADLOCK. Либо использовать другой уровень изоляции (NOLOCK, READ COMMITTED SNAPSHOT).
9 сен 14, 19:16    [16556293]     Ответить | Цитировать Сообщить модератору
 Re: deadlock при SELECT и UPDATE  [new]
invm
Member

Откуда: Москва
Сообщений: 9400
dmitry_ra
В чём может быть проблема?
Да нет проблемы. Ситуация вполне штатная.
Делок у вас возникает из-за наличия в HistoryReport блоба(ов), который(е) вы неявно включили в select-лист. В этом случае, наличие сортировки приводит на TIL RC к удержанию S-блокировок до конца инструкции.
Самый простой способ лечения - перейти на RCSI. NOLOCK может дать вам другие проблемы.
9 сен 14, 20:57    [16556576]     Ответить | Цитировать Сообщить модератору
 Re: deadlock при SELECT и UPDATE  [new]
поспрошайка
Guest
invm
Делок у вас возникает из-за наличия в HistoryReport блоба(ов), который(е) вы неявно включили в select-лист. В этом случае, наличие сортировки приводит на TIL RC к удержанию S-блокировок до конца инструкции.


Наличие ORDER BY является причиной или ROW_OVERFLOW + ORDER BY?
9 сен 14, 21:31    [16556659]     Ответить | Цитировать Сообщить модератору
 Re: deadlock при SELECT и UPDATE  [new]
NickAlex66
Member

Откуда:
Сообщений: 319
dmitry_ra,

Отучите себя писать SELECT * и проблем будет меньше.
9 сен 14, 21:39    [16556679]     Ответить | Цитировать Сообщить модератору
 Re: deadlock при SELECT и UPDATE  [new]
invm
Member

Откуда: Москва
Сообщений: 9400
поспрошайка,

Подробности - Read Committed and Large Objects
9 сен 14, 21:59    [16556728]     Ответить | Цитировать Сообщить модератору
 Re: deadlock при SELECT и UPDATE  [new]
поспрошайка
Guest
invm,

спасибо, читаю
9 сен 14, 22:23    [16556821]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить