SQL Server 中的 ACID 属性
SQL Server 中的事务是什么?
SQL Server 中的事务是一组被视为一个单元的 SQL 语句,它们按照“做所有事或不做任何事”的原则执行,成功的事务必须通过 ACID 测试。
事务的 ACID 属性是什么?
首字母缩写词 ACID 是指事务的四个关键属性
- 原子性: Atomicity
- 一致性: Consistency
- 隔离性: Isolation
- 持久性: Durability
为了理解这一点,我们将使用以下两个表测试。
Product (产品表)
| ProductID | Name | Price | Quantity |
|---|---|---|---|
| 101 | Laptop | 15000 | 100 |
| 102 | Desktop | 20000 | 150 |
| 104 | Mobile | 3000 | 200 |
| 105 | Tablet | 4000 | 250 |
ProductSales (产品销售表)
| ProductSalesID | ProductID | QuantitySold |
|---|---|---|
| 1 | 101 | 10 |
| 2 | 102 | 15 |
| 3 | 104 | 30 |
| 4 | 105 | 35 |
请使用以下 SQL 脚本创建并使用示例数据填充 Product 和 ProductSales 表。
IF OBJECT_ID('dbo.Product','U') IS NOT NULL
DROP TABLE dbo.Product
IF OBJECT_ID('dbo.ProductSales','U') IS NOT NULL
DROP TABLE dbo.ProductSales
GO
CREATE TABLE Product
(
ProductID INT PRIMARY KEY,
Name VARCHAR(40),
Price INT,
Quantity INT
)
GO
INSERT INTO Product VALUES(101, 'Laptop', 15000, 100)
INSERT INTO Product VALUES(102, 'Desktop', 20000, 150)
INSERT INTO Product VALUES(103, 'Mobile', 3000, 200)
INSERT INTO Product VALUES(104, 'Tablet', 4000, 250)
GO
CREATE TABLE ProductSales
(
ProductSalesId INT PRIMARY KEY,
ProductId INT,
QuantitySold INT
)
GO
INSERT INTO ProductSales VALUES(1, 101, 10)
INSERT INTO ProductSales VALUES(2, 102, 15)
INSERT INTO ProductSales VALUES(3, 103, 30)
INSERT INTO ProductSales VALUES(4, 104, 35)
GO
SQL Server 中事务的原子性
SQL Server 中事务的原子性确保事务中的所有 DML 语句(即插入、更新、删除)成功完成或全部回滚。例如,在以下 spSellProduct 存储过程中,UPDATE 和 INSERT 语句都应该成功。如果 UPDATE 语句成功而 INSERT 语句失败,数据库应该通过回滚来撤消 UPDATE 语句所做的更改。
IF OBJECT_ID('spSellProduct','P') IS NOT NULL
DROP PROCEDURE spSellProduct
GO
CREATE PROCEDURE spSellProduct
@ProductID INT,
@QuantityToSell INT
AS
BEGIN
-- 首先我们需要检查待销售产品的可用库存
DECLARE @StockAvailable INT
SELECT @StockAvailable = Quantity FROM Product WHERE ProductId = @ProductId
--如果可用库存小于要销售的数量,抛出错误
IF(@StockAvailable < @QuantityToSell)
BEGIN
Raiserror('可用库存不足',16,1)
END
-- 如果可用库存充足
ELSE
BEGIN
BEGIN TRY
-- 我们需要开启一个事务
BEGIN TRANSACTION
-- 首先做减库存操作
UPDATE Product SET Quantity = (Quantity - @QuantityToSell) WHERE ProductID = @ProductID
-- 计算当前最大的产品销售ID,即 MaxProductSalesId
DECLARE @MaxProductSalesId INT
SELECT @MaxProductSalesId = CASE
WHEN MAX(ProductSalesId) IS NULL THEN 0
ELSE MAX(ProductSalesId)
END
FROM ProductSales
-- 把 @MaxProductSalesId 加一, 所以我们会避免主键冲突
--(解释下,建表的时候,没有设置主键自增,所以需要人工处理自增)
Set @MaxProductSalesId = @MaxProductSalesId + 1
-- 把销售的产品数量记录到ProductSales表中
INSERT INTO ProductSales VALUES (@MaxProductSalesId, @ProductId, @QuantityToSell)
-- 最后,提交事务
COMMIT TRANSACTION
END TRY
BEGIN CATCH
-- 如果发生了异常,回滚事务
ROLLBACK TRANSACTION
END CATCH
End
END
SQL Server 中事务的一致性
SQL Server 中事务的一致性确保数据库数据在事务开始之前处于一致状态,并且在事务完成后也使数据保持一致状态。如果事务违反规则,则应回滚。例如,如果可用库存从 Product 表中减少,那么 ProductSales 表中必须有一个相关条目。
在我们的示例中,假设事务更新了 product 表中的可用数量,突然出现系统故障(就在插入 ProductSales 表之前或中间)。在这种情况下系统会回滚更新,否则我们无法追踪库存信息。
SQL Server 中事务的隔离性
SQL Server 中事务的隔离性确保事务的中间状态对其他事务不可见。一个事务所做的数据修改必须与所有其他事务所做的数据修改隔离。大多数数据库使用锁定来维护事务隔离。
为了理解事务的隔离性,我们将使用两个独立的 SQL Server 事务。从第一个事务开始,我们启动了事务并更新了 Product 表中的记录,但我们还没有提交或回滚事务。在第二个事务中,我们使用 select 语句来选择 Product 表中存在的记录,如下所示。
在sqlserver management studio 或 Navicat 中新建两个独立的查询窗口
首先在第1个窗口运行以下事务,更新库存(注意事务没有提交或回滚,回滚语句被注释了)
begin tran
update dbo.Product set Quantity = 150 where ProductID = 101
--rollback tran
然后在第2个窗口运行以下语句,查询所有产品
select * from dbo.Product where ProductID = 101
你会发现,第2个窗口中的查询语句被阻塞了(一直处于运行状态,没有返回数据)
解决阻塞: 切换到第1个窗口, (按下鼠标左键拖动选择
rollback tran,注意不包含注释 -- ),
然后单独执行这个语句, 在 sqlserver management studio 直接点击执行就行, 在 Navicat 中,点击运行按钮右边的下拉箭头,点击运行已选择的,好了,再切换到第2个窗口,你会发现结果出来了
阻塞的原因: SqlServer默认的事务隔离级别是 Read Committed,
在上述的Update语句执行时会在对应的数据行上加一个 排它锁(X), 直到事务提交或者回滚才会释放,这保证了在此期间,其他任何事务都不能操作此行数据(查询也不行),因为排它锁(也叫独占锁),和其他类型的锁都是不兼容的,这保证了其他事务看不到另一个事务的中间状态,即避免了脏读
SQL Server 中事务的持久性
SQL Server 中事务的持久性确保一旦事务成功完成,它对数据库所做的更改将是永久性的。即使出现系统故障或电源故障或任何异常变化,它也应该保护已提交的数据。
注意:首字母缩写词 ACID 由 Andreas Reuter 和 Theo Härder 在 1983 年创建,然而,Jim Gray 在 1970 年代后期已经定义了这些属性。大多数流行的数据库,如 SQL Server、Oracle、MySQL、Postgre SQL 默认都遵循 ACID 属性。
SQL Server 中的 ACID 属性的更多相关文章
- SQL SERVER中的扩展属性
以前在SQL SERVER建表时,总看到扩展属性,但一直未使用过.今天研究下: 增加扩展属性: 语法: sp_addextendedproperty [ @name = ] { 'property_n ...
- 浅谈SQL Server中的事务日志(三)----在简单恢复模式下日志的角色
简介 在简单恢复模式下,日志文件的作用仅仅是保证了SQL Server事务的ACID属性.并不承担具体的恢复数据的角色.正如”简单”这个词的字面意思一样,数据的备份和恢复仅仅是依赖于手动备份和恢复.在 ...
- SQL Server中的事物
1.事务的四个属性 原子性Atomicity,一致性Consistency,隔离性Isolation,持久性Durability ,即ACID特性. 原子性:事务必须是一个完整工作的单元,要么全部执行 ...
- SQL Server中事务、锁定和阻塞
事务是什么 在SQL Server中事务是构成一个工作逻辑单元的一系列任务,也就说多个任务放在一起执行,这些任务要么全部执行成功,要么全部执行失败. 通过事务我们可以保证数据的完整性,例如:用户A给用 ...
- 【转】T-SQL查询进阶—理解SQL Server中的锁
简介 在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查 ...
- SQL Server中的锁的简单学习
简介 在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查询的 ...
- T-SQL查询进阶—理解SQL Server中的锁
在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查询的.这些 ...
- T-SQL查询进阶--SQL Server中的事务与锁
为什么需要锁 在任何多用户的数据库中,必须有一套用于数据修改的一致的规则,当两个不同的进程试图同时修改同一份数据时,数据库管理系统(DBMS)负责解决它们之间潜在的冲突.任何关系数据库必须支持事务的A ...
- 浅谈SQL Server中的事务日志(一)----事务日志的物理和逻辑构架
简介 SQL Server中的事务日志无疑是SQL Server中最重要的部分之一.因为SQL SERVER利用事务日志来确保持久性(Durability)和事务回滚(Rollback).从而还部分确 ...
随机推荐
- redis的zset数据结构:跳表
点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. 广州这边封闭式管理好久了,今天终于周末可以出去溜溜了 什么是zset z ...
- CoreWCF 1.0.0 发布,微软正式支持WCF
2022年4月28日,我们达到了一个重要的里程碑,并发布了CoreWCF的1.0.0版本.对Matt Connew (微软WCF团队成员)来说,这是5年前即 2017年1月开始的漫长旅程的结束.Mat ...
- [题解] 春荔(cut) | 贪心
题目大意 有一个长度为 \(n\) 的非负整数序列 \(a_i\),每次可以选择一段区间减去 \(1\),要求选择的区间长度 \(\in[l,r]\),问最少多少次把每个位置减成 \(0\). 不保证 ...
- 一个登录点两个逻辑漏洞-edusrc
最近呢, 也是基础漏洞学的差不多了, 就在edusrc上面实战, 刚开始搞一些信息泄漏啥的, 提交了十几个, 结果就他娘的通过了一个. 咱也就不碰信息泄漏了, 没得意思. 关于这个学校测试时也是有坑的 ...
- Web安全学习笔记 SQL注入下
Web安全学习笔记 SQL注入下 繁枝插云欣 --ICML8 SQL注入小技巧 CheatSheet 预编译 参考文章 一点心得 一.SQL注入小技巧 1. 宽字节注入 一般程序员用gbk编码做开发的 ...
- spring4+hibernate4 整合
1.web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version=" ...
- DOM操作标签,事件绑定,jQuery框架
DOM操作标签 ''' 在起变量名的时候 如果该变量指向的是一个标签 那么建议使用 xxxEle eg:aEle\pEle\divEle\spanEle ''' 基本使用 动态创建一个标签 var 变 ...
- 讨论两种Redis中Token的存储方式
摘要:本文讨论一个问题:存储token时,token与对应用户id谁来作为key? 问题起源问题起源于要给公司的后台管理系统添加权限管理,选用的是开源框架shiro,而原本系统上是采用token做了登 ...
- 2020级C++实验课-期末机考模拟考题解
做这个题解的理由很简单,有很多同学想写但是不会写,凑巧我写了,所以搞个题解. 顺序就是题单里的顺序(界面左上角菜单切换文章,右上角目录方便查看) 1:黑马白马 题意: 随机得到一个数字,如果是偶数,则 ...
- 安装Speedtest到Python
Speedtest模块可以测试主机的网络带宽大小. 运行环境 系统版本:CentOS Linux release 7.3.1611 (Core) 软件版本:无 硬件要求:无 安装过程 1.安装Spee ...