1.锁
锁是事务获取的一种控制资源,用于数据资源,防止其他事务对数据进行冲突的或不兼容的访问。
锁模式及其兼容性
排他锁(exclusive lock),共享锁(shared lock);还有一些其他类型的锁(更新锁,意向锁、架构锁)。
当试图修改数据时,事务会为所依赖的数据资源请求排他锁,一旦授予,事务将一直持有排他锁,直至事务完成。这种锁模式之所以称为排他锁,是因为对于相同的数据资源,如果有其他事务已经获得了该资源的任何类型的锁,就不能再获得该资源的排他锁;如果有其他事务已经获得了该资源的排他锁,就不能再获得该资源的任何类型的锁。这是修改行为的默认处理方式,而且这种默认行为不能改变——不能改变为修改数据资源而请求锁模式(排他锁),也不能改变持有的时间长度(直到事务完成)。
当试图读取数据时,事务默认会为所依赖的数据资源请求其享锁,读操作一完成,就立即释放资源上的共享锁。这种锁模式之所以称为共享锁,是因为多个事务可以同时持有同一数据资源上的共享锁。虽然当修改数据时不能改变请求的锁模式和持续时间,但当读取数据时可以对如何处理锁定进行控制。
事务之间的相互制约关系就是锁的兼容性。
排他锁和共享锁的兼容性:如果数据正在由一个事务进行修改,其他事务就既不能修改该数据,也不能读取(至少默认不能)该数据,直到第一个事务完成。如果数据正在由另一个事务读取,其他事务就不能修改该数据(至少默认不能)。
可锁定资源的类型
SQL Server 可以锁定不同类型或粒度的资源,这些资源类型包括RID 或KEY(行)、PAGE(页)、对象(例如,表)、数据库等。行位于页中,而页则是包含表或索引数据的物理数据块。
2. 检测阻塞
如果一个事务持有某一数据资源上的锁,而另一事务请求相同资源上的不兼容的锁,则对新锁的请求将被阻塞,发出请求的事务进入等待状态。在默认情况下,被阻塞的请求会一直等待,直到原来的事务释放相关的锁。
只要能够在合理的时间范围内满足请求,系统中的阻塞就是正常的。但是,如果一些请求等待了太长的时间,可能就需要手工排除阻塞状态,看看能采取什么措施来防止这样长时间的延迟。例如,事务的运行时间过长,会导致持有锁的时间也过久;这时可以尝试缩短事务处理,把不属于工作单元的操作移到事务外面。在某些情况下,应用程序中的bug也可能导致事务一直打开;这时可以先把这样的bug找出来,修复它,确保在所有情况下都可以关闭事务。
要得到有关锁的信息(包括已经授予的锁和当前会话正等待授予的锁),可以在动态管理视图(DMV,dynamic management view)sys.dm_tran_locks;
SELECT
request_session_id AS spid,
resource_type AS restype,
resource_database_id AS dbid,
DB_NAME(resource_database_id) AS dbname,
resource_description AS res,
resource_associated_entity_id AS resid,
request_mode AS mode,
request_status AS status
FROM sys.dm_tran_locks;
每个会话都由惟一的服务器进程标识符(SPID,server process ID)进行标识,可以通过查询@@SPID函数来查看会话的SPID。