572 Chapter13•PerformanceTuning other already has locked—a vicious circle occurs where neither can complete without the other first releasing its locks. Locking Locking is responsible for ensuring database users don’t interfere with each other, and is an essential component of any Relational Database Management system. Locking provides concurrency control within the database engine. A transaction is one or more actions, treated as a unit of work. There are a set of database properties that help understand transactions and the importance of locking: Atomic An atomic transaction must either complete or fail. No aspect of the transaction must be allowed to succeed or fail without all changes succeeding or failing. Should one modification fail, the whole transaction should be rolled back. Consistent Data must be consistent when a transaction completes. Data integrity must not be compromised by a transaction. Isolated User transactions should be isolated from each other. Data affected by one transaction can be accessed by other transactions only in the state it was before the transaction began, or after the transaction completes. Durable Once a transaction has completed the changes must persist, even if there is a crash or system failure. SQL Server uses careful transaction management to enforce Atomicity and Consistency. The Transaction Log ensures transaction durability since all changes are first written to the transaction log. Finally, Isolation is provided by locking within the database engine. Blocking We should consider locking to be completely normal activity within the database engine. When there are lots of users working on a SQL Server database or in a situation with a poor index strategy or badly written queries there can be many thousands of locks. If a transaction holds many locks or holds locks for a long time, eventually this can cause blocking. Blocking occurs when a transaction is waiting for a lock on a resource, usually because a lock is already held by another task. PerformanceTuning•Chapter13 573 Deadlocks Excessive blocking can significantly impact performance and as such, it’s really important to get visibility of tasks that are blocking each other and investigate options to help them coexist. Severe blocking can lead to deadlocks, which will result in SQL Server ending one session, causing a rollback. In a deadlock situation a vicious circle can occur when two (sometimes more) tasks, each already holding locks, are waiting for locks that the other holds. Figure 13.6 shows an illustration. It’s called a deadlock because both processes could wait endlessly for the other to release the locks it needs unless SQL Server intervened. There’s a mechanism within SQL Server to detect and end deadlocks whereby SQL Server will end the task that is least expensive to rollback. Transaction Isolation Levels SQL Server provides five isolation levels for transactions, which include various pessimistic to optimistic locking strategies. These isolation levels provide control over a balance between concurrency and data integrity. Isolation levels may be selected Figure 13.6 Deadlock Scenario 574 Chapter13•PerformanceTuning based on application requirements for data consistency and user concurrency. Isolation levels may provide good concurrency (nonlocking), but may provide incon- sistent data; this may be acceptable in some scenarios. In other cases, data consistency is important, as such performance may be sacrificed in favor of consistent data. Lock Escalation SQL Server always tries to lock the fewest resources possible to maximize concurrency. Fewer locks provides good concurrency but there is an overhead in system resources while managing locks. There are times when SQL Server is managing so many individual locks that it becomes more efficient to increase a single lock on an object at a higher level—this is lock escalation. If a task holds a large number of row or key-range locks, these may be escalated to a table lock. If SQL Server initially takes page locks, these can be escalated to table locks. SQL Server will never escalate from row to page level locks. A new feature introduced in SQL Server 2008 is that with partitioned tables, lock escalation may occur to the partition level, instead of the table. SQL Profiler includes an event for lock escalation (Lock:Escalation). Lock Compatibility There are approximately 22 lock types in SQL Server 2008, each providing a different lock type for resources. Some lock types allow other processes to read the data, too (also depends on transaction isolation level), whereas other lock types require exclu- sive access to data and will wait for existing tasks to complete and release locks before taking their own locks. There’s a lock compatibility matrix that shows the logic around which locks can be taken simultaneously. SQL Server Books Online includes a full lock compatibility matrix, and Table 13.3 contains a compatibility summary of the six most common lock types. PerformanceTuning•Chapter13 575 Detecting and Resolving Locking Problems SQL Server 2008 Management Studio has an Activity Monitor that shows sessions and their state (whether they’re running, waiting, or sleeping). Activity Monitor is available by right-clicking the instance name within Management Studio and features a new look for SQL Server 2008 (see Figure 13.7). Requested Lock Existing Lock IS S U IX SIX X Intent Shared (IS) ¸ ¸ ¸ ¸ ¸ ˚ Shared (S) ¸ ¸ ¸ ˚ ˚ ˚ Update (U) ¸ ¸ ˚ ˚ ˚ ˚ Intent Exclusive (IX) ¸ ˚ ˚ ¸ ˚ ˚ Shared with Intent Exclusive (SIX) ¸ ˚ ˚ ˚ ˚ ˚ Exclusive (X) ˚ ˚ ˚ ˚ ˚ ˚ Table 13.3 Common Lock Compatibility Matrix Figure 13.7 Activity Monitor in SQL Server 2008 Management Studio 576 Chapter13•PerformanceTuning SQL Server Profiler provides good information; in particular, there’s a blocked process report that can capture locking details for sessions exceeding the blocked process threshold (controlled by sp_configure). In situations where there’s an intermittent performance problem and blocking is a suspect, the blocked process report can be useful. There are a number of DMVs that provide visibility of locks held by specific sessions and any blocked processes. The DMVs sys.dm_exec_ requests shows sessions that are suspended waiting for a lock. Additionally, querying sys.dm_tran_locks shows more detailed locking information. If blocking problems are serious there’s a good chance deadlocks may also occur. SQL Server Profiler provides a good level of information, including Deadlock Chain (all sessions involved in the deadlock). Profiler can also capture a deadlock graph, which reveals the commands being executed, locks held, and the session nominated as the deadlock victim. Sometimes deadlocks can be few and far between, but they can still cause problems and a continuous Profiler trace may seem excessive to identify the problem. In this scenario Trace Flag 1222 can be useful since this will output deadlock details to the SQL Server Error Log. Once deadlock information has been captured in the SQL Server Error Log, review the processes that are conflicting. Sometimes they’re different processes and at other times they’re multiple instances of the same query or stored procedure. Try to rework the query or stored procedure to overcome the locking problem, perhaps reduce the size of the transaction, create a new index, or use an alternative join strategy. Configuring&Implementing… ImplementingSQLServerTraceFlags Trace Flags can be enabled from SQL Server Configuration Manager, using the –T1222 startup parameter or by using DBCC traceon (1222, –1). The DBCC traceon method will not require a service restart, however making the change through Configuration Manager requires a service restart. . intervened. There’s a mechanism within SQL Server to detect and end deadlocks whereby SQL Server will end the task that is least expensive to rollback. Transaction Isolation Levels SQL Server provides. locks that the other holds. Figure 13.6 shows an illustration. It’s called a deadlock because both processes could wait endlessly for the other to release the locks it needs unless SQL Server intervened identify the problem. In this scenario Trace Flag 1222 can be useful since this will output deadlock details to the SQL Server Error Log. Once deadlock information has been captured in the SQL Server