sql server 事务

In this article, we will explore the process of rollback an explicit SQL Server transaction. We will also explore the difference between explicit and implicit transactions.

在本文中,我们将探讨回滚显式SQL Server事务的过程。 我们还将探讨显式和隐式事务之间的区别。

介绍 (Introduction)

A transaction in SQL Server is a single unit of work in a database. We perform many transactions daily. In the real world, consider a banking transaction. Suppose you withdraw money from your bank account, you expect that it should get successful once you get money in your account. In case, you try to withdraw money, but after you are done with all formalities, due to a technical error, the amount got deducted from your account, but it did not reach out to you. In this case, the transaction should be rolled back, and the amount should reappear in your account.

SQL Server中的事务是数据库中的单个工作单元。 我们每天执行许多交易。 在现实世界中,考虑银行交易。 假设您从银行帐户中提款,您希望一旦您的帐户中有钱,该笔款项就会成功。 以防万一,您尝试取款,但是在完成所有手续后,由于技术错误,该笔款项从您的帐户中扣除,但没有到账。 在这种情况下,交易应回滚,并且金额应重新出现在您的帐户中。

Similar to the above scenario, consider you are executing a script on the production database that updates data in the existing table. Your developer missed putting a WHERE clause and it might mess your data. In this article, we try to find answers to the following questions.

与上述情况类似,请考虑在生产数据库上执行脚本,该脚本更新现有表中的数据。 您的开发人员错过了放置WHERE子句的操作,这可能会弄乱您的数据。 在本文中,我们尝试找到以下问题的答案。

  • Do we have an option to rollback changes in SQL Server? 我们是否可以选择回滚SQL Server中的更改?
  • What precautions can we take before executing queries in a production environment? 在生产环境中执行查询之前,我们可以采取哪些预防措施?

Before we move further, you can refer to SQL Server Transaction Overview article, and go through ACID properties and transaction states.

在继续进行操作之前,您可以参考“ SQL Server事务概述”一文,并遍历ACID属性和事务状态。

隐式和显式SQL Server事务 (Implicit and Explicit SQL Server transaction)

隐式SQL Server事务: (Implicit SQL Server transaction:)

SQL Server default behavior is Implicit transaction. It provides auto commits functionality, so you do not require to issue a COMMIT TRAN statement. It is a convenient solution, and we can avoid open transaction issues such as session holding resources, but it is not committed.

SQL Server的默认行为是隐式事务。 它提供了自动提交功能,因此您不需要发出COMMIT TRAN语句。 这是一种方便的解决方案,我们可以避免出现开放式事务问题,例如会话持有资源,但是它不是提交的。

To view SQL Server default property, connect to a SQL instance in SSMS. Go to Tools-> Options -> search for keyword Query.

若要查看SQL Server的默认属性,请连接到SSMS中SQL实例。 转到工具->选项->搜索关键字Query

In the filtered menu, click on ANSI, and you see option SET IMPLICIT_TRANSACTION mode is off.

在过滤的菜单中,单击ANSI,然后看到选项SET IMPLICIT_TRANSACTION模式已关闭。

For example, we execute the below update statement and it auto commits data without asking for COMMIT or ROLLBACK statement.

例如,我们执行下面的update语句,它自动提交数据而无需询问COMMIT或ROLLBACK语句。

UPDATE [SQLShack].[dbo].[SalesData]SET UnitPrice = 15.9
WHERE CustomerID = 10776AND subtotal = 200;

Once SQL Server commits a transaction, you cannot run the ROLLBACK statement. Each rollback statement should have an association with the BEGIN Transaction statement.

一旦SQL Server提交了事务,就不能运行ROLLBACK语句。 每个回滚语句应与BEGIN事务语句关联。

Let’s go back to the SSMS option and in a new query window, use the option SET IMPLICIT_TRANSACTION ON before starting a transaction.

让我们回到SSMS选项,并在新的查询窗口中,在开始事务之前使用选项SET IMPLICIT_TRANSACTION ON。

SET IMPLICIT_TRANSACTIONS ON
UPDATE [SQLShack].[dbo].[SalesData]SET UnitPrice = 15.9
WHERE CustomerID = 10776AND subtotal = 200;

