When this database option is enabled and a transaction runs at the Read Committed isolation level, all statements within the transaction see a snapshot of the data as it exists at the st
Trang 1table-level isolation hints within the query Using table-level hints is covered later in this
chapter, in the section “Table Hints for Locking.”
Read Uncommitted Isolation
If you set the Read Uncommitted mode for a session, no isolation is provided to the
SELECT queries in that session A transaction that is running with this isolation level is not
immune to dirty reads, nonrepeatable reads, or phantom reads
To set the Read Uncommitted mode for a session, you run the following statements from
the client:
T-SQL—Use SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
ODBC—Use the function call SQLSetConnectAttr with Attribute set to
SQL_ATTR_TXN_ISOLATION and ValuePtr set to SQL_TXN_READ_UNCOMMITTED
OLE DB—Use the function call ITransactionLocal::StartTransaction with the
isoLevel set to ISOLATIONLEVEL_READUNCOMMITTED
ADO—Set the IsolationLevel property of the Connection object to
adXactReadUncommitted
ADO.NET—For applications using the System.Data.SqlClient managed namespace,
call the SqlConnection.BeginTransaction method and set the IsolationLevel
option to ReadUncommitted
You need to be careful when running queries at Read Uncommitted isolation; it is possible
to read changes that have been made to data that are subsequently rolled back In essence,
the accuracy of the results cannot be guaranteed You should use this mode only when
you need to get information quickly from an online transaction processing (OLTP)
data-base, without affecting or being affected by the ongoing updates and when the accuracy of
the results is not critical
Read Committed Isolation
The Read Committed mode is the default locking-isolation mode for SQL Server With
Read Committed as the transaction isolation level, read operations can read pages only for
transactions that have already been committed No “dirty reads” are allowed Locks
acquired by update transactions are held for the duration of the transaction However, in
this mode, read requests within the transaction release locks as soon as the query finishes
reading the data Although this improves concurrent access to the data for updates, it does
not prevent nonrepeatable reads or phantom reads For example, within a transaction, a
process could read one set of rows early in the transaction and then, before reading the
information again, another process could modify the result set, resulting in a different
result set being read the second time
Because Read Committed is the default isolation level for SQL Server, you do not need to
do anything to set this mode If you need to set the isolation level back to Read
Committed mode for a session, you run the following statements from the client:
T-SQL—Use SET TRANSACTION ISOLATION LEVEL READ COMMITTED
Trang 2ODBC—Use the function call SQLSetConnectAttr with Attribute set to
SQL_ATTR_TXN_ISOLATION and ValuePtr set to SQL_TXN_READ_COMMITTED
OLE DB—Use the function call ITransactionLocal::StartTransaction with
isoLevel set to ISOLATIONLEVEL_READCOMMITTED
ADO—Set the IsolationLevel property of the Connection object to
adXactReadcommitted
ADO.NET—For applications using the System.Data.SqlClient managed namespace,
call the SqlConnection.BeginTransaction method and set the IsolationLevel
option to ReadCommitted
Read Committed Snapshot Isolation
When the READ_COMMITTED_SNAPSHOT database option is set to ON, sessions running with
the Read Committed isolation mode use row versioning to provide statement-level read
consistency When this database option is enabled and a transaction runs at the Read
Committed isolation level, all statements within the transaction see a snapshot of the data
as it exists at the start of the statement
When the READ_COMMITTED_SNAPSHOT option is enabled for a database, SQL Server
main-tains versions of each row that is modified Whenever a transaction modifies a row, an
image of the row before modification is copied into a page in the version store, which is a
collection of data pages in tempdb If multiple transactions modify a row, multiple versions
of the row are linked in a version chain Queries running with Read Committed Snapshot
isolation retrieve the last version of each row that had been committed when the
state-ment started, providing a statestate-ment-level snapshot of the data
In the Read Committed Snapshot isolation mode, read operations do not acquire shared
page or row locks on the data Therefore, readers using row versioning do not block other
processes modifying the same data, and, similarly, processes modifying the data do not
block the readers In addition, because the read operations do not acquire locks, locking
overhead is reduced However, processes modifying data still block other processes
modify-ing data because two operations cannot modify the same data at the same time Exclusive
locks on modified data are still acquired and held until the end of the transaction
While locking overhead is reduced for read operations when using Read Committed
Snapshot isolation, it does introduce overhead to maintain the row versions in tempdb In
addition, tempdb must have sufficient space to hold the row versions in addition to the
space required for normal tempdb operations
You might want to consider enabling the READ_COMMITTED_SNAPSHOT database option when
blocking that occurs between read and write operations affects performance to the point
that the overhead of creating and managing row versions is offset by the concurrency
benefits You may also consider using Read Committed Snapshot isolation when an
appli-cation requires absolute accuracy for long-running aggregations or queries where data
values must be consistent to the point in time that the query starts
Trang 3NOTE
You can use Read Committed Snapshot isolation mode with most existing SQL Server
applications without making any change to the application code itself if the applications
are written to use the default Read Committed isolation level The behavior of Read
Committed, whether to use row versioning or not, is determined by the database
option setting, and this can be enabled or disabled without requiring any changes to
the application code
Repeatable Read Isolation
In Repeatable Read mode, SQL Server provides the same level of isolation for updates as in
Read Committed mode, but it also allows the data to be read many times within the same
transaction and guarantees that the same values will be read each time Repeatable Read
isolation mode prevents other users from updating data that has been read within the
transaction until the transaction in which it was read is committed or rolled back This
way, the reading transaction does not pick up changes to the rows it read previously
within the transaction However, this isolation mode does not prevent additional rows
(that is, phantom reads) from appearing in the subsequent reads
Although preventing nonrepeatable reads is desirable for certain transactions, it requires
holding locks on the data that has been read until the transaction is completed This
reduces concurrent access for multiple update operations and causes performance
degrada-tion due to lock waits and locking contendegrada-tion between transacdegrada-tions It can also potentially
lead to deadlocks (Deadlocking is discussed in more detail in the “Deadlocks” section,
later in this chapter.)
To set Repeatable Read mode for a session, you run the following statements from the client:
T-SQL—Use SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
ODBC—Use the function call SQLSetConnectAttr with Attribute set to
SQL_ATTR_TXN_ISOLATION and ValuePtr set to SQL_TXN_REPEATABLEREAD
OLE DB—Use the function call ITransactionLocal::StartTransaction with
isoLevel set to ISOLATIONLEVEL_REPEATABLEREAD
ADO—Set the IsolationLevel property of the Connection object to adXact
REPEAT-ABLEREAD
ADO.NET—For applications using the System.Data.SqlClient managed namespace,
call the SqlConnection.BeginTransaction method and set the IsolationLevel
option to RepeatableRead
Serializable Read Isolation
Serializable Read mode is similar to repeatable reads but adds to it the restriction that rows
cannot be added to a result set that was read previously within a transaction This prevents
phantom reads In other words, Serializable Read locks the existing data being read as well
as rows that do not yet exist It accomplishes this by locking the data being read In
Trang 4tion, SQL Server puts locks on the range of values being read so that additional rows cannot
be added to the range
For example, say you run a query in a transaction that retrieves all records for the Sales
table in the bigpubs2008 database for a store with the stor_id of 7066 To prevent
addi-tional sales records from being added to the Sales table for this store, SQL Server locks the
range of values with stor_id of 7066 It accomplishes this by using key-range locks, which
are discussed in the “Serialization and Key-Range Locking” section, later in this chapter
Although preventing phantom reads is desirable for certain transactions, Serializable Read
mode, like Repeatable Read, reduces concurrent access for multiple update operations and
can cause performance degradation due to lock waits and locking contention between
transactions, and it can potentially lead to deadlocks
To set Serializable Read mode for a session, you run the following statements from the
client:
T-SQL—Use SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
ODBC—Use the function call SQLSetConnectAttr with Attribute set to
SQL_ATTR_TXN_ISOLATION and ValuePtr set to SQL_TXN_SERIALIZABLE
OLE DB—Use the function call ITransactionLocal::StartTransaction with
isoLevel set to ISOLATIONLEVEL_SERIALIZABLE
ADO—Set the IsolationLevel property of the Connection object to adXact
SERIALIZABLE
ADO.NET—For applications using the System.Data.SqlClient managed namespace,
call the SqlConnection.BeginTransaction method and set the IsolationLevel
option to Serializable
Snapshot Isolation
Snapshot Isolation is an additional isolation level available in SQL Server 2008 Similar to
Read Committed Snapshot, Snapshot Isolation mode uses row versioning to take a
point-in-time snapshot of the data However, unlike Read Committed Snapshot isolation, which
provides a statement-level snapshot of the data, Snapshot Isolation maintains a snapshot
of the data for the duration of the entire transaction A data snapshot is taken when the
transaction starts and the snapshot remains consistent for the duration of the transaction
Snapshot Isolation mode provides the benefit of repeatable reads without acquiring and
holding shared locks on the data that is read This can help minimize locking and
block-ing problems between read operations and update operations Read operations do not
have to wait for write operations and writes don’t have to wait for reads
To set the Snapshot Isolation mode for a session, you run the following statement:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
Trang 5In addition, to be able to request the Snapshot Isolation mode in a session, you must
enable the database option ALLOW_SNAPSHOT_ISOLATION with the ALTER DATABASE
command:
ALTER DATABASE dbname SET ALLOW_SNAPSHOT_ISOLATION ON
When Snapshot Isolation mode is enabled, SQL Server assigns a transaction sequence
number to each transaction that manipulates data using row versioning When either the
READ_COMMITTED_SNAPSHOT or ALLOW_SNAPSHOT_ISOLATION database option is set to ON, SQL
Server stores a version of the previously committed image of the data row in tempdb
whenever the row is modified by a transaction Each of these versions is marked with the
transaction sequence number of the transaction that made the change The versions of the
modified rows are linked together in a chain, with the most recent version of the row
always stored in the current database and the versioned rows stored in tempdb
When a transaction requests a read of data, it searches the version chain to locate the last
committed version of the data row with a lower transaction sequence number than the
current transaction Row versions are kept in tempdb only long enough to satisfy the
requirements of any transactions running under row versioning–based isolation levels SQL
Server keeps track of the sequence number of the oldest outstanding transaction and
period-ically deletes all row versions stamped with transaction sequence numbers lower than that
You might consider using snapshot isolation in the following instances:
When you want optimistic concurrency control
When it is unlikely that your transaction would have to be rolled back because of an
update conflict
When an application generates reports based on long-running, multistatement
queries that must have point-in-time consistency
With systems that are incurring a high number of deadlocks because of read/write
contention
There is a risk to using snapshot isolation, however If two client applications both retrieve
the same data and then both attempt to write changes to the data back to the database,
the second application could potentially overwrite the first application’s changes This is
called a lost update error Fortunately, SQL Server 2008 resolves this problem by blocking
the second transaction’s writes So, although snapshot isolation provides benefits for
resolving conflicts between read and write operations, there can still be conflicts between
multiple write operations For systems with heavy read and insert activity and with little
concurrent updating of the same resource, snapshot isolation can provide a solution for
concurrency issues
Another cost of snapshot isolation is that it can make heavy use of tempdb For this
reason, you should locate tempdb on its own high-performance drive system
Trang 6NOTE
Only one of the transaction isolation levels can be active at any given time for a user
session The isolation level you set within an application is active for the duration of
the connection or until it is manually reset To check the current transaction isolation
level settings, you run the DBCC USEROPTIONS command and examine the value for
isolation level, as in the following example:
DBCC USEROPTIONS
go
Set Option Value
-
-textsize 2147483647
language us_english
dateformat mdy
datefirst 7
lock_timeout -1
quoted_identifier SET
arithabort SET
ansi_null_dflt_on SET
ansi_warnings SET
ansi_padding SET
ansi_nulls SET
concat_null_yields_null SET
isolation level snapshot
Be aware that DBCC USEROPTIONS reports an isolation level of Read Committed
Snapshot when the database option READ_COMMITTED_SNAPSHOT is set to ON and the
current transaction isolation level is set to Read Committed The actual isolation level
in effect for the user session is Read Committed
The Lock Manager
The responsibility for ensuring lock conflict resolution between user processes falls on the
SQL Server Lock Manager SQL Server automatically assigns locks to processes to guarantee
that the current user of a resource (for example, a data row or page, an index row or page,
a table, an index, or a database) has a consistent view of that resource, from the beginning
to the end of a particular operation In other words, what you start with is what you work
with throughout your transaction Nobody can change what you are working on in
midstate, thereby ensuring the consistency of your transaction
Trang 7The Lock Manager is responsible for deciding the appropriate lock type (for example,
shared, exclusive, update) and the appropriate granularity of locks (for example, row, page,
table), according to the type of operation being performed and the amount of data being
affected Based on the type of transaction, the SQL Server Lock Manager chooses different
types of lock resources For example, a CREATE INDEX statement might lock the entire
table, whereas an UPDATE statement might lock only a specific row
The Lock Manager also manages compatibility between lock types attempting to access the
same resources, resolves deadlocks, and escalates locks to a higher level, if necessary
The Lock Manager manages locks for both shared data and internal system resources For
shared data, the Lock Manager manages row locks, page locks, and table locks on tables, as
well as data pages, text pages, and leaf-level index pages Internally, the Lock Manager uses
latches to manage locking on index rows and pages, controlling access to internal data
structures and, in some cases, for retrieving individual rows of data Latches provide better
system performance because they are less resource intensive than locks Latches also
provide greater concurrency than locks Latches are typically used for operations such as
page splits, deletion of index rows, movement of rows in an index, and so on The main
difference between a lock and a latch is that a lock is held for the duration of the
transac-tion, and a latch is held only for the duration of the operation for which it is required
Locks are used to ensure the logical consistency of data, whereas latches are used to ensure
the physical consistency of the data and data structures
The remainder of this chapter examines how the Lock Manager determines the type and
level of lock to assign, based on the type of command being executed, number of rows
affected, and lock isolation level in effect
Monitoring Lock Activity in SQL Server
To monitor the performance of a system, you need to keep track of locking activity in SQL
Server The following are the most commonly used methods to do so:
Querying the sys.dm_tran_locks dynamic management view directly
Viewing locking activity with SQL Server Profiler
Monitoring locks with Performance Monitor
As you read through the rest of this chapter, you might want to examine or monitor the
locking activity for the examples presented To assist you in that effort, the following
sections describe the methods of examining lock activity in SQL Server 2008
Querying the sys.dm_tran_locks View
The sys.dm_tran_locks dynamic management view returns information about all the
locks currently granted or waiting to be granted in SQL Server (The information is
popu-lated from the internal lock management structures in SQL Server 2008.) This view
provides no historical information; rather, the data in this view corresponds to live Lock
Trang 8Manager information This data can change at any time for subsequent queries of the view
as locks are acquired and released
The information returned by the view can be divided into two main groups: resource
information and lock request information The resource information describes the
resource on which the lock request is being made, and the request information provides
details on the lock request itself Table 37.1 describes the most useful data columns
returned by the sys.dm_tran_locks view
TABLE 37.1 Useful Columns Returned by the sys.dm_tran_locks View
resource_type Indicates the type of resource the lock is being
held or requested on
resource_subtype Indicates a subtype of the resource_type, if any
resource_database_id Indicates the database ID of the database where
the resource resides
resource_description Provides information about the resource that is not
available from other resource columns
resource_associated_entity_id Indicates the ID of the entity in a database that
the resource is associated with
resource_lock_partition Indicates the ID of the associated partition for a
resource that is partitioned
request_mode Indicates the lock mode of the request that has
been granted or is being waited on
request_type Indicates the request type (The only current value
is LOCK.) request_status Indicates the current status of this request (GRANT,
CONVERT, or WAIT)
request_reference_count Returns an approximate number of times the same
requestor has requested this resource
request_lifetime Specifies a code indicating when the lock on the
resource is released
request_session_id Indicates the ID of the session that generated the
corresponding request
request_exec_context_id Indicates the ID of the execution context of the
process that generated the lock request
Trang 9Table 37.2 lists the possible lock request modes that can be displayed in the request_mode
column of the sys.dm_tran_locks view
TABLE 37.1 Useful Columns Returned by the sys.dm_tran_locks View
request_request_id Indicates the batch ID of the process that
gener-ated the request
request_owner_type Indicates the type of entity that owns the request
Possible values include, but are not limited to, TRANSACTION, CURSOR, and SESSION
request_owner_id Specifies the ID of the specific owner of this
request This value is used for transactions for which this is the transaction ID
request_owner_guid Indicates the GUID of the specific owner of the
lock request This value is used only by a distrib-uted transaction where the value corresponds to the MS DTC GUID for that transaction
request_owner_lockspace_id Represents the lockspace ID of the requestor The
lockspace ID determines whether two requestors are compatible with each other and can be granted locks in modes that would otherwise conflict with one another
lock_owner_address Indicates the memory address of the internal data
structure used to track the request
TABLE 37.2 Lock Request Modes
1 N/A No access provided to the requestor NULL
4 Shared Acquisition of a shared lock on the resource S
5 Update Acquisition of an update lock on the resource U
6 Exclusive Exclusive lock granted on the resource X
Trang 10Listing 37.1 provides an example of a query against the sys.dm_tran_locks view
LISTING 37.1 An Example of a Query Against the sys.dm_tran_locks View
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(20), object_name(resource_Associated_Entity_id))
else convert(char(20), resource_Associated_Entity_id)
TABLE 37.2 Lock Request Modes
10 Intent Shared lock with intent for an update lock on subordinate
resources
SIU
11 Intent Shared lock with intent for an exclusive lock on subordinate
resources
SIX
12 Intent Update lock with an intent for an exclusive lock on
subordi-nate resources
UIX
13 Bulk BULK UPDATE lock used for bulk copy operations BU
14 Key-Range Shared lock on the range between keys and shared lock on
the key at the end of the range; used for serializable range scan
Range_S_S
15 Key-Range Shared lock on the range between keys, with an update lock
on the key at the end of the range
Range_S_U
16 Key-Range Exclusive lock used to prevent inserts into a range between
keys
RangeIn-N
17 Key-Range Key-range conversion lock created by overlap of RangeIn-N
and shared (S) locks
RangeIn-S
18 Key-Range Key-range conversion lock created by overlap of RangeIn-N
and update (U) locks
RangeIn-U
19 Key-Range Key-range conversion lock created by overlap of RangeIn-N
and exclusive (X) locks
RangeIn-X
20 Key-Range Key-range conversion lock created by overlap of RangeIn-N
and RangeS_S locks
RangeX-S
21 Key-Range Key-Range conversion lock created by overlap of RangeIn-N
and RangeS_U locks
RangeX-U
22 Key-Range Exclusive lock on range between keys, with an exclusive lock
on the key at the end of the range
RangeX-X