About the appearance of two update statements deadlock each other, deepen our understanding of the lock

Source: Internet
Author: User
Tags create index datetime getdate first row

Some time ago in the MSDN forum to see Sanda reply to a question, feel more understanding of the lock, first apart "take" record under study.

Original post address: Http://social.msdn.microsoft.com/Forums/zh-CN/6559504d-c546-45a6-89e2-eeb75041b3e7/-?forum=sqlserverzhchs

First, the Environment script

CREATE TABLE [dbo]. [Table1] (

[A] [nvarchar] (A) NULL,

[B] [nvarchar] (a) not NULL,

[C] [nvarchar] (a) NULL

) on [PRIMARY]

Go

INSERT [dbo]. [Table1] ([A], [B], [C]) VALUES (n ' Aa1 ', n ' B1 ', n ' 11 ')

INSERT [dbo]. [Table1] ([A], [B], [C]) VALUES (n ' aa2 ', n ' b3 ', n ' 11 ')

INSERT [dbo]. [Table1] ([A], [B], [C]) VALUES (n ' Aa3 ', n ' b4 ', n ' 11 ')

INSERT [dbo]. [Table1] ([A], [B], [C]) VALUES (n ' Aa3 ', n ' B5 ', n ' 11 ')

INSERT [dbo]. [Table1] ([A], [B], [C]) VALUES (n ' Aa3 ', n ' B2 ', n ' 11 ')

INSERT [dbo]. [Table1] ([A], [B], [C]) VALUES (n ' Aa3 ', n ' b6 ', n ' 11 ')

INSERT [dbo]. [Table1] ([A], [B], [C]) VALUES (n ' Aa3 ', n ' B7 ', n ' 11 ')

INSERT [dbo]. [Table1] ([A], [B], [C]) VALUES (n ' Aa3 ', n ' B8 ', n ' 11 ')

INSERT [dbo]. [Table1] ([A], [B], [C]) VALUES (n ' Aa1 ', n ' B9 ', n ' 11 ')


Then there are three scripts

--Enquiry 1

SET TRANSACTION Isolation Level READ UNCOMMITTED

BEGIN Tran

Print convert (nvarchar (), CONVERT (Datetime,getdate (), 121), 121)

Update table1

Set a= ' Aa1 '

where b= ' B3 '

Print convert (nvarchar (), CONVERT (Datetime,getdate (), 121), 121)

EXEC sp_lock @ @spid

WAITFOR DELAY ' 00:00:10 '

Update table1

Set a= ' Aa2 '

where b= ' B8 '

EXEC sp_lock @ @spid

Print convert (nvarchar (), CONVERT (Datetime,getdate (), 121), 121)

Commit Tran

--Query Two

SET TRANSACTION Isolation Level Read UNCOMMITTED

BEGIN Tran

Update table1

Set a= ' Aa3 '

Where b= ' B7 '

EXEC sp_lock @ @spid

Commit Tran

--Query Three:

SET TRANSACTION Isolation Level Read UNCOMMITTED

BEGIN Tran

Update table1

Set a= ' Aa3 '

Where b= ' B1 '

EXEC sp_lock @ @spid

Commit Tran

The situation is running in two threads

Situation 1:

Run Query 1 First, and then run Query 2 in another thread immediately.

The result is a smooth completion of the update on both sides

Situation 2:

Run Query 1 First, and then run Query 3 in another thread immediately.

The result is a deadlock condition in Query 3.

The above is the phenomenon

---------------------------------------------------------------------------------------------

Let's look at why this is happening, and first let's see what the update action is going to do.

We start with Profiler, monitor lock:acquired and lock:released two projects, and limit suid to the process IDs we need to monitor, and then we get the following monitoring results

We can draw a conclusion that:

Scan tables during update record U lock on each line, if satisfied, convert to x Lock update, Release U lock if condition is not satisfied. From this conclusion, we can infer the reason why the above causes the deadlock and does not cause the deadlock.

Situation 1:

Query 1: Scan the table to record the U-lock per line, if the conditions are met, the conversion to the X-lock update, if not satisfied with the release of the U lock. When the update is complete, the X lock remains if it is not committed.