It commits a single row, and you get the output – 1 row affected. For my demo, this query uses the SPID 55.

它只提交一行,您将得到输出-受影响的一行。 对于我的演示,此查询使用SPID 55。

Now, check the locks held by session 55 using the sp_whoisactive stored procedure.

现在,使用sp_whoisactive存储过程检查会话55持有的锁。

sp_whoisactive @get_locks=1

In the output above, we see one open transaction for the SPID 55. Click on the hyperlink for locks, and you get currently held locks in an XML format.

在上面的输出中,我们看到一个针对SPID 55的未结事务。单击锁的超链接,您将获得XML格式的当前持有的锁。

Now, open a new query window and try to select the same records that we updated.

现在,打开一个新的查询窗口,并尝试选择我们更新的相同记录。

select * from  [SQLShack].[dbo].[SalesData]
where
CustomerID = 10776AND subtotal = 200;

We did not commit update transactions yet, so the SELECT statement faces blocking.

我们尚未提交更新事务,因此SELECT语句面临阻塞。

Go back to the update session and commit the records to clear blocking. If we specify SET IMPLICIT_TRANSACTIONS ON in a transaction, SQL Server automatically starts a transaction for you and waits for your instructions to commit or rollback data.

返回到更新会话,并提交记录以清除阻止。 如果我们在事务中指定SET IMPLICIT_TRANSACTIONS ON,则SQL Server会自动为您启动事务,并等待您的指令提交或回滚数据。

You can check the status of an implicit transaction for a query session, using the below query.

您可以使用以下查询来检查查询会话的隐式事务的状态。

DECLARE @IMPLICIT_TRANSACTIONS VARCHAR(3) = 'OFF';
IF ( (2 & @@OPTIONS) = 2 ) SET @IMPLICIT_TRANSACTIONS = 'ON';
SELECT @IMPLICIT_TRANSACTIONS AS IMPLICIT_TRANSACTIONS;

显式SQL Server事务 (Explicit SQL Server transaction)

In this mode, each code block starts with a BEGIN TRANSACTION statement, and it requires an explicit COMMIT or ROLLBACK statement. It gives the flexibility to decide whether you want to save changes performed by query or not.

在这种模式下,每个代码块均以BEGIN TRANSACTION语句开头,并且需要显式的COMMIT或ROLLBACK语句。 它使您可以灵活地决定是否要保存通过查询执行的更改。

  • BEGIN TRANSACTION – It indicates the starting point of a transaction
  • 开始交易 –它指示交易的起点
  • ROLLBACK TRANSACTION -It starts the rollback process and reverts any changes performed by the transaction. It might take a long time depending upon the changes performed earlier ROLLBACK TRANSACTION-它开始回滚过程并还原由事务执行的所有更改。 根据之前执行的更改,可能需要很长时间
  • COMMIT TRANSACTION -It commits the changes in the database. Once we issued a commit transaction, it cannot be rolled back COMMIT TRANSACTION-提交数据库中的更改。 一旦我们发出了提交事务,就无法回滚

We can achieve the transaction control using the explicit transactions similar to specifying SET IMPLICIT_TRANSACTIONS ON.

我们可以使用类似于指定SET IMPLICIT_TRANSACTIONS ON的显式事务来实现事务控制。

In the below query, we specify BEGIN TRAN, in the beginning, to specify an explicit transaction and roll back the updates.

在下面的查询中,我们首先指定BEGIN TRAN以指定一个显式事务并回滚更新。

BEGIN TRAN
UPDATE [SQLShack].[dbo].[SalesData]SET UnitPrice = 15.9
WHERE CustomerID = 10776AND subtotal = 200;
ROLLBACK TRAN

We can define a name for the transaction as well as using explicit transactions. It helps us to commit or rollback a specific transaction when we have multiple transactions in a query.

我们可以为事务定义名称,也可以使用显式事务。 当查询中有多个事务时,它有助于我们提交或回退特定事务。

In the below query, we have two transactions Demotran1 and Demotran2. We rollback the first transaction but commits the second transaction.

