T-SQL:事务锁下的并发处理(十五)

1.事务

在sql  servce 中 事务是一个工作单元 可能包含查询和修改数据以及修改数据定义等多个活动 也可以显示或隐式定义事务边界

显示定义事务 BEGIN TRAN 开始  如果要提交事务 使用 COMMIT TRAN   撤销事务(回滚) ROLLBACK TRAN  如下示例

BEGIN TRAN;
INSERT INTO Sales.Orders
      (custid, empid, orderdate, requireddate, shippeddate,
       shipperid, freight, shipname, shipaddress, shipcity,
       shippostalcode, shipcountry)
    VALUES
      (85, 5, ‘20090212‘, ‘20090301‘, ‘20090216‘,
       3, 32.38, N‘Ship to 85-B‘, N‘6789 rue de l‘‘Abbaye‘, N‘Reims‘,
       N‘10345‘, N‘France‘);
commit tran

一个简单的显示事务    也可以是隐式事务

GO
 INSERT INTO Sales.Orders
      (custid, empid, orderdate, requireddate, shippeddate,
       shipperid, freight, shipname, shipaddress, shipcity,
       shippostalcode, shipcountry)
    VALUES
      (85, 5, ‘20090212‘, ‘20090301‘, ‘20090216‘,
       3, 32.38, N‘Ship to 85-B‘, N‘6789 rue de l‘‘Abbaye‘, N‘Reims‘,
       N‘10345‘, N‘France‘);
GO

通过GO 在当前批执行完成时自动 提交事务   当然默认情况下SQL Server 将每个单独的语句作为一个事务 每个语句结束后SQL Server 会自动提交事务 也可通过设置会话来改变默认设置

SET IMPLICIT_TRANSACTIONS ON

设置为ON 后不需要指定BEGIN TRAN 语句开始事务 但必须以COMMIT TRAN或 TOLLBACK TRAN 标记结束

事务有4个属性-原子性,一致性,隔离性,持续性 首字母缩写为ACID

原子性(Atomicity): 事务是一个原子工作单元,事务中的所有修改要么提交,要么撤销。在事务提交指令记录到事务日志之前 如果系统出现了故障,重新启动时,SQL Server 会撤销所做的修改。  如果事务中出现错误 默认会自动回滚   也可以通过 @@TRANCOUNT 检测事务事务完成 或者说是 当前环境是否在事务中 如果在就返回 1 没有就是0

SELECT    @@TRANCOUNT

一致性(Consistency):指数据状态, 在隔离级别中  每个级别都要是 一致性级别 只有事务保持一致性级别才能访问。在约束中 也指 主外键 书屋会转换数据库的一致性状态到另一个一致性状态 保持一致性

隔离性(Isolation):隔离是一种控制访问数据的机制,确保事务所范围数据是在其所期望的一致性级别中的数据。在SQL Server 中支持两种不同的模式来处理隔离:基于锁的传统模式和行版本控制(新模式) 但是默认的是 锁模式  而且当前加锁也是共享锁 ,如果数据状态不一致 读取数据就会被阻止 直到状态一致 。而改成行版本控制模式 读取就不需要等待 也不会加共享锁 在不需要及时显示的数据时 这种模式是提高并发的处理方式。 具体实现要看使用的隔离级别。

持续性(Durability):数据修改在写入到数据库磁盘之前,总是先写入数据库的事务日志磁盘。提交后,指令记录在事务日志磁盘上,在尚未修改磁盘数据之前,事务是持续的,回滚也只是删除事务日志的所有修改记录。

下面是一个完整的事务示例:

BEGIN TRAN;

  DECLARE @neworderid AS INT;

BEGIN TRY
  INSERT INTO Sales.Orders
      (custid, empid, orderdate, requireddate, shippeddate,
       shipperid, freight, shipname, shipaddress, shipcity,
       shippostalcode, shipcountry)
    VALUES
      (85, 5, ‘20090212‘, ‘20090301‘, ‘20090216‘,
       3, 32.38, N‘Ship to 85-B‘, N‘6789 rue de l‘‘Abbaye‘, N‘Reims‘,
       N‘10345‘, N‘France‘);

  SET @neworderid = SCOPE_IDENTITY();

  SELECT @neworderid AS neworderid;

  INSERT INTO Sales.OrderDetails(orderid, productid, unitprice, qty, discount)
    VALUES(@neworderid, 11, 14.00, 12, 0.000),
          (@neworderid, 42, 9.80, 10, 0.000),
          (@neworderid, 72, 34.80, 5, 0.000);

