4
INSERT INTO T1 (xField) SELECT 7 AS xField WHERE (SELECT COUNT(*) FROM T1) = 0

基本上,如果一百万用户同时运行它,T1 中是否会出现不止一行?

Thread A: SELECT COUNT(*) FROM T1: 0
Thread B: SELECT COUNT(*) FROM T1: 0
Thread A: INSERT INTO T1...
Thread B: INSERT INTO T1...

还是保证永远不会发生,因为这只是一个声明?

如果这不安全,那么这样的事情呢?

表 T2(GoNorth 和 GoSouth 绝不能同时为 1):

ID      GoNorth   GoSouth
1       0         0

然后会发生这种情况:

User A: UPDATE T2 SET GoNorth = 1 WHERE GoSouth = 0
User B: UPDATE T2 SET GoSouth = 1 WHERE GoNorth = 0

Thread A: Find rows where GoSouth = 0
Thread B: Find rows where GoNorth = 0
Thread A: Found a row where GoSouth = 0
Thread B: Found a row where GoNorth = 0
Thread A: Setting GoNorth = 1 for the located row
Thread B: Setting GoSouth = 1 for the located row

结果:

ID      GoNorth   GoSouth
1       1         1

什么可以同时发生,什么不能同时发生的规则是什么?

我的数据库引擎是“Microsoft SQL Server 2008 R2 (SP2)”。

4

4 回答 4

2

不,它是作为单个语句编写的,因此 SQL 规则规定整个语句是原子的。

但是,这里有一些警告。首先,这可能意味着创建大量锁,直到查询完成之前您的表实际上变得不可用。换句话说,为了保证安全,你会抛弃并发。另一个警告是,这仅适用于默认隔离级别。较弱的隔离级别可能允许查询在不创建适当锁的情况下运行。一个非常弱的隔离级别可能允许它忽略锁。

于 2013-05-08T13:37:16.087 回答
1

回答使用#temp 表的原始问题:如果您只使用#tables 即临时表,那么您的情况将不会发生。# 表是特定于连接的,我相信您的百万用户不会同时共享同一个连接。

更新的答案:

如果您使用的是具体表,那么是的,T1 中可以有不止一行是多个用户正在运行插入语句。但是,这里还有其他需要考虑的事情。有关更多详细信息,您应该阅读SQL SERVER – 并发基础 – Vinod Kumar 的来宾帖子

于 2013-05-08T13:22:54.793 回答
0

我认为您需要这些信息来了解可能发生的情况:SQL 服务器并发访问
我还建议您阅读Pinal Dave 的并发基础知识(他是 SQL Server 的行走之神 :)

于 2013-05-08T13:30:34.333 回答
0

您的场景是写入偏斜异常的示例。根据使用的隔离级别,它们可能会也可能不会。它们可以通过快照隔离实现。

于 2013-05-08T13:39:16.960 回答