2

My procedure spUmowyXMLintoLOG looks like :

CREATE PROCEDURE dbo.spUmowyXMLintoLOG
(
    @inXML XML,
    @PROCID INT,
    @idRekorduZrodlowego INT,
    @idTabeliZrodlowej INT,
    @TrybWywolania INT, /*  0 pierwszy wpis z inXML, 
                                1 drugi wpis z outXML, 
                               -1 czytanie z logu po nazwie obiektu idRekorduZrodloweho i idTabeliZrodlowej */
    @outIdWpisuDoLogu INT OUTPUT,
    @dataOd DATETIME,
    @dataDo DATETIME,
    @CzyBlad BIT,
    @ErrorMessage VARCHAR(4000),
    @uidOperacji VARCHAR(255) = NULL /* UM2-4818 */
)
AS
BEGIN
    DECLARE @komunikatPrint VARCHAR(1000)
    DECLARE @NazwaObiektu VARCHAR(255)
    
    SELECT @NazwaObiektu = name
    FROM dbo.sysobjects WITH(NOLOCK)
    WHERE id = @PROCID
    
    BEGIN TRY 
    
        IF @TrybWywolania = 0
        BEGIN
    
            INSERT INTO dbo.UmowyXMLzInterfejsow_log2(ProcID,NazwaObiektu,inXml,CzyBlad,UIDOperacji)
            SELECT @PROCID,@NazwaObiektu,@inXML,@CzyBlad,@uidOperacji

            SELECT @outIdWpisuDoLogu = SCOPE_IDENTITY()
            
            /* zamapowanie szczegółów */
            INSERT INTO UmowyXMLzInterfejsow_log2_szczegoly WITH(XLOCK,ROWLOCK)
            SELECT @outIdWpisuDoLogu,idRekorduZrodlowego,idTabeliZrodlowej
            FROM #UmowyXMLzInterfejsow_log_szczegoly WITH(NOLOCK)


            /* UM2-4842 BEGIN zapis uida biznesowego */
            IF OBJECT_ID('tempdb..#umowyXMLzInterfejsow_log_UIDbiznesowy') IS NOT NULL
            BEGIN
                INSERT INTO dbo.UmowyXMLzInterfejsow_log2_UIDbiznesowy (idWpisuDoLogu,UIDBiznesowy)
                SELECT @outIdWpisuDoLogu,UIDBiznesowy
                FROM #umowyXMLzInterfejsow_log_UIDbiznesowy
            END
            /* UM2-4842 END zapis uida biznesowego */

        END
        ELSE
        IF @TrybWywolania = 1
        BEGIN
        
            UPDATE dbo.UmowyXMLzInterfejsow_log2 WITH(XLOCK,ROWLOCK)
            SET outXml = @inXML,
                DataAktualizacji = GETDATE(),
                CzyBlad = @CzyBlad,
                ErrorMessage = @ErrorMessage
            WHERE idWpisuDoLogu = @outIdWpisuDoLogu

        END
        ELSE
        IF @TrybWywolania = -1
        BEGIN
        
            IF ISNULL(@PROCID,0) <> 0
            AND ISNULL(@idRekorduZrodlowego,0) <> 0
            AND ISNULL(@idTabeliZrodlowej,0) <> 0
                BEGIN
                    SELECT 'Wyszukianie po idRekorduZrodlowego,idTabeliZrodlowej -> dbo.UmowyXMLzInterfejsow_log',l.*,'_szczegoly',ls.*,'SWUIM_SystemyTabeleZrodlowe',stz.*
                    FROM dbo.UmowyXMLzInterfejsow_log2 l WITH(NOLOCK)
                    JOIN UmowyXMLzInterfejsow_log2_szczegoly ls WITH(NOLOCK)
                        ON l.idWpisuDoLogu = ls.idWpisuDoLogu
                    LEFT JOIN SWUIM_SystemyTabeleZrodlowe stz WITH(NOLOCK)
                        ON ls.idTabeliZrodlowej = stz.id
                    WHERE ls.idRekorduZrodlowego = @idRekorduZrodlowego
                        AND ls.idTabeliZrodlowej = @idTabeliZrodlowej
                END

        END
        IF @TrybWywolania = -2
        BEGIN
        
            IF ISNULL(@PROCID,0) <> 0
            AND ISNULL(@dataOd,'9999-12-31') <= CONVERT(VARCHAR(10),GETDATE(),120)
            AND ISNULL(@dataDo,'9999-12-31') >= CONVERT(VARCHAR(10),GETDATE(),120)
                BEGIN
                    SELECT 'Wyszukianie po dacieWpisu -> dbo.UmowyXMLzInterfejsow_log',l.*,'_szczegoly',ls.*,'SWUIM_SystemyTabeleZrodlowe',stz.*
                    FROM dbo.UmowyXMLzInterfejsow_log2 l WITH(NOLOCK)
                    JOIN UmowyXMLzInterfejsow_log2_szczegoly ls WITH(NOLOCK)
                        ON l.idWpisuDoLogu = ls.idWpisuDoLogu
                    LEFT JOIN SWUIM_SystemyTabeleZrodlowe stz WITH(NOLOCK)
                        ON ls.idTabeliZrodlowej = stz.id
                    WHERE l.NazwaObiektu = @NazwaObiektu
                    AND l.DataWpisu >= @dataOd 
                    AND l.DataWpisu <= @dataDo
                END             

        END

    END TRY
    BEGIN CATCH
    
        SELECT @komunikatPrint = 'Wystapił problem z zapisem do XML do logu: ' + ERROR_MESSAGE()
        
    END CATCH