COMMIT TRAN;
END TRY
BEGIN CATCH
ROLLBACK TRAN;
END CATCH

2.锁

锁是事务保护数据资源而获得的控制资源,防止其他事务的冲突或不兼容访问。

锁主要有两种锁模式 排他锁和共享锁

当你试图修改数据时 事务会请求数据资源的一个排他锁,它会一直到事务结束才会解除 期间任何其他事务请求都会被阻塞。对于单条语句事务 只要这条语句结束锁就会自动解除。对于多条语句事务 就只有当他完成所有语句执行并通过 COMMIT TRAN 或 ROLLBACK TRAN 命令时事务才会解除锁

排他锁:如果一个事务在修改行,直到事务完成,其他事务都不能修改相同的行。但是能不能读取相同行 取决于它的隔离级别。

共享锁:在读取事务加锁是默认加的是共享锁  SQL读取的默认隔离级别 READ COMMITTED  因为此隔离级别 会让事务请求读取资源时默认加上共享锁  多个事务可以同时拥有相同数据资源共享锁。 此模式下也会因为并发造成幻读 虽然在修改数据时,无法修改锁和持续时间,但可以通过改变隔离级别 在读取数据时控制锁定的处理方式。

其实锁的本质就是数据的隔离级别 在通过控制隔离级别也能达到加锁的效果 ,而且效果更好。

在SQL 中默认的隔离级别 READ COMMITTED SNAPSHOT 这种隔离依靠行版本控制,而不是锁,在此模式下 读取者不需要共享锁,因为不需要等待,依赖行版本控制技术提供隔离。   如果一个事务在READ COMMITTED隔离级别下 修改数据行 直到事务完成,另一个事务都不能读取相同行。这种并发控制称 “悲观式并发”  如果一个事务在READ COMMITTED SNAPSHOT隔离级别下 修改数据行  此时另一个事务读取相同行 会获得最后一次提交的可用状态。这种并发控制称 “乐观式并发” 在乐观并发中可以很好的解决修改和展示并发问题。

这种事务之间的并发处理已称为 锁兼容性

请求锁模式 请求排他锁 请求共享锁
请求排他锁
请求共享锁

交叉的否代表不兼容 请求锁模式会被拒绝 交叉是 表示兼容 请求锁模式会被接收

那么锁都可以锁些什么资源呢?

锁定的资源包括RID ,键,行,页,对象,表,数据库,范围,分配单元,堆,B树。

锁请求流程规则是什么呢?

例如:获取一个行上的排他锁  事务必须首先获取一个行所在页的意向排他锁和一个拥有该页对象的意向排他锁, 同样的 共享锁也是此步骤。

为什么要申请意向锁?

为了在更高级别有效的检测是否有锁不兼容请求,并防止授予这些锁请求,这就是为什么在排他锁请求相同数据行时被阻断的原因。

例如:一个事务持有行上锁,而另一个事务在该行所在的页或者表请求不兼容锁比如排他锁 有第一个事务的行上锁 有一个 表意向锁  这个时候请求就被拒绝了

但意向锁不会拒绝更低级别对象的锁请求

例如: 一个页上的意向锁不会阻断在该页的其他事务的排他锁  我们可以通过一个表来细致的了解这些锁的兼容性请求。

请求锁模式 请求排他锁 请求共享锁 请求意向排他锁 请求意向共享锁
请求排它锁
请求共享锁
请求意向排他锁
请求意向共享锁

通过这些锁得到我们最理想的并发处理 锁定所需要的内容,即受影响行数 。锁是需要内存资源和内部管理开销, 当需要锁时要考虑当前系统资源情况。

有一个情况不得不说  在行锁中超过5000个时 会自动升级锁 到表锁 然后每加1250个锁都会触发默认的锁升级

可以通过ALTER TABLE语句设置LOCK_ESCALATION 的表选项控制锁升级。 也可以禁用。 也可以更改升级方式 比如 分区级别( 把一个表物理的组织成小单元c成为分区)   锁到此语句结束了下次讲  如何优雅的排除并发导致的阻塞数据处理。

原文地址:https://www.cnblogs.com/yuanzijian-ruiec/p/9501200.html

时间: 2024-10-22 16:52:55

T-SQL:事务锁下的并发处理(十五)的相关文章

lduan server 2012 DHCP管理 下(三十五)

sql server中的锁 事务锁 更新锁 保持锁 共享锁 你知道吗?

