SQL基本并发
基本上,如果一百万用户同时运行这个,T1中会不会有超过一行的用户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
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
的情况。类似地,对于tableT1
,添加第二列(被限制为只包含一个可能的值,然后声明为主键)可以确保只有一行。我不敢相信我错过了这一行。我改了,所以它们不再是临时的。
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