SQL基本并发

SQL基本并发,sql,sql-server-2008,concurrency,Sql,Sql Server 2008,Concurrency,基本上,如果一百万用户同时运行这个,T1中会不会有超过一行的用户 INSERT INTO T1 (xField) SELECT 7 AS xField WHERE (SELECT COUNT(*) FROM T1) = 0 或者这是保证永远不会发生的,因为这都是一句话 如果那样不安全,像这样的东西怎么样 表T2(GoNorth和GoSouth不得同时为1): 然后发生这种情况: ID GoNorth GoSouth 1 0 0 结果是: User A

基本上,如果一百万用户同时运行这个,T1中会不会有超过一行的用户

INSERT INTO T1 (xField) SELECT 7 AS xField WHERE (SELECT COUNT(*) FROM T1) = 0
或者这是保证永远不会发生的,因为这都是一句话

如果那样不安全,像这样的东西怎么样

表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
什么样的事情可以同时发生,什么样的事情不能同时发生


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

对使用临时表的原始问题的回答:如果您只使用临时表,那么您的场景就不会发生表是特定于连接的,我相信您的数百万用户不会同时共享同一个连接

更新答案:


如果您使用的是具体的表,那么当多个用户正在运行insert语句时,T1中可以有多行。然而,这里还有其他的事情要考虑。有关更多详细信息,您应该阅读

我认为您需要这些信息来了解可能发生的情况:
我还建议您阅读Pinal Dave(他有点像SQL Server的活神:)

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


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

您的场景就是写倾斜异常的例子。根据所使用的隔离级别,它们可能是可能的,也可能不是。它们可以使用。

您运行的事务隔离级别是什么?默认值,我认为是READ COMMITTED,但如果需要,我可以更改它。:)当然,对于table
T2
,您只需应用一个合适的
CHECK
约束,以确保(无论发生什么情况),永远不会出现两列都是
1
的情况。类似地,对于table
T1
,添加第二列(被限制为只包含一个可能的值,然后声明为主键)可以确保只有一行。我不敢相信我错过了这一行。我改了,所以它们不再是临时的。
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