1. 概述

SQL Server 数据库支持多个用户同时访问数据库,但当用户同时访问数据库时,就会造成并发问题,锁的机制能很好地解决这个问题,保证数据的完整性和一致性;
SQL Server 自带锁机制,若是简单的数据库访问机制,完全能满足用户的需求;但对于数据完全与数据完整性有特殊要求,就必须自动控制锁机制解决;

2. SQL Server 锁机制

锁是处理 SQL Server 中并发问题的最有效手段,当多个事务访问同一数据时,能很好地保证数据的完整性和一致性;
在很多数据库系统中(如DB2、MySQL、Oracle)都有锁机制,其规则也大同小异;
在 SQL Server 中采用系统来管理锁,SQL Server 中采用的是动态加锁的机制;
SQL Server 中有一套默认的锁机制,若用户在使用数据库的过程中不设置任何锁,系统将自动对锁管理;

3. 锁模式

在 SQL Server 中有不同的锁,在各种锁的类型中有些是能相互兼容的,锁的类型决定了并发发生时数据资源的范文模式,在 SQL Server 中常用的锁以下 5 种;

  1. 更新锁:一般使用于可更新数据,能防止并发访问中的脏读情况以及在数据更新时可能会出现的死锁情况,更新锁一般会在对数据进行查询更新时使用;若事务修改资源,更新锁会转换为排他锁,否则会转换为共享锁;在 SQL Server 中,当一个事务访问资源时获得更新锁,其他事务能够对资源进行访问,但不允许排他式访问;
  2. 排他锁:在事务对资源进行数据更改操作(如 INSERT、UPDATE、DELETE)时使用;排他锁能保证同一数据不会被多个事务同时进行更改操作;
  3. 共享锁:共享锁允许多个事务同时访问同一资源,但不允许其他事务修改当前事务所使用的数据;
  4. 键范围锁:能防止幻读,通过保护行之间键的范围还能防止对事务访问的记录集进行幻读插入或删除;
  5. 架构锁:数据库引擎在表数据定义语言(DDL)操作(如添加列或删除表)的过程中使用架构修改锁;保持该锁期间,架构锁将阻止对表进行并发访问;即架构锁在释放前将阻止所有外围操作;

4. 锁的粒度

Microsoft SQL Server 数据库引擎具有多粒度锁定,允许一个事务锁定不同类型的资源;
为了减少锁定的开销,数据库引擎自动将资源锁定在适合任务的级别;锁定在较小的粒度(如行)能提高并发度,但开销较高,因为若锁定了许多行,就需要持有更多的锁;
锁定在加大的粒度(如表)会降低并发,因为锁定整个表限制了其他事务对表中任意部分的访问;但其开销较低,因为需要维护的锁较少;
20220413
数据库引擎通常必须获取多粒度级别上才能完整地保护资源,多粒度级别上的所称为层次结构;

4. 查看锁

在 SQL Server数据库中,能通过查看 sys.dm_tran_locks 返回 SQL Server 数据库中有关当前活动的锁的管理的信息;
向锁管理器发出的已授予锁或正等待授予锁的每个当前活动请求分别对应一行;结果集中的列大体分为两组:资源组和请求组;

5. 死锁

在两个或多个任务中,若每一个任务都锁定了其他的资源,就会造成永久的阻塞,这种情况就是死锁;
20220412

形成死锁有以下 4 个必要条件:

  • 互斥条件:资源不能被共享,只能被一个进程施使用;
  • 请求与保持条件:已获得资源的进程能同时申请其他资源;
  • 非剥夺条件:已分配的资源不能从该进程中被剥夺;
  • 循环等待条件:多个进程构成环路,且每个进程都在等待相邻进程正在使用的资源;

在一个复杂的数据库系统中很难百分之百地避免死锁,但能按照以下的访问策略减少死锁的发生;

  1. 所有事务中以相同的次序使用资源;避免出现循环;
  2. 减少事务持有资源的时间,避免事务中的用户交互;
  3. 让事务保持在一个批处理中;
  4. 由于锁的隔离级别越高共享锁的时间就越长,因此能降低隔离级别来达到减少竞争的目的;
  5. 使用绑定连接;

注意: SQL Server 数据库引擎自动检测 SQL Server 中的死锁循环;数据库引擎选择一个会话作为死锁的牺牲品,然后终止当前事务(出现错误)来打断死锁;

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