Tải bản đầy đủ (.pdf) (10 trang)

Microsoft SQL Server 2008 R2 Unleashed- P144 pot

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (312 KB, 10 trang )

ptg
1374
CHAPTER 37 Locking and Performance
could lead to greater page-level contention because the likelihood of the data rows being
requested by different processes residing on the same page is greater. Using row-level
locking increases the concurrent access to the data.
On the other hand, row-level locking consumes more resources (memory and CPU) than
page-level locks simply because there is a greater number of rows than pages in a table. If
a process needed to access all rows on a page, it would be more efficient to lock the entire
page than acquire a lock for each individual row. This would result in a reduction in the
number of lock structures in memory that the Lock Manager would have to manage.
Which is better—greater concurrency or lower overhead? As shown earlier, in Figure 37.6,
it’s a trade-off. As lock size decreases, concurrency improves, but performance degrades
due to the extra overhead. As the lock size increases, performance improves due to less
overhead, but concurrency degrades. Depending on the application, the database design,
and the data, either page-level or row-level locking can be shown to be better than the
other in different circumstances.
SQL Server makes the determination automatically at runtime—based on the nature of the
query, the size of the table, and the estimated number of rows affected—of whether to
initially lock rows, pages, or the entire table. In general, SQL Server attempts to first lock
at the row level more often than the page level, in an effort to provide the best concur-
rency. With the speed of today’s CPUs and the large memory support, the overhead of
managing row locks is not as expensive as in the past. However, as the query processes
and the actual number of resources locked exceed certain thresholds, SQL Server might
attempt to escalate locks from a lower level to a higher level, as appropriate.
At times, SQL Server might choose to do both row and page locking for the same query. For
example, if a query returns multiple rows, and if enough contiguous keys in a nonclustered
index page are selected to satisfy the query, SQL Server might place page locks on the index
while using row locks on the data. This reduces the need for lock escalation.
Lock Escalation
When SQL Server detects that the locks acquired by a query are using too much memory


and consuming too many system resources for the Lock Manager to manage the locks effi-
ciently, it automatically attempts to escalate row, key, or page locks to table-level locks.
For example, because a query on a table continues to acquire row locks and every row in
the table will eventually be accessed, it makes sense for SQL Server to escalate the row
locks to a table-level lock. After the table-level lock is acquired, the row-level locks are
released. This helps reduce locking overhead and keeps the system from running out of
available lock structures. Recall from earlier sections in this chapter that the potential
need for lock escalation is reflected in the intent locks that are acquired on the table by
the process locking at the row or page level. While the default behavior in SQL Server is to
escalate to table-level locks, SQL Server 2008 introduces the capability to escalate row or
page locks to a single partition via the
LOCK_ESCALATION setting in ALTER TABLE. This new
option allows you to specify whether escalation is always to the table or partition level.
The
LOCK_ESCALATION setting can also be used to prevent lock escalation entirely.
ptg
1375
SQL Server Lock Granularity
37
NOTE
SQL Server never escalates row locks to page locks, only to table or partition-level
locks. Also, multiple partition-level locks are never escalated to a single table-level
lock.
What are the lock escalation thresholds in SQL Server? Currently, SQL Server attempts
lock escalation under the following conditions:
. Whenever a single T-SQL statement acquires at least 5,000 locks on a single reference
of a table, table partition, or index (this value is subject to change in subsequent
service packs). Note that lock escalation does not occur if the locks are spread across
multiple objects in the same statement—for example, 4,000 locks on one index and
2,500 locks on another.

