Почему у меня тупик SQL Server?Включены следы тупика T1222 - PullRequest
1 голос
/ 25 октября 2011

У меня тупик, но я не могу понять, почему. В конце сообщения находится след T1222. Вот что происходит:

UPDATE ADMISSIONS SET …
LAUNCHS A TRIGGER - > INSERT INTO PCM_RECENTCHANGES …
LAUNCHS A TRIGGER -> CALL FUNCTION GETLASTLOCATION
THE FUNCTION EXECUTES -> SELECT TOP 1 @ENVIRONMENT = ENVIRONMENTDBOID

Иногда, когда несколько компьютеров делают одно и то же, мы получаем тупик, о котором сообщается ниже. Что я не понимаю, так это то, что у нас есть тупик в SELECT TOP 1 @ENVIRONMENT = ENVIRONMENTDBOID, если это просто запрос на чтение и, насколько я знаю, никто не вставляет данные в эту таблицу.

Отчет о взаимоблокировке:

 deadlock-list
  deadlock victim=processd99ab0
   process-list
    process id=processd99ab0 taskpriority=0 logused=11760 waitresource=RID: 8:7:765:0 waittime=2249 ownerId=6288074 transactionname=user_transaction lasttranstarted=2011-10-25T15:38:43.667 XDES=0x262dec08 lockMode=S schedulerid=3 kpid=2692 status=suspended spid=65 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2011-10-25T15:38:43.710 lastbatchcompleted=2011-10-25T15:38:43.710 lastattention=2011-10-25T15:37:34.667 clientapp=Careman hostname=BCNW-ISOLER hostpid=4400 loginname=PicisSQL isolationlevel=read committed (2) xactid=6288074 currentdb=8 lockTimeout=4294967295 clientoption1=537002016 clientoption2=128056
     executionStack
      frame procname=NTPA_TEST_CAR.dbo.GETLASTLOCATION line=83 stmtstart=4218 stmtend=4478 sqlhandle=0x03000800ac4d05647a42db00819f00000000000000000000
 SELECT TOP 1 @ENVIRONMENT = ENVIRONMENTDBOID
                              FROM ENVIRONMENTS 
                              WHERE ENCOUNTERDBOID = @ENCOUNTER
                              ORDER BY STARTED DESC     
      frame procname=NTPA_TEST_CAR.dbo.GETFACILITYBYTABLEDBOID line=31 stmtstart=1492 stmtend=1598 sqlhandle=0x03000800318fdd145641db00819f00000000000000000000
 SELECT @ret = dbo.GETLASTLOCATION('ADMISSION', @id)     
      frame procname=NTPA_TEST_CAR.dbo.TR_PCM_RECENTCHANGES_INSTEAD line=60 stmtstart=7396 stmtend=8576 sqlhandle=0x0300080062bc4b452d42db00819f00000000000000000000
 INSERT PCM_RECENTCHANGES (STARTED, ISDELETED, TABLENAME, PCM_KEY, PCM_MESSAGE, PATIENTDBOID, ENCOUNTERDBOID,FILTERID, FACILITYDBOID) 
                              SELECT inserted.STARTED, inserted.ISDELETED, inserted.TABLENAME, inserted.PCM_KEY, inserted.PCM_MESSAGE, inserted.PATIENTDBOID, inserted.ENCOUNTERDBOID,'ADT', CASE WHEN inserted.FACILITYDBOID IS NOT NULL THEN inserted.FACILITYDBOID ELSE dbo.GETFACILITYBYTABLEDBOID(TABLENAME, CASE WHEN inserted.TABLENAME = 'PATIENTS' THEN inserted.PATIENTDBOID ELSE inserted.PCM_KEY END) END 
                              FROM inserted 
                              -- EXIT BECAUSE WE DO NOT HAVE ANYTHING ELSE TO DO.     
      frame procname=NTPA_TEST_CAR.dbo.TR_ADMISSIONS_IU line=169 stmtstart=21690 stmtend=27250 sqlhandle=0x03000800b9db99535642db00819f00000000000000000000
 INSERT INTO PCM_RECENTCHANGES (STARTED, ISDELETED, TABLENAME, PCM_KEY, PCM_MESSAGE) 
                         SELECT      GetDate(),  
                               'F',  
                               'ADMISSIONS',
                               CONVERT(CHAR(21), i.ADMISSIONDBOID),
                               ISNULL( CONVERT(CHAR(48), A.ADMID1), REPLICATE(' ', 48) )
                                     + ISNULL( CONVERT(CHAR(48), i.ADMID2), REPLICATE(' ', 48) )
                                     + ISNULL( CONVERT(CHAR(48), i.ADMID3), REPLICATE(' ', 48) )
                                     + ISNULL( CONVERT(CHAR(19), i.HOSPITALSTARTED, 120), REPLICATE(' ', 19) )
                                     + ISNULL( CONVERT(CHAR(19), i.ENDED, 120), REPLICATE(' ', 19) )
                                     + ISNULL( CONVERT(CHAR(19), i.PREADMISSION, 120), REPLICATE(' ', 19) )
                                     + ISNULL( CONVERT(CHAR(13), i.WEIGHT), REPLICATE(' ', 13) )
                                     +     
      frame procname=adhoc line=1 stmtstart=94 sqlhandle=0x0200000070ece538900ddb307676a81ad422678baf24495d
 UPDATE [ADMISSIONS] set [ENDED] = @1,[DISCHDBOID] = @2  WHERE [ADMISSIONDBOID]=@3     
      frame procname=adhoc line=1 sqlhandle=0x0200000026f85e24d2ee570e5908604daf7249bd6d4e9032
 update ADMISSIONS set ENDED={ts '2011-10-25 15:38:42'},DISCHDBOID=009000000000000000000 where ADMISSIONDBOID=004511105043973019010     
     inputbuf
 update ADMISSIONS set ENDED={ts '2011-10-25 15:38:42'},DISCHDBOID=009000000000000000000 where ADMISSIONDBOID=004511105043973019010    
    process id=processfc2c70 taskpriority=0 logused=13584 waitresource=RID: 8:7:758:8 waittime=2233 ownerId=6288077 transactionname=user_transaction lasttranstarted=2011-10-25T15:38:43.670 XDES=0xa228550 lockMode=S schedulerid=4 kpid=4340 status=suspended spid=86 sbid=0 ecid=0 priority=0 trancount=2 lastbatchstarted=2011-10-25T15:38:43.723 lastbatchcompleted=2011-10-25T15:38:43.720 lastattention=2011-10-25T15:37:36.140 clientapp=Careman hostname=BCNW-DANIM hostpid=13812 loginname=PicisSQL isolationlevel=read committed (2) xactid=6288077 currentdb=8 lockTimeout=4294967295 clientoption1=537002016 clientoption2=128056
    executionStack
     frame procname=NTPA_TEST_CAR.dbo.GETLASTLOCATION line=83 stmtstart=4218 stmtend=4478 sqlhandle=0x03000800ac4d05647a42db00819f00000000000000000000