在下面的查询中,我们有两个事务Demotran1和Demotran2。 我们回滚第一笔交易,但提交第二笔交易。

DECLARE @TransactionName VARCHAR(20)= 'Demotran1';
BEGIN TRAN @TransactionName;
INSERT INTO Demo
VALUES(1), (2);
ROLLBACK TRAN @TransactionName;
SELECT *
FROM demo;
DECLARE @TransactionName1 VARCHAR(20)= 'Demotran2';
BEGIN TRAN @TransactionName;
INSERT INTO Demo
VALUES(1), (2);
COMMIT TRAN @TransactionName1;
SELECT *
FROM demo;

Let’s explore a few useful examples for the explicit transactions.

让我们探索一些显式事务的有用示例。

IDENTITY列行为用于显式回滚 (IDENTITY columns behavior for explicit rollback)

Suppose you started an explicit transaction that inserts a record in the demo table. Later, we want to rollback. This table has an identity column as well.

假设您启动了一个显式事务,该事务将一条记录插入到演示表中。 稍后,我们要回滚。 该表还具有一个标识列。

What would be the impact on identity column if we roll back a SQL Server transaction? Let’s explore it using an example. First, create the demo table with two columns [id] and [EmpName]. ID is an identity column for this table.

如果我们回滚SQL Server事务,将对Identity列产生什么影响? 让我们通过一个例子来探索它。 首先,使用两列[id]和[EmpName]创建演示表。 ID是此表的标识列。

CREATE TABLE demo(id INT IDENTITY(1, 1),EmpName varchar(50));

In the below query, we do the following tasks.

在下面的查询中,我们执行以下任务。

  • Check current identity value using the IDENT_CURRENT() function 使用IDENT_CURRENT()函数检查当前身份值
  • It begins an explicit transaction using the BEGIN TRANSACTION statement 它使用BEGIN TRANSACTION语句开始显式事务
  • Inserts few records 插入几条记录
  • Check the identity after inserts 插入后检查身份
SELECT IDENT_CURRENT('demo') as [IdentityBeforeInsert];
BEGIN TRANSACTION
INSERT INTO dbo.demo ( EmpName ) VALUES('Raj');
INSERT INTO dbo.demo ( EmpName ) VALUES('Sonu');
INSERT INTO dbo.demo ( EmpName ) VALUES('Hari');
INSERT INTO dbo.demo ( EmpName ) VALUES('Cheena');
SELECT IDENT_CURRENT('demo') as [IdentityAfterInsert];

We can see the first record in the demo table gets identity value 1, and after inserts, the identity value is 4.

我们可以看到演示表中的第一条记录的标识值为1,插入后的标识值为4。

Let’s rollback this transaction and check the identity value. Once the rollback completes, SQL Server removes the data rows, but still, identity value is set to 4. If we insert a new row in the demo table, it gets the next identity value 5.

让我们回滚此事务并检查标识值。 回滚完成后,SQL Server删除数据行,但身份值仍设置为4。如果在演示表中插入新行,它将获得下一个身份值5。

This demonstration shows that an explicit transaction rollbacks a transaction, but it cannot revert the identity value. It is the reason we see gaps in the identity value in a SQL table. Its value depends on the last identity value for that table. You can use the RESEED function to reset identity values in a table.

此演示表明显式事务回滚事务,但是它不能还原标识值。 这就是我们在SQL表中看到标识值差距的原因。 它的值取决于该表的最后一个标识值。 您可以使用RESEED函数来重置表中的标识值。

SQL表变量和显式SQL Server事务 (SQL Table variables and explicit SQL Server transaction)

We use table variables as a particular table data type that you can use to perform intermediate tables similar to temporary tables. You can refer to An overview of the SQL table variable article, to know more about it.

我们将表变量用作特定的表数据类型,可用于执行类似于临时表的中间表。 您可以参考SQL表变量文章概述 ,以了解更多信息。

In the below example, we do the following tasks.

