• Aucun résultat trouvé

Querying Transaction Information by Session

Dans le document Transact-SQL Recipes (Page 154-158)

This recipe demonstrates how to find out more information about an active transaction. To demon-strate, I’ll describe a common scenario: your application is encountering a significant number of blocks with a high duration. You’ve been told that this application always opens up an explicit transaction prior to each query.

To illustrate this scenario, I’ll execute the following SQL (representing the application code causing the concurrency issue):

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRAN

SELECT *

FROM HumanResources.Department INSERT HumanResources.Department (Name, GroupName)

VALUES ('Test', 'QA')

In a separate/new SQL Server Management Studio query window, I would like to identify all open transactions by querying thesys.dm_tran_session_transactionsDynamic Management View (DMV):

SELECT session_id, transaction_id, is_user_transaction, is_local FROM sys.dm_tran_session_transactions

WHERE is_user_transaction = 1

This returns the following (your actual session IDs and transaction IDs will vary):

session_id transaction_id is_user_transaction is_local

54 145866 1 1

Now that I have a session ID to work with, I can dig into the details about the most recent query executed by queryingsys.dm_exec_connectionsandsys.dm_exec_sql_text:

SELECT s.text

FROM sys.dm_exec_connections c

CROSS APPLY sys.dm_exec_sql_text(c.most_recent_sql_handle) s WHERE session_id = 54

This returns the last statement executed. (I could have also used thesys.dm_exec_requests DMV for an ongoing and active session; however, nothing was currently executing for my example transaction, so no data would have been returned.)

text

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRAN

SELECT *

FROM HumanResources.Department INSERT HumanResources.Department (Name, GroupName)

VALUES ('Test', 'QA')

Since I also have the transaction ID from the first query againstsys.dm_tran_session_

transactions, I can use thesys.dm_tran_active_transactionsto learn more about the transaction itself:

SELECT transaction_begin_time, CASE transaction_type

WHEN 1 THEN 'Read/write transaction' WHEN 2 THEN 'Read-only transaction' WHEN 3 THEN 'System transaction' WHEN 4 THEN 'Distributed transaction' END tran_type,

CASE transaction_state

WHEN 0 THEN 'not been completely initialized yet' WHEN 1 THEN 'initialized but has not started' WHEN 2 THEN 'active'

WHEN 3 THEN 'ended (read-only transaction)'

WHEN 4 THEN 'commit initiated for distributed transaction' WHEN 5 THEN 'transaction prepared and waiting resolution' WHEN 6 THEN 'committed'

WHEN 7 THEN 'being rolled back' WHEN 8 THEN 'been rolled back' END tran_state

FROM sys.dm_tran_active_transactions WHERE transaction_id = 145866

This returns information about the transaction begin time, the type of transaction, and the state of the transaction:

transaction_begin_time tran_type tran_state 2008-08-26 10:03:26.520 Read/write transaction active

How It Works

This recipe demonstrated how to use various DMVs to troubleshoot and investigate a long-running, active transaction. The columns you decide to use depend on the issue you are trying to trouble-shoot. In this scenario, I used the following troubleshooting path:

• I queriedsys.dm_tran_session_transactionsin order to display a mapping between the ses-sion ID and the transaction ID (identifier of the individual transaction).

• I queriedsys.dm_exec_connectionsandsys.dm_exec_sql_textin order to find the latest command executed by the session (referencing themost_recent_sql_handlecolumn).

• Lastly, I queriedsys.dm_tran_active_transactionsin order to determine how long the trans-action was opened, the type of transtrans-action, and the state of the transtrans-action.

Using this troubleshooting technique allows you to go back to the application and pinpoint query calls for abandoned transactions (opened but never committed), and transactions that are inappropriate because they run too long or are unnecessary from the perspective of the application.

Locking

Locking is a normal and necessary part of a relational database system, ensuring the integrity of the data by not allowing concurrent updates to the same data or viewing of data that is in the middle of being updated. Locking can also prevent users from reading data while it is being updated. SQL Server manages locking dynamically; however, it is still important to understand how Transact-SQL queries impact locking in SQL Server. Before proceeding on to the recipe, I’ll briefly describe SQL Server locking fundamentals.