SELECT TOP 1 @ENVIRONMENT = ENVIRONMENTDBOID
                             FROM ENVIRONMENTS 
                             WHERE ENCOUNTERDBOID = @ENCOUNTER
                             ORDER BY STARTED DESC     
     frame procname=NTPA_TEST_CAR.dbo.GETFACILITYBYTABLEDBOID line=31 stmtstart=1492 stmtend=1598 sqlhandle=0x03000800318fdd145641db00819f00000000000000000000
SELECT @ret = dbo.GETLASTLOCATION('ADMISSION', @id)     
     frame procname=NTPA_TEST_CAR.dbo.TR_PCM_RECENTCHANGES_INSTEAD line=60 stmtstart=7396 stmtend=8576 sqlhandle=0x0300080062bc4b452d42db00819f00000000000000000000
INSERT PCM_RECENTCHANGES (STARTED, ISDELETED, TABLENAME, PCM_KEY, PCM_MESSAGE, PATIENTDBOID, ENCOUNTERDBOID,FILTERID, FACILITYDBOID) 
                             SELECT inserted.STARTED, inserted.ISDELETED, inserted.TABLENAME, inserted.PCM_KEY, inserted.PCM_MESSAGE, inserted.PATIENTDBOID, inserted.ENCOUNTERDBOID,'ADT', CASE WHEN inserted.FACILITYDBOID IS NOT NULL THEN inserted.FACILITYDBOID ELSE dbo.GETFACILITYBYTABLEDBOID(TABLENAME, CASE WHEN inserted.TABLENAME = 'PATIENTS' THEN inserted.PATIENTDBOID ELSE inserted.PCM_KEY END) END 
                              FROM inserted 
                              -- EXIT BECAUSE WE DO NOT HAVE ANYTHING ELSE TO DO.     
      frame procname=NTPA_TEST_CAR.dbo.TR_ADMISSIONS_IU line=169 stmtstart=21690 stmtend=27250 sqlhandle=0x03000800b9db99535642db00819f00000000000000000000
 INSERT INTO PCM_RECENTCHANGES (STARTED, ISDELETED, TABLENAME, PCM_KEY, PCM_MESSAGE) 
                         SELECT      GetDate(),  
                               'F',  
                               'ADMISSIONS',
                               CONVERT(CHAR(21), i.ADMISSIONDBOID),
                               ISNULL( CONVERT(CHAR(48), A.ADMID1), REPLICATE(' ', 48) )
                                     + ISNULL( CONVERT(CHAR(48), i.ADMID2), REPLICATE(' ', 48) )
                                     + ISNULL( CONVERT(CHAR(48), i.ADMID3), REPLICATE(' ', 48) )
                                     + ISNULL( CONVERT(CHAR(19), i.HOSPITALSTARTED, 120), REPLICATE(' ', 19) )
                                     + ISNULL( CONVERT(CHAR(19), i.ENDED, 120), REPLICATE(' ', 19) )
                                     + ISNULL( CONVERT(CHAR(19), i.PREADMISSION, 120), REPLICATE(' ', 19) )
                                     + ISNULL( CONVERT(CHAR(13), i.WEIGHT), REPLICATE(' ', 13) )
                                     +     
      frame procname=adhoc line=1 stmtstart=94 sqlhandle=0x0200000070ece538900ddb307676a81ad422678baf24495d
 UPDATE [ADMISSIONS] set [ENDED] = @1,[DISCHDBOID] = @2  WHERE [ADMISSIONDBOID]=@3     
      frame procname=adhoc line=1 sqlhandle=0x02000000ea3b4a253048c290f000fae3e15fc38eacf905c7
 update ADMISSIONS set ENDED={ts '2011-10-25 15:38:43'},DISCHDBOID=009000000000000000000 where ADMISSIONDBOID=004511105044149020010     
     inputbuf
 update ADMISSIONS set ENDED={ts '2011-10-25 15:38:43'},DISCHDBOID=009000000000000000000 where ADMISSIONDBOID=004511105044149020010    
   resource-list
    ridlock fileid=7 pageid=765 dbid=8 objectname=NTPA_TEST_CAR.dbo.ENVIRONMENTS id=lock1ae5d240 mode=X associatedObjectId=64466095439872
     owner-list
      owner id=processfc2c70 mode=X
     waiter-list
      waiter id=processd99ab0 mode=S requestType=wait
    ridlock fileid=7 pageid=758 dbid=8 objectname=NTPA_TEST_CAR.dbo.ENVIRONMENTS id=lock1afaf540 mode=X associatedObjectId=64466095439872
     owner-list
      owner id=processd99ab0 mode=X
     waiter-list
      waiter id=processfc2c70 mode=S requestType=wait

Ответы [ 2 ]

1 голос
/ 05 мая 2014

Если данные ENVIRONMENTS медленно меняются, вы можете использовать

with (NOLOCK) 

в таблице ОКРУЖАЮЩАЯ СРЕДА. Это снизит риск возникновения этого тупика.

SELECT TOP 1 @ENVIRONMENT = ENVIRONMENTDBOID
                          FROM ENVIRONMENTS with (nolock)
                          WHERE ENCOUNTERDBOID = @ENCOUNTER
                          ORDER BY STARTED DESC 

Во-вторых, вы также можете удалить ORDER BY, поскольку он не используется.

Далее вы также можете переписать этот раздел, например:

if exists(select top 1 1 FROM ENVIRONMENTS WHERE ENCOUNTERDBOID = @ENCOUNTER) 
set @Environment = @Encounter

Ваш SQL всегда будет устанавливать @ENVIRONMENT равным @ENCOUNTER, если в таблице ENVIRONMENTS есть хотя бы одна строка, соответствующая этой категории. Нет необходимости сортировать, так как установленное значение всегда будет равно @ENCOUNTER, а STARTED не возвращается.

Я перечислил эти решения, потому что все они могут внести свой вклад в вашу тупиковую ситуацию.

1 голос
/ 30 октября 2011

По какой-то причине обе транзакции имеют блокировку X на ENVIRONMENTS.

Возможно, существует отношение on update cascade внешнего ключа с ADMISSIONS или, возможно, блокировка X была полученапредыдущий оператор выполняется в той же транзакции и не имеет ничего общего с кодом, показанным в отчете о взаимоблокировке (здесь показаны операторы, выполняемые при возникновении взаимоблокировки, а не операторы, которые получили ресурсы в первую очередь).

...