END

As you can see this procedure get insert into :

INSERT INTO dbo.UmowyXMLzInterfejsow_log2(ProcID,NazwaObiektu,inXml,CzyBlad,UIDOperacji)
            SELECT @PROCID,@NazwaObiektu,@inXML,@CzyBlad,@uidOperacji

Now i try to get deadlock while execute this procedure to test .

I open 2 query windows and in first one i try to lock table like this :

BEGIN TRY
begin tran az

        

        select top 10 * from UmowyXMLzInterfejsow_log2 with(tablockx)


WAITFOR DELAY '00:0:30'


commit tran az

END TRY

BEGIN CATCH
rollback tran az
END CATCH

The second window is just execute this procedure - to get deadlock while inserting data

begin tran az

DECLARE @outIdWpisuDoLogu INT 

IF OBJECT_ID('tempdb..#umowyXMLzInterfejsow_log_szczegoly') IS NOT NULL
        DROP TABLE #umowyXMLzInterfejsow_log_szczegoly

    CREATE TABLE #umowyXMLzInterfejsow_log_szczegoly
    (
        idWpisuDoLogu [int] NULL,
        idRekorduZrodlowego [int] NOT NULL,
        idTabeliZrodlowej [int] NOT NULL
    )


EXEC dbo.spUmowyXMLintoLOG 'xx',@@procid,null,null,0,@outIdWpisuDoLogu OUTPUT,NULL,NULL,0,NULL


select @outIdWpisuDoLogu

rollback tran az

After when i lock table - the procedure just executing 30 sec then output comes out without problem.

When i change delay time to 10 min it just execute 10 min... How can i get deadlock here? - it should appears because table is locked by another transaction.

O. Jones
  • 103,626
  • 17
  • 118
  • 172
adam
  • 179
  • 2
  • 12
  • I most admit, all the `NOLOCK`s in the have a code smell and a half... Do you really need them; especially when you're making explicit locks against other tables. – Thom A Aug 12 '21 at 12:11
  • This procedure after BEGIN TRY is trying to insert data into table where i lock just. I want to have only lock to test. – adam Aug 12 '21 at 12:13
  • Does this answer your question? [How to simulate DEADLOCK on SQL Server?](https://stackoverflow.com/questions/22825147/how-to-simulate-deadlock-on-sql-server) – O. Jones Aug 12 '21 at 12:41
  • No :( , i try to do something like this with an update update UmowyXMLzInterfejsow_log2 set OperatorWpisu = 'Adam' where idWpisuDoLogu = 1131 WAITFOR DELAY '00:00:15' -- But all time i can't get deadlock in procedure execution – adam Aug 12 '21 at 13:01
  • With 2 global tebles it works , but i have INSERT into in procedure maybe that's why i can't have a deadlock? Or SELECT @outIdWpisuDoLogu = SCOPE_IDENTITY() always will return number? It doesn't matter if begin TRY is done? Maybe that's why? – adam Aug 12 '21 at 13:19

1 Answers1

2

Deadlocks aren't locks. They are conflicting locks. For example:

  • sp1 locks table a, then table b.
  • sp2 locks table b, then table a.

If you run the two sps concurrently, sp1 locks table a and then tries to lock table b. But sp2 has already locked b so sp1 waits for it to be unlocked. At the same time sp2 has locked table b so sp1 waits. They're both waiting, until SQL Server detects the situation and terminates one of the operations to break the deadlock.

Your database is functioning as designed, by delaying execution of one sp until another sp releases the locks it has.

To force a deadlock, you'll need two resources (tables) to lock, and two SQL sequences from separate database connections to lock them in the opposite order. You could do this with one stored procedure and a SSMS session. Start the SSMS session with SET DEADLOCK_PRIORITY HIGH; so SQL Server kills your SP rather than randomly picking your SSMS session to kill.

Consider Monty Python's Australian Philosophers sitting around a table with a big plate of spaghetti, and just one fork and one spoon they must share. To eat, each philosopher needs to use both the spoon and the fork and then put them down. If one grabs the fork first and another grabs the spoon first, they go hungry. But if all philosophers grab the fork first, then the spoon, they can eat one at a time.

O. Jones
  • 103,626
  • 17
  • 118
  • 172
  • So how can i test deadlock on this procedure while inserting data into this table? I need to have deadlock here . And procedure needs to fail with deadlock. Is it possible to do without create another procedure to test it? – adam Aug 12 '21 at 12:17
  • I am interested in the topic too. Is it possible to test it without creating another stored procedure? – Adamszsz Aug 12 '21 at 12:26
  • You could do this with one stored procedure and a SSMS session. – O. Jones Aug 12 '21 at 12:34
  • Could you show a little example how to do that with 1 procedure and SSMS second session? As i undestand correctly he try to do that with 2 sessions. 2 opened window in SSMS is 2 different sessions – Adamszsz Aug 12 '21 at 12:38