在下面的示例中,我们执行以下任务。

  • Declare a table variable @Demo 声明一个表变量@Demo
  • Insert a record into it 将记录插入其中
  • Starts an explicit transaction using BEGIN TRANSACTION 使用BEGIN TRANSACTION启动显式事务
  • Update the record in the table variable 更新表变量中的记录
  • Rollback transaction 回滚交易
  • Check the value of the record in the table variable. 检查表变量中记录的值。
DECLARE @Demo TABLE ( id INT );
INSERT @Demo ( id ) VALUES( 11 ); SELECT id AS 'Before BEGIN TRAN statement' FROM @Demo;
BEGIN TRANSACTION
UPDATE @Demo SET id = 20; SELECT id AS 'After BEGIN TRAN statement' FROM @Demo;
ROLLBACK TRAN SELECT id AS 'After explicit ROLLBACK TRAN' FROM @Demo;

In the above screenshot, we can note that SQL Server does not rollback value held in a table variable using the explicit transaction. You need to consider this before using the table variable and rollback using an explicit transaction.

在上面的屏幕快照中,我们可以注意到SQL Server不会使用显式事务回滚保存在表变量中的值。 在使用表变量和使用显式事务回滚之前,您需要考虑这一点。

@@ Trancount跟踪打开SQL Server事务 (@@Trancount to keep track of open SQL Server transaction)

We can use the global variable @@trancount to track the open transactions.

我们可以使用全局变量@@ trancount来跟踪未结交易。

  • A BEGIN TRANSACTION increments the value for @@Trancount by 1 BEGIN TRANSACTION将@@ Trancount的值加1
  • A COMMIT TRANSACTION decrements the value for @@Trancount by 1 COMMIT TRANSACTION将@@ Trancount的值减1
  • @@Trancount value zero shows no outstanding transactions in the current session @@交易值零表示当前会话中没有未完成的交易
  • A non-zero value for @@Trancount shows that data from the first BEGIN TRANSACTION is not committed yet @@ Trancount的非零值表示来自第一个BEGIN TRANSACTION的数据尚未提交
  • A ROLLBACK TRANSACTION command sets the value for @@Trancount to zero ROLLBACK TRANSACTION命令将@@ Trancount的值设置为零

In the below query, you can see how the value changes for the @@Trancount as per BEGIN TRANSACTION and COMMIT TRANSACTION statements for explicit SQL Server transactions.

在下面的查询中,您可以看到对于@@ Trancount的值如何根据显式SQL Server事务的BEGIN TRANSACTION和COMMIT TRANSACTION语句进行更改。

SELECT @@TRANCOUNT AS [First trancount];
BEGIN TRANSACTION;
SELECT @@TRANCOUNT AS [Second trancount]; INSERT INTO demo(EmpName) VALUES('Hari');
INSERT INTO demo(EmpName) VALUES('Cheena'); COMMIT TRANSACTION;SELECT @@TRANCOUNT AS [Third trancount];

Let’s look at another example. Execute the following query and note the value of @@trancount.

让我们看另一个例子。 执行以下查询,并记下@@ trancount的值。

Let's look at another example. Execute the following query and note the value of @@trancount.
SELECT @@TRANCOUNT AS [First trancount];
BEGIN TRANSACTION;
SELECT @@TRANCOUNT AS [Second trancount];
INSERT INTO demo(EmpName) VALUES('Hari');
BEGIN TRANSACTION;
SELECT @@TRANCOUNT AS [Third trancount];
INSERT INTO demo(EmpName) VALUES('MOHAN');
COMMIT TRANSACTION;
SELECT @@TRANCOUNT AS [Fourth trancount];
ROLLBACK TRANSACTION;
SELECT @@TRANCOUNT AS [Fifth trancount];

In the below screenshot, note the following points.

在下面的屏幕截图中,请注意以下几点。

  1. Initially, we do not have a transaction, so @@trancount returns value 0 最初,我们没有交易,因此@@ trancount返回值0
  2. The first BEGIN TRANSACTION statement increments the value of @@trancount by 1, so @@trancount returns 1 in the output 第一个BEGIN TRANSACTION语句将@@ trancount的值加1,因此@@ trancount在输出中返回1
  3. The second BEGIN TRANSACTION increments value of @@trancount y 1, so it returns 2 in the output 第二个BEGIN TRANSACTION将@@ trancount y的值递增1,因此它在输出中返回2
  4. The first commit statement decrements the value of @@trancount y 1, so it returns 1 in the output 第一条commit语句将@@ trancount y 1的值减1,因此它在输出中返回1。
  5. In the end, we have a ROLLBACK TRANSACTION that resets the value of@@trancount to zero, so it rollbacks the entire transaction irrespective of the previous commit transaction 最后,我们有一个ROLLBACK TRANSACTION,它将@@ trancount的值重置为零,因此它回滚整个事务,而与先前的提交事务无关