. When the amount of memory required by lock resources exceeds 40% of the avail-
able Database Engine memory pool
NOTE
Generally, if more memory is required for lock resources than is currently available in
the Database Engine memory pool, the Database Engine allocates additional memory
dynamically to satisfy the request for locks as long as more computer memory is avail-
able and the
max server memory threshold has not been reached. However, if allocat-
ing additional memory would cause paging at the operating system level, more lock
space is not allocated. If no more memory is available, or the amount of memory allo-
cated to lock resources reaches 60% of the memory acquired by an instance of the
Database Engine, further requests for locks generate an out-of-lock memory error.
If locks cannot be escalated because of lock conflicts, SQL Server reattempts lock escalation
when every 1,250 additional locks are acquired. For example, if another process is also
holding locks at the page or row level on the same table (indicated by the presence of that
process’s intent lock on the table), lock escalation cannot take place if the lock types are
not compatible until the lower-level locks are released by the other processes. In this case,
SQL Server continues acquiring locks at the row or page level until the table lock becomes
available.
Controlling Lock Escalation
Escalating locks to the table or partition level can lead to locking contention or blocking
for other transactions attempting to access a row or page in the same table. Under certain
circumstances, you might want to disable lock escalation.
As mentioned previously, lock escalation can be enabled or disabled at the table level
using the
ALTER TABLE command:
ALTER TABLE tablename set (LOCK_ESCALATION ={ AUTO | TABLE | DISABLE } )
ptg
1376
CHAPTER 37 Locking and Performance

Setting the option to
AUTO allows SQL Server to escalate to the table or partition level.
Setting the option to
DISABLE prevents escalation to the table or partition level.
SQL Server 2008 also supports disabling lock escalation for all tables in all databases
within a SQL Server instance using either the 1211 or 1224 trace flags. Trace flag 1211
completely disables lock escalation, regardless of the memory required for lock resources.
However, when the amount of memory required for lock resources exceeds 60% of the
maximum available Database Engine memory, an out-of-lock memory error is generated.
Alternatively, trace flag 1224 disables the built-in lock escalation based on the number of
locks acquired, but lock escalation is still possible when the 40% of available Database
Engine memory threshold is reached. However, as noted previously, if the locks cannot be
escalated, SQL Server could still run out of available memory for locks.
NOTE
You should be extremely careful when considering disabling lock escalation via the
trace flags. A poorly designed application could potentially exhaust the available SQL
Server memory with excessive lock structures and seriously degrade SQL Server perfor-
mance. It is usually preferable to control lock escalation at the object level via the
ALTER TABLE command.
Lock Compatibility
If a process has already locked a resource, the granting of lock requests by other transac-
tions on the same resource is governed by the lock compatibility matrix within SQL
Server. Table 37.3 shows the lock compatibility matrix for the locks most commonly
acquired by the SQL Server Lock Manager, indicating which lock types are compatible and
which lock types are incompatible when requested on the same resource.
TABLE 37.3 SQL Server Lock Compatibility Matrix
Requested Lock Type Existing Lock Type
IS S U IX SIX X Sch-S SCH-M BU
Intent shared Yes Yes Yes Yes Yes No Yes No No
Shared Yes Yes Yes No No No Yes No No

Update Yes Yes No No No No Yes No No
Intent exclusive Yes No No Yes No No Yes No No
Shared with intent exclusive Yes No No No No No Yes No No
Exclusive No No No No No No Yes No No
Schema stability Yes Yes Yes Yes Yes Yes Yes No Yes
Schema modify No No No No No No No No No
Bulk update No No No No No No Yes No Yes
ptg
1377
Locking Contention and Deadlocks
37
For example, if a transaction has acquired a shared lock on a resource, the possible lock
types that can be acquired on the resource by other transactions are intent shared, shared,
update, and schema stability locks. Intent exclusive,
SIX, exclusive, schema modification,
and bulk update locks are incompatible with a shared lock and cannot be acquired on the
resource until the shared lock is released.
Locking Contention and Deadlocks
In the grand scheme of things, the most likely culprits of SQL Server application perfor-
mance problems are typically poorly written queries, poor database and index design, and
locking contention. Whereas the first two problems result in poor application perfor-
mance, regardless of the number of users on the system, locking contention becomes
more of a performance problem as the number of users increases. It is further
compounded by increasingly complex or long-running transactions.
Locking contention occurs when a transaction requests a lock type on a resource that is
incompatible with an existing lock type on the resource. By default, the process waits
indefinitely for the lock resource to become available. Locking contention is noticed in
the client application through the apparent lack of response from SQL Server.
Figure 37.9 demonstrates an example of locking contention. Process 1 has initiated a
transaction and acquired an exclusive lock on page 1:325. Before Process 1 can acquire the