Note: The number of X locks retained here is line 2nd (B3) because this is a heap table, which is usually sorted in the order of insertion, and the update scans the table from the first


Query 2: Scan the table once for each row to record the U lock, because the target that needs to be queried is after the X lock of 1, the query cannot be queried until the condition that needs to be updated is not able to add a U lock wait, so that only after query 1 completes the query, Query 2 can continue, so it does not cause a deadlock.

Note: Because query 2 is to satisfy X-lock conditions on line 7th (B7), so when query 2 of the U lock to get the release action, to the second line, the query 1 retained the X lock, the entire transaction into the waiting state, and did not leave any interference to query 1 of the second statement of the lock, so, when the query 1 directly after the completion , query 2 continues to perform normally

Situation 2:

Query 1: Scan the table to record the U-lock per line, if the conditions are met, the conversion to the X-lock update, if not satisfied with the release of the U lock. When the update is complete, the X lock remains if it is not committed.

Query 3: Scan a table to record a U lock on each line, because the condition requiring update is found and X-locked before query 1, but unable to add U lock after scanning to the X lock added by the query 1 lock will cause you to wait for query 1 to complete before submitting. At this point, query 1 of the second UPDATE statement began to run, update U lock, found that query 2 x, to wait for the query 3 of the X-lock release while the deadlock condition.

Note: Because of the Add X lock action for Query 3, the first line occurs (B1), then the second row is, and the X lock retained by query 1 blocks the continuation of the second line (B3). So he needs to wait for query 1 to release the X lock in the second line to continue with the update, but the second statement of Query 1 needs to query 3 to first release the X lock in the first row (B1), thus forming the deadlock condition.

So this on the same page, the different rows of each other deadlock, and the reason for the deadlock is quite clear.

The focus of this case is that update is a two-action transaction, divided into queries and modifications, and that the action is modified by an X-lock on each row that satisfies the condition.

This action, when confronted with concurrency, can lead to deadlock, even for different rows.

In this case we should come to the conclusion that multithreading of a table should be avoided. Because they are likely to cause deadlocks.


--------------------------------------------------------------------------------------------

The following is an extension study:

So now another problem, if the update action will scan the entire table, and the U lock to get the release action, this will cause a lot of performance consumption,

Whether the big data will be different. Does adding an index improve? Does adding a primary key improve?

We do the following experiments

1, do not increase the primary key or index, only the table to enlarge the amount of data, and then update the 1000th Row Records


--Environment Establishment statement
Create Table DBO.A2
(
ID int identity (1,1),
Value1 Char (10),
value2 varchar (20)
)

DECLARE @n int
Set @n=1
--Test data population
while (@n<10000)
Begin
INSERT into DBO.A2
(Value1, value2
)
VALUES
(REPLICATE (' C ', 10)
, CONVERT (varchar, REPLICATE (' F ', 20))
)
Set @n=@n+1
End

The resulting lock and number of releases and number of lines *2 the gap is not very large, which allows us to directly confirm the table scan of the Terrible


2, increase the primary key, and expand the amount of data

Create a table with the int listed as the self-added primary key, insert 1W data, update the 1000th row record with the primary key

This time we can see that the entire transaction does not use the U lock at all, but first through the S lock, positioning to the specific page, and then directly lock the corresponding row, to implement the update.


3, does not add the primary key, but the query table to add index, data volume 10000


Create Table dbo.a3
(
ID int identity (1,1),
Value1 Char (10),
value2 varchar (20)
)
Create INDEX IX_A3 on A3 (ID)

DECLARE @n int
Set @n=1

while (@n<10000)
Begin
INSERT into dbo.a3
(Value1, value2
)
VALUES
(REPLICATE (' C ', 10)
, CONVERT (varchar, REPLICATE (' F ', 20))
)
Set @n=@n+1
End


1:18,051 of which are index pages,

This query results in rows of about 80 lines, which is the end of the output, which repeatedly shows the release of the S lock.

We can judge this by querying the index, locating the corresponding row of the index, and then adding a U-lock to the corresponding data row. Note that you can see here is an IU action on the index page, which is to determine if the change will affect the index page, because the index page has not been accounts, thereby releasing the IU lock.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.