We can use the @@trancount in the stored procedure to check the existing open transactions and commit transactions in the value of @@trancount is greater than 1. In the below stored procedure, we make error handling using the TRY CATCH block. It performs COMMIT or ROLLBACK depending upon the value of @@trancount.

我们可以在存储过程中使用@@ trancount来检查现有的未清事务,并提交@@ trancount值大于1的事务。在下面的存储过程中,我们使用TRY CATCH块进行错误处理。 它根据@@ trancount的值执行COMMIT或ROLLBACK。

CREATE PROCEDURE SP_UpdateData @subtotal INT
ASBEGINBEGIN TRYBEGIN TRANSACTION;UPDATE [SQLShack].[dbo].[SalesData]SET UnitPrice = 15.9WHERE CustomerID = 10776AND subtotal = @subtotal;IF @@TRANCOUNT > 0COMMIT;END TRYBEGIN CATCHIF @@TRANCOUNT > 0ROLLBACK;SELECT ERROR_NUMBER() AS ErrorNumber;SELECT ERROR_MESSAGE() AS ErrorMessage;END CATCH;END;

隐式和显式事务的性能测试
(Performance testing of implicit and explicit transactions
)

Let’s perform a quick performance comparison of the implicit and explicit SQL Server transactions. For this demo, we insert records into the demo table with implicit and explicit transactions. Both queries insert the same number of rows in the demo table.

让我们对隐式和显式SQL Server事务进行快速性能比较。 对于此演示,我们使用隐式和显式事务将记录插入到演示表中。 这两个查询在演示表中插入相同数量的行。

Before running the query, enable the client statistics from the SSMS query-> Enable client statistics option.

运行查询之前,请从SSMS查询->启用客户端统计信息选项中启用客户端统计信息。

First, I run the implicit transaction and later in the same query window, start the explicit transaction.

首先,我运行隐式事务,然后在同一查询窗口中启动显式事务。

--Implicit transactionSET NOCOUNT on
DECLARE @i int
SET @i =1
WHILE (@i < 100000)
begininsert into Demo VALUES ('Performance test')set @i=@i+1
end
--Explicit transactionSET NOCOUNT on
DECLARE @i int
SET @i =1
BEGIN tran
WHILE (@i < 100000)
begininsert into Demo VALUES ('Performance test')set @i=@i+1
end
commit tran

In the below screenshot, we can see explicit transaction runs faster in comparison with the implicit transaction. You see a difference in the client processing time, total execution time and the wait time on the server replies.

在下面的屏幕快照中,我们可以看到显式事务比隐式事务运行得更快。 您会看到客户端处理时间,总执行时间和服务器答复上的等待时间有所不同。

In the explicit transaction, SQL Server flushes only when the log blocks in memory are full. In the implicit transaction, it does log flush more often, so it requires more time for it to complete.

在显式事务中,仅当内存中的日志块已满时,SQL Server才会刷新。 在隐式事务中,它确实更频繁地进行日志刷新,因此需要更多时间才能完成。

结论 (Conclusion)

In this article, we discussed implicit and explicit SQL Server transactions. We can decide to commit or rollback a transaction in explicit mode. You should make use of explicit transaction, especially in the production environment where a minor mistake can lead to a significant issue. You should always have a proper data backup and recovery strategy before making production data changes.

在本文中,我们讨论了隐式和显式SQL Server事务。 我们可以决定以显式模式提交或回滚事务。 您应该使用显式事务,尤其是在生产环境中,轻微的错误可能导致严重的问题。 在更改生产数据之前,您应该始终具有正确的数据备份和恢复策略。