lock that it needs on page 1:341 to complete its transaction, Process 2 acquires an exclu-
sive lock on page 1:341. Until Process 2 commits or rolls back its transaction and releases
the lock on Page 1:341, the lock continues to be held. Because this is not a deadlock
scenario (which is covered in the “Deadlocks” section, later in this chapter), by default,
SQL Server takes no action. Process 1 simply waits indefinitely.
Process 1
Process 2
Page 1:325
Page 1:341
Locks
Requests Locks
1
23
X
X
Lock
Wait
X
FIGURE 37.9 Locking contention between two processes.
ptg
1378
CHAPTER 37 Locking and Performance
Identifying Locking Contention
When a client application appears to freeze after submitting a query, this is often due to
locking contention. To identify locking contention between processes, you can use the
SSMS Activity Monitor, as discussed earlier in this chapter, in the “Monitoring Lock
Activity in SQL Server” section; use the
sp_who2 stored procedure; or query the
sys.dm_tran_locks system catalog view. Figure 37.10 shows an example of a blocking lock
as viewed in the SSMS Activity Monitor.

To identify whether a process is being blocked using
sp_who2, examine the BlkBy column.
If any value besides ‘-’ is displayed, it is the SPID of the process that is holding the block-
ing lock. In the following output of
sp_who2 (edited for space), you can see that process 57
is
SUSPENDED, waiting on a lock held by process 53:
exec sp_who2
go
SPID Status Login HostName BlkBy DBName Command

*** info for internal processes deleted ***
51 sleeping rrankins LATITUDED830-W7 . master AWAITING COMMAND
52 sleeping SQLADMIN LATITUDED830-W7 . msdb AWAITING COMMAND
53 sleeping rrankins LATITUDED830-W7 . bigpubs2008 AWAITING COMMAND
54 sleeping rrankins LATITUDED830-W7 . tempdb AWAITING COMMAND
FIGURE 37.10 Examining locking contention between two processes in SSMS Activity Monitor.
ptg
1379
Locking Contention and Deadlocks
37
55 sleeping rrankins LATITUDED830-W7 . master AWAITING COMMAND
56 sleeping SQLADMIN LATITUDED830-W7 . msdb AWAITING COMMAND
57 SUSPENDED rrankins LATITUDED830-W7 53 bigpubs2008 INSERT
58 sleeping rrankins LATITUDED830-W7 . bigpubs2008 AWAITING COMMAND
59 RUNNABLE rrankins LATITUDED830-W7 . master SELECT INTO
To determine what table, page, or rows are involved in blocking and at what level the
blocking is occurring, you can query the
sys.dm_tran_locks catalog view, as shown in
Listing 37.5.

LISTING 37.5 Viewing Locking Contention by Using the sys.dm_tran_locks View
use bigpubs2008
go
select str(request_session_id, 4,0) as spid,
convert (varchar(12), db_name(resource_database_id)) As db_name,
case when resource_database_id = db_id() and resource_type = ‘OBJECT’
then convert(char(12), object_name(resource_Associated_Entity_id))
else convert(char(16), resource_Associated_Entity_id)
end as object,
convert(varchar(12), resource_type) as resource_type,
convert(varchar(8), request_mode) as mode,
convert(varchar(14), resource_description) as resource_desc,
convert(varchar(6), request_status) as status
from sys.dm_tran_locks
order by request_session_id, 3 desc
go
spid db_name object resource_type mode resource_desc status

52 msdb 0 DATABASE S GRANT
53 bigpubs2008 673416192655360 PAGE IX 1:608 GRANT
53 bigpubs2008 673416192655360 KEY X (928195c101b1) GRANT
53 bigpubs2008 391941215944704 KEY X (59d1a826552c) GRANT
53 bigpubs2008 391941215944704 PAGE IX 1:280 GRANT
53 bigpubs2008 stores OBJECT IX GRANT
53 bigpubs2008 0 DATABASE S GRANT
56 msdb 0 DATABASE S GRANT
57 bigpubs2008 391941215944704 PAGE IS 1:280 GRANT
57 bigpubs2008 391941215944704 KEY S (59d1a826552c) WAIT
57 bigpubs2008 stores OBJECT IS GRANT
57 bigpubs2008 0 DATABASE S GRANT

