锁机制

SQL Server支持多用户的并发操作,这些操作有的是读取数据、有的是更新数据、如果一个用户要读取正在被其他用户修改的数据、或者一个用户要修改其他用户正在修改的数据,就需要锁的机制来规范这些操作,使得在保证数据一致性的情况下,又不会对并发性产生较大的影响。

锁的粒度

锁的粒度就是锁定资源的类型,如数据库、文件、区、表、索引、数据页、表记录、索引键值等。比较常用的锁粒度主要是指表、数据页、记录、索引键值,其中粒度最低的类型是记录锁,最高的是表锁。锁的粒度越低,所需锁的个数就越多,耗费的内存也就越大。但是锁粒度越高,并发性也会越低。

管理一个锁需要96个字节大小。

例如一个包含5000行记录的表,如果锁定所有记录,可以使用5000个行锁锁定每行记录(需要96B*5000=480000字节内存),也可以用一个表锁锁定整个表(只需要96个字节内存)。

数据库锁的目的主要是防止在用户操作数据库时,其他用户改变其选项设置、将其删除或离线。

文件锁、区锁的目的是在改变文件大小或对表、索引分配空间时防止争用。

锁模式

锁模式是指资源被锁定的程度,或者与其他锁兼容的程度。

如果两个锁相互兼容,就可以同时附加在同一个资源上。如果两个锁不兼容,则只能附加两者之一。

锁模式主要包括共享(S)、排他(X)、更新(U)这3种。Share、Exclusive、Update。

为了更有效率的管理锁,在数据页或表等上层资源上可以附加意向锁,意向锁可以与共享、排他、更新锁组合在一起。可以构成意向共享锁(IS)、意向排他锁(IX)、意向更新锁(IU)。I表示的是单词Intent。

1、共享锁(S)

同一个资源上可以附加多个共享锁,共享锁一般在查询操作中使用。可以附加在表、数据页或者记录上,一个资源可以由多个查询操作访问,这是共享的含义。

共享锁一般在数据读取完成后即释放,如在read committed隔离级别下,(read committed--事务只能读取到其他事务提交后的修改结果),使用全表扫描方式查询一个表时,会对扫描到的记录附加共享锁。

如果是目标记录则读出,然后释放其锁。若不是目标记录,则马上释放锁,这些锁不会保持到查询完成,更不会保持到事务结束,除非查询操作附加了特定的锁提示。

2、排他锁(X)

DML  (Data Manipulation Language数据操作语言,DML语句是SQL命令中最常用的部分,包括insert、delete、update、select等基本操作语句) 操作时,一般会对修改的记录附加排他锁,排他锁与其他任何锁都不兼容,若一个资源上附加了排他锁,其他连接不能对其执行任何操作。排他锁一般会保持到事务结束才释放。

3、更新锁(U)

     更新锁主要是对表执行Update操作时,在搜索目标记录过程中对记录附加的一种锁,一般表示为U锁,若记录满足修改条件则把其U锁转换为X锁,若不满足修改条件,则把U锁释放。

     U锁与U锁不兼容,一行记录只能附加一个U锁。

     搜索目标记录附加U锁,而不是附加S锁的目的是为了降低发生死锁的几率。因为同一条记录可以附加多个S锁,若搜索满足修改条件的记录时,对记录附加S锁,可能会因为要同时转换为X锁而导致发生死锁。

     如果一个连接修改一个表的记录row_m,并对此记录附加了X锁,另外一个连接继续修改这个表的记录row_n。在未使用索引的情况下,第2个连接搜索目标记录row_n时,会使用全表扫描对其搜索到的每一行记录都附加U锁,当扫描至row_m并对其附加U锁时,就会与其已持有的X锁互斥而被阻塞,从而发生等待。

     也就是说,在没有索引的情况下,两个连接不能同时对同一个表执行update、delete操作,即使这两个连接操作的是不同的目标记录。

     解决这种等待问题的方法是对表创建索引,使得搜索目标记录时可以利用索引直接定位,不必使用全表扫描,从而避免在搜索row_n时对其他记录也附加U锁。

4、意向锁

     意向锁锁定的资源类型主要是表和数据页。在默认的read committed隔离级别下,查询表中的记录时,SQL Server先对表附加意向共享锁,再对目标记录所在的数据页附加意向共享锁,最后最记录附加共享锁。

     如果已经由其他连接对表附加了X锁,则在对表附加意向共享锁时,就会因为两者不兼容而阻塞,不需要再检测表中各个记录锁的情况。如果要修改表中的记录则先对表附加意向排他锁,再对目标记录所在的数据页

     附加IX(意向排他锁),最后对目标记录附加X锁。

5、架构锁

Sch-M及Sch-S两种模式,分别表示Schema Modification 架构更改锁 与 Schema Stability 架构稳定锁。

DDL(Data Definition Language数据定义语言,是SQL语言中的一个分类,用于创建及修改数据库对象,如创建表、修改表的结构等操作,主要包括create、alter、drop、truncate、comment、grant reloke等语句。执行DDL语句时,主要通过修改系统基表记载数据库对象发生的各种变化)操作时附加于表的。Sch_M锁与其他锁都不兼容,从而在修改表的结构时,通过附加Sch-M锁可以防止其他连接访问表的数据,也可以在访问表的数据时,防止其他连接修改表的结构。Sch-M锁会保持到事务结束。

Sch-S锁与其他锁都兼容。Sch-S锁在编译过程完成之后、操作执行之前即释放,而不会保持到操作结束或事务结束。

6、大容量跟新锁

     在执行大容量数据装载操作时,如果对目标表附加了 TABLOCK 提示或者执行 sp_tableoption系统过程对表设置了 table lock on bulk load 选项,SQL Server会对表附加大容量更新锁,大容量更新锁表示为BU(Bulk Update)。