翻译自: https://www.sqlshack.com/how-to-rollback-using-explicit-sql-server-transactions/

sql server 事务

sql server 事务_如何使用显式SQL Server事务回滚相关推荐

  1. sql azure 语法_如何:Azure中SQL Server文件快照备份

    sql azure 语法 After receiving new additions to backup and restore capabilities of SQL Servers like fi ...

  2. sql server 监视_使用动态管理对象监视SQL Server –请求

    sql server 监视 In my last post, Monitoring SQL Server with dynamic management objects – Sessions and ...

  3. sql azure 语法_在Azure中使用SQL Server 2016 CTP3

    sql azure 语法 As the time of the release of the next version of SQL Server is closing in, the cycle o ...

  4. sql int 比较_分享 21 个编写 SQL 的好习惯

    点击上方 IT牧场 ,选择 置顶或者星标 技术干货每日送达 前言 每一个好习惯都是一笔财富,本文基于MySQL,分SQL后悔药, SQL性能优化,SQL规范优雅三个方向,分享写SQL的21个好习惯,谢 ...

  5. sql 单引号_三种数据库的 SQL 注入详解

    SQL 注入原理 SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用 ...

  6. lua mysql 事务_为什么在 Redis 实现 Lua 脚本事务?-阿里云开发者社区

    在刚过去的几个月中,我一直在构思并尝试在 redis 中实现 lua 脚本的事务功能.没有多少人理解我的想法,所以我将通过一些历史为大家做下解释. MySQL 与 Postgres 在 1998-20 ...

  7. sql date类型_共享单车数据分析的SQL数据库设计

    SQL,发音为" sequel"(或SQL,如果愿意的话),是数据科学家的重要工具.实际上,它可以说是获取数据工作中最重要的语言.在共享单车数据分析的SQL设计中,我们将从入门者的 ...

  8. sql azure 语法_使用Visual Studio和SQL Azure数据库

    sql azure 语法 介绍 ( Introduction ) In this chapter, we will work with Visual Studio to connect to SQL ...

  9. 预编译sql查询语句_频繁查询重新编译– SQL查询性能杀手–检测

    预编译sql查询语句 previous part of this article, we presented query recompilation basics. We explained when ...

最新文章

  1. Python访问街区10个点,并俩俩绘制一条线,得到5条线,求最短的距离和?
  2. MFC EDIT控件的使用记录
  3. Docker Overlay 介绍
  4. 安全测试需要关注那些要点
  5. boost::parameter::aux::maybe相关的测试程序
  6. 分布式服务下的关键技术(转)
  7. SinoBBD跨入大数据产业发展新模式
  8. 132_Power BI之建模必备要素Power Query之数据表字段名称管理
  9. collection.stream()以及collect()方法
  10. L1-042 日期格式化-PAT团体程序设计天梯赛GPLT
  11. Echarts数据可视化series-effectscatter特效散点图,开发全解+完美注释
  12. struts2基本介绍
  13. 统一网关Gateway
  14. 桌面图标拖不动怎么办?
  15. STM32CubeIDE 复制工程
  16. 【转载】Ubuntu完全教程,让你成为Ubuntu高手!
  17. 电脑wifi显示连接上了但是没有网络是怎么回事,手机wifi网络正常,已解决
  18. 【Scikit-Learn 中文文档】40 数据集加载工具 - 用户指南 | ApacheCN
  19. APP开发定制需求的常说分销模式,对于分销大家了解多少呢?
  20. 解决PS等软件出现应用程序无法正常启动(0xc000007b)

热门文章

  1. Django-开胃菜
  2. PLSQL DEVELOPER编辑器的自动替换文件
  3. ESP32串口API
  4. 基于c#的windows基础设计(学习日记1)【关于异或运算】
  5. 性能测试之LoardRunner 手动关联二
  6. Android Studio来了,它能取代Eclipse吗?
  7. Oracle学习笔记---(一)
  8. vue引入id3_使用决策树ID3算法,预测收入是否大于50k
  9. 哲学家都在干些什么_哲学家们都干了些什么——哲学是什么
  10. 什么是互联网保险平台?