From this output, you can see that Process 57 is waiting for a shared (S) lock on key
59d1a826552c of page 1:280 of the stores table. Process 53 has an intent exclusive (IX)
ptg
1380
CHAPTER 37 Locking and Performance
lock on that page because it has an exclusive (
X) lock on a key on that page. (Both have
the same
resource_Associated_Entity_id of 59d1a826552c.)
As an alternative to sp_who and the sys.dm_tran_locks view, you can also get specific
information on any blocked processes by querying the
sys.dm_os_waiting_tasks system
catalog view, as shown in Listing 37.6.
LISTING 37.6 Viewing Blocked Processes by Using the sys.dm_os_waiting_tasks View
select convert(char(4), session_id) as spid,
convert(char(8), wait_duration_ms) as duration,
convert(char(8), wait_type) as wait_type,
convert(char(3), blocking_session_id) as blk,
resource_description
from sys.dm_os_waiting_tasks
where blocking_session_id is not null
go
spid duration wait_type blk resource_description


57 134118 LCK_M_S 53 keylock hobtid=391941215944704 dbid=8 id=lockfd43800
mode=X associatedObjectId=391941215944704
Setting the Lock Timeout Interval
If you do not want a process to wait indefinitely for a lock to become available, SQL Server
allows you to set a lock timeout interval by using the

SET LOCK_TIMEOUT command. You
specify the timeout interval in milliseconds. For example, if you want your processes to
wait only 5 seconds (that is, 5,000 milliseconds) for a lock to become available, you
execute the following command in the session:
SET LOCK_TIMEOUT 5000
If your process requests a lock resource that cannot be granted within 5 seconds, the state-
ment is aborted, and you get the following error message:
Server: Msg 1222, Level 16, State 52, Line 1
Lock request time out period exceeded.
To examine the current LOCK_TIMEOUT setting, you can query the system function
@@lock_timeout:
select @@lock_timeout
go

5000
ptg
1381
Locking Contention and Deadlocks
37
If you want processes to abort immediately if the lock cannot be granted (in other words,
no waiting at all), you set the timeout interval to
0. If you want to set the timeout interval
back to infinity, execute the
SET_LOCK_TIMEOUT command and specify a timeout interval
of
-1.
Minimizing Locking Contention
Although setting the lock timeout prevents a process from waiting indefinitely for a lock
request to be granted, it doesn’t address the cause of the locking contention. In an effort
to maximize concurrency and application performance, you should minimize locking

contention between processes as much as possible. Some general guidelines to follow to
minimize locking contention include the following:
. Keep transactions as short and concise as possible. The shorter the period of time
locks are held, the less chance for lock contention. Keep commands that are not
essential to the unit of work being managed by the transaction (for example, assign-
ment selects, retrieval of updated or inserted rows) outside the transaction.
. Keep statements that comprise a transaction in a single batch to eliminate unneces-
sary delays caused by network input/output (I/O) between the initial
BEGIN TRAN
statement and the subsequent COMMIT TRAN commands.
. Consider coding transactions entirely within stored procedures. Stored procedures
typically run faster than commands executed from a batch. In addition, because
they are server resident, stored procedures reduce the amount of network I/O that
occurs during execution of the transaction, resulting in faster completion of the
transaction.
. Commit updates in cursors frequently and as soon as possible. Cursor processing is
much slower than set-oriented processing and causes locks to be held longer.
NOTE
Even though cursors might run more slowly than set-oriented processing, cursors can
sometimes be used to minimize locking contention for updates and deletions of a large
number of rows from a table, which might result in a table lock being acquired. The
UPDATE or DELETE statement itself might complete faster; however, if it is running with
an exclusive lock on the table, then no other process can access the table until it com-
pletes. By using a cursor to update a large number of rows one row at a time and com-
mitting the changes frequently, the cursor uses page- or row-level locks rather than a
table-level lock. It might take longer for the cursor to complete the actual update or
delete, but while the cursor is running, other processes are still able to access other
rows or pages in the table that the cursor doesn’t currently have locked.
. Use the lowest level of locking isolation required by each process. For example, if
dirty reads are acceptable and accurate results are not imperative, consider using

