sql-server - 两个 (SELECT TOP 1 +1 ) 语句和两个 INSERTS 同时
问题描述
如果在执行事务时,另一台客户端计算机进行了插入,会发生什么情况?
我有两台客户端计算机和一个数据库。这些计算机上有相同的程序。假设我们有订单表和 salesorder# 列,该列是唯一的。
如果两台计算机同时执行,我知道 SQL 服务器将选择其中一个事务并让另一个等待。所以这个交易确实遵循
@ordernumber= SELECT TOP Salesorder# +1 .
INSERT INTO order (salesorder#,dateship, user) VALUES (@ordernumber,GETDATE(),1,)
我相信如果两者同时发生,它只会选择 then 中的一个,完全运行,然后对另一个执行相同的操作。那是对的吗?
在不同的情况下会发生什么。如果事务开始,并且在 SELECT 语句之后但在 INSERT 发生之前请求另一个 INSERT(不是 TRANSACTION Just INSERT 语句)。
SQL Server 在这种情况下会做什么?这甚至可能吗?
解决方案
一句话:不要这样做!!这肯定会失败。
假设您有一个最大数量为 100 的表 - 现在您有两个(或多个)并发用户请求来执行插入。
两个请求都将首先读取最高数字 (100),然后每个请求都会将其递增 +1 - 因此两者内部的值都是 101。该SELECT
语句只会做一个快速的共享锁——但两者都SELECT
可以工作,并且会读取 100 的值。它们是否在一个事务中在这里没有区别——仅仅因为有一个事务并不能阻止一秒钟SELECT
的发生。
INSERT
实际上将创建一个排他锁 - 但仅在插入的行上(而不是整个表!)。阻止两个并发请求插入它们的新行并没有什么,并且两者都将尝试插入salesorder#
值为 101 的行。如果您对此有唯一约束,则其中一个请求将失败,因为另一个请求已经插入了值为 101。
这是您不应该手动处理给出顺序 ID 的众多原因之一-让数据库通过使用INT IDENTITY
列或SEQUENCE
对象来处理它。
推荐阅读
- python - Conda 工作但无法创建虚拟环境
- express - 抓取goodreads时如何避免403响应?
- angular - ng build后如何使用所需的功能?
- java - Java类内部静态接口的使用
- scikit-learn - 参数“coef0”是否表示 sklearn.svm.SVC 方法中的特定系数?
- c# - 检测用户何时暂时停止在 UITextField Xamarin iOS 上输入
- jgit - 来自 git.pull().call() 的受影响文件列表
- udp - 如何使用 Gstreamer 命令行在数据包中发送一行
- python - 按值排序字典
- c# - 为什么我的跳跃动画在中间停止并返回空闲?