当前位置:  开发笔记 > 编程语言 > 正文

T-SQL存储过程执行'原子'吗?

如何解决《T-SQL存储过程执行'原子'吗?》经验,为你挑选了2个好方法。

假设我有一个看起来像这样的简单存储过程(注意:这只是一个例子,不是一个实际的过程):

CREATE PROCEDURE incrementCounter AS

DECLARE @current int
SET @current = (select CounterColumn from MyTable) + 1

UPDATE
    MyTable
SET
    CounterColumn = current
GO

我们假设我有一个名为'myTable'的表,其中包含一行,'CounterColumn'包含我们当前的计数.

这个存储过程可以同时执行多次吗?

即这是可能的:

我称之为'incrementCounter'两次.调用A到达设置'当前'变量的位置(假设它是5).调用B到达设置"当前"变量(也将是5)的点.呼叫A完成执行,然后呼叫B结束.最后,该表应包含值6,但由于执行的重叠而包含5



1> dkretz..:

这适用于SQL Server.

每个语句都是原子的,但是如果你希望存储过程是原子的(或者一般的任何语句序列),你需要用

BEGIN TRANSACTION
Statement ...
Statement ...
COMMIT TRANSACTION

(通常使用BEGIN TRAN和END TRAN.)

当然,根据其他正在发生的事情,有很多方法可以解决锁定问题,因此您可能需要一种策略来处理失败的事务.(完全讨论可能导致锁定的所有情况,无论你如何设计这个特定的SP,都超出了问题的范围.)但是由于原子性,它们仍然会被重新提交.根据我的经验,您可能会很好,不知道您的交易量和数据库上的其他活动.请原谅我说明显的.

与流行的误解相反,这将适用于您的默认事务级别设置.


他特意说他想要治愈.你的答案无法治愈.错误的答案值得支持,直到他们看起来错误,其他人不会被欺骗.理论与否,它是不完整的.
原子性不能解决并发问题和竞争条件.如您所建议的那样修改OPs检查存储过程将不会容忍并发,因为随着时间的推移获取并升级锁.如果两个客户端A&B同时运行此过程,则可以获得此模式:A获取读锁定并读取表,然后释放锁定.B获取读锁定并从表**读取相同的值,然后释放锁定.获取更新锁定和更新,然后B执行相同操作.BLAM.你死定了.你必须提前获得正确的锁定以正确阻止!

2> Dave Cludera..:

除了放置之间的代码BEGIN TRANSACTIONEND TRANSACTION,你需要确保你的事务隔离级别设置正确.

例如,SERIALIZABLE隔离级别将防止代码同时运行时丢失更新,但READ COMMITTED(SQL Server Management Studio中的默认值)不会.

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

正如其他人已经提到的那样,在确保一致性的同时,这可能导致阻塞和死锁,因此可能不是实践中的最佳解决方案.


@Dave,我做了一些研究,发现你的描述不准确.SERIALIZABLE隔离级别不会阻止其他客户端读取相同的值.如果两个客户端读取SERIALIZABLE然后一个尝试更新会导致死锁并且一个客户端连接将以偏见终止,它会怎么做.
推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有