transaction Isolation Level 0. Use the Repeatable Read or Serializable Read isolation
levels only if absolutely necessary.
ptg
1382
CHAPTER 37 Locking and Performance
. Never allow user interaction between a BEGIN TRAN statement and a COMMIT TRAN
statement because doing so may cause locks to be held for an indefinite period of
time. If a process needs to return rows for user interaction and then update one or
more rows, consider using optimistic locking or Snapshot Isolation in your applica-
tion. (Optimistic locking is covered in the “Optimistic Locking” section, later in this
chapter.)
. Minimize “hot spots” in a table. Hot spots occur when the majority of the update
activity on a table occurs within a small number of pages. For example, hot spots
occur for concurrent insertions to the last page of a heap table or the last pages of a
table with a clustered index on a sequential key. You can often eliminate hot spots
by creating a clustered index in a table on a column or columns to order the rows in
the table in such a way that insert and update activity is spread out more evenly
across the pages in the table.
Deadlocks
A deadlock occurs when two processes are each waiting for a locked resource that the other
process currently holds. Neither process can move forward until it receives the requested
lock on the resource, and neither process can release the lock it is currently holding until
it can receive the requested lock. Essentially, neither process can move forward until the
other one completes, and neither one can complete until it can move forward.
Two primary types of deadlocks can occur in SQL Server:
. Cycle deadlocks—A cycle deadlock occurs when two processes acquire locks on
different resources, and then each needs to acquire a lock on the resource that the
other process has. Figure 37.11 demonstrates an example of a cycle deadlock.
In Figure 37.11, Process 1 acquires an exclusive lock on page 1:201 in a transaction.
At the same time, Process 2 acquires an exclusive lock on page 1:301 in a transac-

Process 1
Process 2
Page 1:201
Page 1:301
Locks
Requests
Requests
Locks
1
2
4
3
Lock
Wait
X X
X
Lock
Wait
X
FIGURE 37.11 An example of a cycle deadlock.
ptg
1383
Locking Contention and Deadlocks
37
tion. Process 1 then attempts to acquire a lock on page 1:301 and begins waiting for
the lock to become available. Simultaneously, Process 2 requests an exclusive lock on
page 1:201, and a deadlock, or “deadly embrace,” occurs.
. Conversion deadlocks—A conversion deadlock occurs when two or more processes
each hold a shared lock on the same resource within a transaction and each wants
to promote the shared lock to an exclusive lock, but neither can do so until the

other releases the shared lock. An example of a conversion deadlock is shown in
Figure 37.12.
It is often assumed that deadlocks happen at the data page or data row level. In fact, dead-
locks often occur at the index page or index key level. Figure 37.13 depicts a scenario in
which a deadlock occurs due to contention at the index key level.
SQL Server automatically detects when a deadlock situation occurs. A separate process in
SQL Server, called
LOCK_MONITOR, checks the system for deadlocks roughly every 5 seconds.
In the first pass, this process detects all the processes that are waiting on a lock resource.
The
LOCK_MONITOR thread checks for deadlocks by examining the list of waiting lock
requests to see if any circular lock requests exist between the processes holding locks and
the processes waiting for locks. When the
LOCK_MONITOR detects a deadlock, SQL Server
aborts the transaction of one of the involved processes. How does SQL Server determine
which process to abort? It attempts to choose as the deadlock victim the transaction that
it estimates would be least expensive to roll back. If both processes involved in the dead-
lock have the same rollback cost and the same deadlock priority, the deadlock victim is
chosen randomly.
Process 1
Process 2
Page 1:201
Locks
Requests
Locks
Locks
1
4
2
3

Lock
Wait
XX
S S
FIGURE 37.12 An example of a conversion deadlock.

×