锁定数据库的一个表 SELECT * FROM table WITH (HOLDLOCK) 注意: 锁定数据库的一个表的区别 SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除 SELECT * FROM table WITH (TABLOCKX) 其他事务不能读取表,更新和删除 SELECT 语句中"加锁选项"的功能说明 SQL Server提供了强大而完备的锁机制来帮助实现数据库系统的并发性和高性能.用户既能使用SQL Ser

Synchronized锁在Spring事务管理下,为啥还线程不安全?

大年初二,朋友问了我一个技术的问题(朋友实在是好学,佩服!) 开启10000个线程,每个线程给员工表的money字段[初始值是0]加1,没有使用悲观锁和乐观锁,但是在业务层方法上加了synchronized关键字,问题是代码执行完毕后数据库中的money 字段不是10000,而是小于10000 问题出在哪里? Service层代码:SQL代码(没有加悲观/乐观锁):用1000个线程跑代码:简单来说:多线程跑一个使用synchronized关键字修饰的方法,方法内操作的是数据库,按正常逻辑应该最终

SSM(十五) 乐观锁与悲观锁的实际应用

SSM(十五) 乐观锁与悲观锁的实际应用 前言 随着互联网的兴起,现在三高(高可用.高性能.高并发)项目是越来越流行. 本次来谈谈高并发.首先假设一个业务场景:数据库中有一条数据,需要获取到当前的值,在当前值的基础上+10,然后再更新回去.如果此时有两个线程同时并发处理,第一个线程拿到数据是10,+10=20更新回去.第二个线程原本是要在第一个线程的基础上再+20=40,结果由于并发访问取到更新前的数据为10,+20=30. 这就是典型的存在中间状态,导致数据不正确.来看以下的例子: 并发所带来

44. SQL -- 事务(2)

SETIMPLICIT_TRANSACTIONS ON --进入隐式事务模式 INSERTINTO orders VALUES('p07','2011-09-10 00:00:00.000','ded','EN','4000',convert(varbinary(256), pwdencrypt('passw0rd'))) SELECTtimes=5,* FROM orders --显示'p07'被插入 ROLLBACK go SELECTtimes=6,* FROM orders --因为执行

innodb事务锁

计算机程序锁 控制对共享资源进行并发访问 保护数据的完整性和一致性 lock  主要是事务,数据库逻辑内容,事务过程 latch/mutex 内存底层锁: 更新丢失 原因: B的更改还没有提交时,A已经再次修改了数据. 此时A使用原来的元数据作为基础更新后,B的更新便会丢失: 解决办法: 在修改数据上加写锁,当有锁时,A会等B更新提交完,才可以继续在B的基础上继续更新: 事务锁粒度 行锁: innodb ,oracle 页锁:sql server 表锁:Myisam ,memory 获取inno

oracle 事务 锁机制

本课内容属于Oracle高级课程范畴,内容略微偏向理论性,但是与数据库程序开发和管理.优化密切相关:另外本课的部分内容在前面章节已经涉及,请注意理论联系实际. 事务  事务(Transaction)从 通讯的角度看:是用户定义的数据库操作序列,这些操作要么全做.要么全不做,是不可分割的一个工作单元.事务控制语句称为TCL,一般包括Commit和Rollback. 事务不是程序,事务和程序分属两个概念.在RDBMS中,一个事务可以有一条SQL语句.一组SQL语句或者整个程序:一个应用程序又通常包含

SQL Server锁分区特性引发死锁解析

原文:SQL Server锁分区特性引发死锁解析 锁分区技术使得SQL Server可以更好地应对并发情形,但也有可能带来负面影响,这里通过实例为大家介绍,分析由于锁分区造成的死锁情形. 前段时间园友@JentleWang在我的博客锁分区提升并发,以及锁等待实例中问及锁分区的一些特性造成死锁的问题,这类死锁并不常见,我们在这里仔细分析下.不了解锁分区技术的朋友请先看下我的锁分区那篇实例. Code(执行测试脚本时请注意执行顺序,说明) 步骤1 创建测试数据 use tempdb go creat

lock(1)——创建及更新表过程中SQL SERVER锁资源分配情况

锁应该说是由关系型数据库ACID(Atomicity,Consistency,Isolation,Durability)特性而引出的. 以下将测试在创建及更新表过程中SQL Server锁资源分配情况 获取当前会话的事务隔离级别:DBCC USEROPTIONS 测试环境:SQL SERVER 2008 R2 read committed隔离级别下 创建表 当我们只是打开一个SSMS查询窗口,选择数据库为master和tempdb时,没有任何锁产生,当我选择其他数据库,sql server就会在