Locks help prevent concurrency problems from occurring. Concurrency problems (discussed in detail in the next section, “Transaction, Locking, and Concurrency”) can happen when one user attempts to read data that another is modifying, modify data that another is reading, or modify data that another transaction is trying to modify.

Locks are placed against SQL Server resources. How a resource is locked is called itslock mode.

Table 3-2 reviews the main lock modes that SQL Server has at its disposal.

Table 3-2.SQL Server Lock Modes

Name Description

Shared lock Shared locks are issued during read-only, non-modifying queries. They allow data to be read, but not updated by other processes while being held.

Intent lock Intent locks effectively create a lock queue, designating the order of connections and their associated right to update or read resources. SQL Server uses intent locks to show future intention of acquiring locks on a specific resource.

Update lock Update locks are acquired prior to modifying the data. When the row is modified, this lock is escalated to an exclusive lock. If not modified, it is downgraded to a shared lock. This lock type prevents deadlocks if two connections hold a shared lock on a resource and attempt to convert to an exclusive lock, but cannot because they are each waiting for the other transaction to release the shared lock.

Exclusive lock This type of lock issues a lock on the resource that bars any kind of access (reads or writes). It is issued duringINSERT,UPDATE, orDELETE statements.

Schema modification This type of lock is issued when a DDL statement is executed.

Schema stability This type of lock is issued when a query is being compiled. It keeps DDL operations from being performed on the table.

Bulk update This type of lock is issued during a bulk-copy operation. Performance is increased for the bulk copy operation, but table concurrency is reduced.

Key-range Key-range locks protect a range of rows (based on the index key)—for example, protecting rows in anUPDATEstatement with a range of dates from 1/1/2005 to 12/31/2005. Protecting the range of data prevents row inserts into the date range that would be missed by the current data modification.

You can lock all manner of objects in SQL Server, from a single row in a database, to a table, to the database itself. Lockable resources vary in granularity, from small (at the row level) to large (the entire database). Small-grain locks allow for greater database concurrency, because users can exe-cute queries against specified unlocked rows. Each lock placed by SQL Server requires memory, however, so thousands of individual row locks can also affect SQL Server performance. Larger-grained locks reduce concurrency, but take up fewer resources. Table 3-3 details the resources SQL Server can apply locks to.

Table 3-3.SQL Server Lock Resources

Resource Name Description

Allocation unit A set of related pages grouped by data type, for example, data rows, index rows, and large object data rows.

Application An application-specified resource.

DB An entire database lock.

Extent Allocation unit of eight 8KB data or index pages.

File The database file.

HOBT A heap (table without a clustered index) or B-tree.

Metadata System metadata.

Key Index row lock, helping prevent phantom reads. Also called a key-range lock, this lock type uses both a range and a row component. The range represents the range of index keys between two consecutive index keys. The row component represents the lock type on the index entry.

Object A database object (for example a view, stored procedure, function).

Page An 8KB data or index page.

RID Row identifier, designating a single table row.

Table A resource that locks entire table, data, and indexes.

Not all lock types are compatible with each other. For example, no other locks can be placed on a resource that has already been locked by an exclusive lock. The other transaction must wait or time out until the exclusive lock is released. A resource locked by an update lock can only have a shared lock placed on it by another transaction. A resource locked by a shared lock can have other shared or update locks placed on it.

Locks are allocated and escalated automatically by SQL Server. Escalation means that finer-grain locks (row or page locks) are converted into coarse-finer-grain table locks. SQL Server will attempt to initialize escalation when a single Transact-SQL statement has more than 5,000 locks on a single table or index, or if the number of locks on the SQL Server instance exceeds the available memory threshold. Locks take up system memory, so converting many locks into one larger lock can free up memory resources. The drawback to freeing up the memory resources, however, is reduced concurrency.

Note

SQL Server 2008 has a new table option that allows you to disable lock escalation or enable lock escala-tion at the partiescala-tion (instead of table) scope. I’ll demonstrate this in the “Controlling a Table’s Lock Escalaescala-tion Behavior” recipe.

Dans le document Transact-SQL Recipes (Page 154-158)