---- --- --- --- ---54 HumanResources.Department PAGE IX GRANT 54 HumanResources.Department KEY X GRANT Transaction 2 ensures that the transaction isolation level is set to the default a
Trang 1- - -
-54 HumanResources.Department PAGE IX GRANT
54 HumanResources.Department KEY X GRANT
Transaction 2 ensures that the transaction isolation level is set to the default and then attempts to read
the same row transaction 1 is updating:
Transaction 2 USE AdventureWorks2008;
SET TRANSACTION ISOLATION LEVEL
READ COMMITTED;
SELECT Name FROM HumanResources.Department
WHERE DepartmentID = 1;
There is no result yet for transaction 2 It’s waiting for transaction 1 to complete — blocked by
transac-tion 1’s exclusive lock
Requeryingsys.dm_tran_locksreveals that the second transaction (SPID 51) has an intent to share
(IS) read lock and is waiting for a share (S) read lock.
Result:
- - -
-51 HumanResources.Department PAGE IS GRANT
51 HumanResources.Department PAGE S WAIT
54 HumanResources.Department KEY X GRANT
54 HumanResources.Department PAGE IX GRANT
54 HumanResources.Department PAGE IX GRANT
54 HumanResources.Department KEY X GRANT
54 HumanResources.Department KEY X GRANT While transaction 1 is holding its exclusive lock, transaction 2 has to wait In other words, transaction 1
is blocking transaction 2
Now, transaction 1 commits the transaction and releases the exclusive lock:
Transaction 1
COMMIT TRANSACTION
Immediately, transaction 1 completes and releases its locks Transaction 2 springs to life and performs
the select, reading the committed change
Trang 2
-New Name
The point of transaction isolation level read committed is to avoid reading uncommitted data What if
the update doesn’t change the data? If transaction 1 updates the data from ‘‘John’’ to ‘‘John,’’ what’s the
harm of reading ‘‘John’’?
SQL Server handles this situation by not respecting an exclusive lock if the page hasn’t been changed,
i.e., if the page isn’t flagged as dirty This means that sometimes (because there’s probably more data
on the page than just the data in question) SQL Server can avoid locking and blocking if the data isn’t
actually being changed Cool, no?
You can prove this behavior by reexecuting the previous locking and blocking sample code with the
same update value
Monitoring Locking and Blocking
Without the ability to see the lock, the various types of locks and their durations may seem like pure
theory Fortunately, SQL Server is a relatively open environment, and it’s easy to inspect the current
locks from several possible points of view
Viewing blocking with Management Studio reports
With Management Studio, transaction information for a server or database may be seen using the
Stan-dard Reports, available from the server or database context menus, which pull data from the dynamic
management views The transaction-related reports include All Transactions, All Blocking Transactions
(shown in Figure 66-2), Top Transactions by Age, Top Transactions by Blocked Transaction Count, Top
Transactions by Lock Count, Resource Locking by Object, and User Statistics
Viewing blocking with Activity Monitor
The Activity Monitor (see Figure 66-3) is completely rewritten for SQL Server 2008 and includes process
information It’s available both on the toolbar and in the Object Explorer’s server context menu
For more information on the Activity Monitor, refer to Chapter 6, ‘‘Using Management
Studio.’’
Using Profiler
You can also use SQL Server Profiler to watch blocked processes using the Error and Warnings: Blocked
Process Report event
Trang 3FIGURE 66-2
Management Studio’s All Blocking Transactions Report is a quick way to view key transaction locking
and blocking information
Best Practice
Of the many possible methods to monitor locking and blocking, Activity Monitor and Management
Studio’s Summary page provide the best overall view to determine whether locking and blocking is a
problem To home in on the specific locking and blocking issues, Profiler provides the actual code for the
transactions involved
The catch to using Profiler is that by default the server is not configured to fire the blocked process
event To enable it, you have to configure theblocked process thresholdsetting Because that’s
an advanced option, you must enable ‘‘Show advanced options’’ first The following snippet sets the
blocking duration to one second:
sp_configure ‘show advanced options’, 1;
Trang 4Activity Monitor displays information about the current locks and any blocking going on In this
instance, SPID 53 is blocking SPID 54
GO
RECONFIGURE;
GO
sp_configure ‘blocked process threshold’, 1;
GO
RECONFIGURE;
This means that the server will check every second for blocked statements, and for any statement that
has been blocked for longer than one second, the blocked process report event will fire Depending on
when the last check was done, a statement may be blocked for more than the threshold value before it
is reported This can be seen by setting the threshold to a large value, say 10 seconds
The result is a complete XML-formatted disclosure of the blocked and blocking process (see
Fig-ure 66-4) Saving this trace to a file and analyzing it in total is an excellent locking and blocking
debugging technique
Trang 5FIGURE 66-4
SQL Server Profiler can monitor and display the blocked and blocking code in XML
Querying locks with DMVs
Personally, I’m a big fan of SQL Server dynamic management views, but then I like to write queries The
sys.dm_exec_requestsDMV reports several interesting facts about current sessions, including the
blocking session ID:
SELECT session_id, blocking_session_id FROM sys.dm_exec_requests
WHERE blocking_session_id > 0
My friend and SQL Server MVP Adam Machanic has developed an extensive script based
on this DMV that reports all active sessions, their statements, and their blocking status It’s available at: http://sqlblog.com/blogs/adam
machanic/archive/2008/12/31/a-gift-of-script-for-2009-who-is-active-redux.aspx
Viewing all the locks is possible with thesys.dn_tran_locksDMV The following query joins with
other DMVs to provide a complete picture of the locks in a database:
Trang 6request_session_id as Spid,
Coalesce(s.name + ‘.’ + o.name + isnull(‘.’ + i.name,’’),
s2.name + ‘.’ + o2.name,
db.name) AS Object,
l.resource_type as Type,
request_mode as Mode,
request_status as Status
FROM sys.dm_tran_locks l
LEFT JOIN sys.partitions p
ON l.resource_associated_entity_id = p.hobt_id
LEFT JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
LEFT JOIN sys.objects o
ON p.object_id = o.object_id
LEFT JOIN sys.schemas s
ON o.schema_id = s.schema_id
LEFT JOIN sys.objects o2
ON l.resource_associated_entity_id = o2.object_id
LEFT JOIN sys.schemas s2
ON o2.schema_id = s2.schema_id
LEFT JOIN sys.databases db
ON l.resource_database_id = db.database_id
WHERE resource_database_id = DB_ID()
ORDER BY Spid, Object, CASE l.resource_type
When ‘database’ Then 1 when ‘object’ then 2 when ‘page’ then 3 when ‘key’ then 4 Else 5 end
Deadlocks
A deadlock is a special situation that occurs only when transactions with multiple tasks compete for the
same data resource out of order For example:
■ Transaction 1 has a lock on data A and needs to lock data B to complete its transaction
and
■ Transaction 2 has a lock on data B and needs to lock data A to complete its transaction
Each transaction is stuck waiting for the other to release its lock, and neither can complete until the
other does Unless an outside force intercedes, or one of the transactions gives up and quits, this
situation could last until the end of time
Trang 7While a deadlock typically involves two transactions, it can be a cyclic locking and blocking problem
involving several transactions — for example, A is waiting on B, which is waiting on C, which is
waiting on A
Deadlocks used to be a serious problem Fortunately, SQL Server handles deadlocks refreshingly well
I’ve seen deadlocks result from a single parallelized UPDATE query The parallel threads
of the query deadlocked on index updates This is why I strongly recommend that OLTP servers run with maximum degree of parallelism (maxdop) set to 1.
Creating a deadlock
It’s easy to create a deadlock situation in SQL Server using two connections in Management Studio’s
Query Editor, as illustrated in Figure 66-5 Transaction 1 and transaction 2 will simply try to update the
same rows but in the opposite order Use a third window to watch the locks using Activity Monitor or
one of the DMV queries
FIGURE 66-5
Creating a deadlock situation in Management Studio using two connections tiled vertically
Trang 81 Create two query windows In one paste the following:
Transaction 1
Step 1
USE OBXKites
BEGIN TRANSACTION
Update Contact
SET LastName = ‘Jorgenson’
WHERE ContactCode = ‘101’
Transaction 1
Step 3
Update Product
SET ProductName
= ‘DeadLock Identification Tester’
Where ProductCode = ‘1001’
COMMIT TRANSACTION
2 Paste the following in the second window:
Transaction 2
Step 2
USE OBXKites
BEGIN TRANSACTION
Update Product
SET ProductName
= ‘DeadLock Repair Kit’
Where ProductCode = ‘1001’
Update Contact
SET FirstName = ‘Neals’
Where ContactCode = ‘101’
COMMIT TRANSACTION
Execute in the code in the first query window:
Transaction 1
Step 1
USE OBXKites
BEGIN TRANSACTION
Update Contact
SET LastName = ‘Jorgenson’
WHERE ContactCode = ‘101’
Transaction 1 now has an exclusive lock onContactCode 101
Execute step 2 in the second window:
Trang 9Transaction 2 Step 2
USE OBXKites BEGIN TRANSACTION
Update Product
SET ProductName
= ‘DeadLock Repair Kit’
Where ProductCode = ‘1001’
Update Contact
SET FirstName = ‘Neals’
Where ContactCode = ‘101’
COMMIT TRANSACTION Transaction 2 will gain an exclusive lock onProductCode 1001and then try to grab an exclusive
lock onContactCode 101, but transaction 1 already has it locked
It’s not a deadlock yet because although transaction 2 is waiting for transaction 1, transaction 1 is
not waiting for transaction 2 At this point, if transaction 1 finished its work and issued aCOMMIT
TRANSACTION, the data resource would be freed; transaction 2 could get its lock on the contact row
and be on its way as well
The trouble begins when transaction 1 tries to updateProductCode 1001 It can’t get an exclusive
lock because transaction 2 already has an exclusive lock So when the following code is executed:
Transaction 1 Step 3
Update Product
SET ProductName
= ‘DeadLock Identification Tester’
Where ProductCode = ‘1001’
COMMIT TRANSACTION transaction one returns the following friendly error message in about two seconds The deadlock can
also be viewed using SQL Server Profiler (as shown in Figure 66-6)
Server: Msg 1205, Level 13, State 50, Line 1
Transaction (Process ID 5173) was deadlocked on lock resources with
another process and has been chosen
as the deadlock victim Rerun the
transaction
Transaction 2 completes as if there’s no problem Result:
(1 row(s) affected) (1 row(s) affected)
Trang 10SQL Server Profiler can monitor deadlocks using the Locks: Deadlock Graph event and can display
the resource conflict that caused the deadlock
Automatic deadlock detection
As the previous deadlock code demonstrated, SQL Server automatically detects a deadlock situation by
examining the blocking processes and rolling back the transaction that has performed the least amount
of work A process within SQL Server is constantly checking for cross-blocking locks and even detects
deadlocks that span multiple servers using distributed queries The deadlock-detection delay is typically
instantaneous
Handling deadlocks
Once a deadlock occurs, SQL Server will determine the transaction to roll back based on an estimate
of the amount of work it requires The transaction selected as the deadlock victim will need to be
performed again
Before SQL Server 2005, trapping a deadlock could only occur at the client, but fortunately try-catch
error-handling code can trap a 1205 error, and deadlocks can now be handled in the catch block If you
catch the deadlock within the transaction, your only option is to roll back the transaction However,
you can then rerun your transaction using T-SQL logic, as shown in the following example: