MSSQL-并发控制-1-Transaction
1 事务类别
1.1 显式事务
1.1.1 COMMIT
1 begin tran yu1 2 select @@TRANCOUNT 3 begin tran yu2 4 insert into tbxin(name,age) select \'第2层tran\',100; 5 select @@TRANCOUNT 6 7 begin tran yu3 8 insert into tbxin(name,age) select \'第3层tran\',100; 9 select @@TRANCOUNT 10 commit tran --等同于 commit tran anyname 11 select @@TRANCOUNT 12 commit tran --等同于 commit tran anyname 13 select @@TRANCOUNT 14 commit tran --等同于 commit tran anyname 15 select @@TRANCOUNT
1.1.2 ROLLBACK
- 第一个,回滚当前所有未结束事务
- rollback = rollback tran = rollback transaction = rollback work
- 无论嵌套了多少事务,@@trancount为多少,执行 rollback则直接回滚所有嵌套事务,设置@@trancount为0
- 常见错误案例:EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。
- 第二个,回滚到某个保存点的位置
- rollback tran savepoint_name
- 不影响@@trancount计算,回滚到 某个 save tran savepoint_name的位置
1 CREATE PROC p_count 2 AS 3 begin transaction 4 insert into tbxin(name,age) select \'第一层tran\',200; 5 rollback transaction 6 GO 7 8 BEGIN TRAN 9 EXEC p_count 10 select @@TRANCOUNT 11 12 消息 266,级别 16,状态 2,过程 p_count,第 0 行 13 EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。
1.1.3 SAVE TRANSACTION
- save transaction [savepoint_name] 提供 用户 在事务内设置保存点或标记,所以 save transaction 只能在事务内部执行;
- save transaction [savepoint_nmae] 不影响 @@trancount 计数;
- 注意 save transaction [savepoint_name] 只有对应 rollback transaction [savepoint_name],并没有对应 commit transaction [savepoint_name],强调下:对应的rollback transaction [savepoint_name] 是有带 保存点名字的,如果没有带名字,则会回滚整个最外部的事务;
- save transaction 对应的 rollback transaction [savepoint_name]并不需要一一对应,可以多个save tran 对应0到多个rollback tran;
- 事务内,可以有多个 save transaction [savepoint_name],可使用 rollback transaction [savepoint_name] 回滚到任意一个保存点;
- 支持savepoint_name重复命名,但是不建议。在事务中允许有重复的保存点名称,但指定保存点名称的 ROLLBACK TRANSACTION savepoint_name 语句只将事务回滚到使用该名称的最近的 SAVE TRANSACTION savepoint_name;
- 在使用 BEGIN DISTRIBUTED TRANSACTION 显式启动或从本地事务升级的分布式事务中,不支持 SAVE TRANSACTION。
1 begin tran 2 select @@TRANCOUNT 3 4 save tran yu1 5 insert into tbxin(name,age) select \'第1层save\',100; 6 select @@TRANCOUNT 7 8 save tran yu2 9 insert into tbxin(name,age) select \'第2层save\',100; 10 select @@TRANCOUNT 11 12 save tran yu3 13 insert into tbxin(name,age) select \'第3层save\',100; 14 select @@TRANCOUNT 15 16 save tran yu4 17 insert into tbxin(name,age) select \'第4层save\',100; 18 select @@TRANCOUNT 19 20 rollback tran yu3 21 select @@TRANCOUNT 22 23 commit tran yu2 24 select @@TRANCOUNT 25 26 rollback tran
1.1.4 XACT_ABORT
1.2 隐式事务
- ALTER TABLE
- CREATE
- DROP
- OPEN
- FETCH
- GRANT
- REVOKE
- SELECT
- UPDATE
- DELETE
- INSERT
- TRUNCATE TABLE
1.3 自动提交事务
--例子 INSERT INTO ...
--数据库默认的事务管理模式,在没有被显式事务及隐式事务覆盖的情况下,自动在每个Tsql完成时,提交或者回滚
1.4 手动提交事务
--例子 BEGIN TRAN INSERT INTO ... COMMIT / ROLLBACK --数据库默认的事务管理模式,显式事务在完成时,手动指定SQL,说明提交或者回滚。
1.5 批范围事务
1.6 分布式事务
BEGIN DISTRIBUTED TRANSACTION SELECT ... FROM Stock... WHERE ... UPDATE Stock ... INSERT INTO ORDERS ... COMMIT
在SQL SERVER中,如果没有配置服务器的DTC服务,使用分布式事务的时候,会报错如下:
(1 行受影响) 消息 8501,级别 16,状态 3,第 4 行 服务器 \'XINYSU\MSSQL\' 上的 MSDTC 不可用。 (1 行受影响) 链接服务器"test_xinysu"的 OLE DB 访问接口 "SQLNCLI11" 返回了消息 "该伙伴事务管理器已经禁止了它对远程/网络事务的支持。"。 消息 7391,级别 16,状态 2,第 4 行 无法执行该操作,因为链接服务器 "test_xinysu" 的 OLE DB 访问接口 "SQLNCLI11" 无法启动分布式事务。
如果实例需要支持分布式事务,则需要在双方的服务器其上开启DTC服务,运行XA事务。这里注意一点,如果链接服务器是MySQL数据库,因为mysql的odbc不支持 XA事务,所以,会报错 无法启动分布式事务。官网解释如下:
1 INSERT INTO mssql_xinysu.dbname.dbo.tbid(id) select id from sys.sysobjects 2 或者 3 INSERT INTO openquery([mysql_xinysu],\'select id from tbid\') select id from sys.sysobjects
假设 select id from sys.sysobjects 的结果有2k行,则在 第一个SQL的 ODBC 是这么处理的:
- 分为2000个INSERT 语句
- (@Param000004 int)INSERT [dbname].[dbo].[tbid]([id]) VALUES(@Param000004)
- 一条一条INSERT
- 分为2000个INSERT 语句
- INSERT INTO tbid ([id]) VALUES(单个的ID值)
- 一条条INSERT
2 ACID特性
2.1 Atomicity
2.2 Consistency
2.3 Isolation
2.4 Durability
3 协议
3.1 2PL
BEGIN LOCK A READ A A:A+100 WRITE A UNLOCK A LOCK B READ B UNLOCK B COMMIT
两阶段锁还有几种特殊情况:conservative(保守)、strict(严格)、strong strict(强严格),这三种类型在加锁和释放锁的处理有些不一样。
- conservative
- 在事务开始的时候,获取需要的记录的锁,避免在操作期间逐个申请锁可能造成的锁等待,conservative 2PL 可以避免死锁
- strict
- 仅在事务结束的时候(commit or rollback),才释放所有 write lock,read lock 则正常释放
- strong strict
- 仅在事务结束的时候(commit or rollback),才释放所有锁,包括write lock 跟 read lock 都是结束后才释放。
3.2 XA
3.2.1 CAP理论
- Consitency
- 一致性,在分布式存储系统中,对于每一次的读操作,对于读到的数据,要么都是最新的,要么则返回一个错误
- 这里的CAP的C跟ACID的C虽然是一个单词,但是含义不一样哦,记得区分
- 在关系型数据库里边,通常优先考虑到是一致性
- Availability
- 可用性,保证每次请求都正常,但不要求返回的结果是最新的数据
- Partition tolerance
- 分区容错性,当各个分区之间因为网络发生消息丢失或者延迟是,分布式存储系统仍能正常运行。
- 则是在操作 涉及多个服务器的事务 过程中,
3.2.2 2PC
- Prepare
- 事务协调器coordinator 对 涉及到的节点 发起 操作申请;
- 各个节点获取到 操作后,直接在 数据库中执行,并存放相关的日志到redo / undo log中,注意注意,这里仅是操作,并没有提交或者回滚该操作;
- 各节点将处理日志写入磁盘;
- 返回信息给coordinnator
- 如果节点可以正常执行,则返回 Ready 通知 coordinator;
- 如果节点不可以正常执行,则该节点本地回滚该操作,并返回 Not Ready 通知 coordinator
- Comiit/Rollback
- coordinator 根据各个节点 的反馈信息,来决定 该事务操作的结果
- coordinator将 操作结果记录到日志中
- 反馈操作结果给各个节点
- 如果出现一个或者一个以上的节点 反馈回来 Not Ready的通知,则coordinator会通知 正常执行操作的节点 回滚事务
- 如果没有出现 Not Ready 的反馈,则coordinator会通知所有节点 COMMIT 操作。
- 事务协调器宕机
- 这里需要引入一个新角色:coordinator watchdog,事务协调器看门狗
- 无论是coordinator 还是分布式系统的各个节点,在操作过程中,都会记录当前操作的状态日志。当出现异常或者恢复时,可以通过日志来判断当前的情况。
- 当 coordinator 发起提议后宕机,而此时各个节点开始操作,然后反馈给 coordinator,但是 迟迟没有接收到 coordinator 的回应,那么各个节点的操作就无法回滚或者提交,处于堵塞情况。而 coordinator watchdog 则可以解决这个堵塞现象,当coordinator宕机一定时间后,看门狗会自动 担任 coordinator 的工作,接收各个节点的 反馈情况,然后再根据反馈结果传递 COMMIT/ROLLBAK给各个节点。
- 节点宕机
- prepare阶段宕机,则coordinator接收到事务后发送给各个节点需要做的 操作时,节点发生宕机,这个时候,则该节点无法返回 Ready 的消息,coordinator则默认接受该节点发出的 abort 信息,coordinator通知其他各个节点 Rollback 操作;
- Comiit/Rollback阶段宕机,由于各个节点及coordinator都有日志记录,coordinator会记录这个事务是会提交还是回滚,当 节点宕机后,其他节点根据coordinator的通知执行ROLLBACK或者COMMIT,而宕机节点本地会记录该事务操作未执行提交或者回滚,节点恢复后,会从 coordinator 日志中读取日志,重新处理该操作。