并发插入的记录是否会在表中重叠?SQL场景下的可能性问询
并发INSERT下IDENTITY表的状态问题
首先明确我们的测试基础:
CREATE TABLE SomeTable (SomeKey int IDENTITY(1,1), SomeInt int)
同时执行两条批量插入语句:
-- 语句A INSERT INTO SomeTable (SomeInt) SELECT 1 UNION ALL SELECT 1; -- 语句B INSERT INTO SomeTable (SomeInt) SELECT 2 UNION ALL SELECT 2;
答案是存在这样的场景,具体取决于SQL Server的配置和事务调度逻辑:
场景1:默认IDENTITY_CACHE开启状态
默认情况下,SQL Server会为批量INSERT语句一次性分配所需的所有IDENTITY值。也就是说,语句A会拿到连续的2个SomeKey值(比如1、2),语句B拿到另外连续的2个(比如3、4),或者反过来。此时如果按SomeKey排序查询,结果只会是:
要么两个1在前、两个2在后,要么两个2在前、两个1在后,不会出现交错的情况。
场景2:禁用IDENTITY_CACHE状态
如果我们禁用了当前数据库的IDENTITY缓存:
ALTER DATABASE [YourDatabaseName] SET IDENTITY_CACHE OFF;
此时SQL Server会为每一行插入单独分配IDENTITY值,而不是为整个批量语句预分配。这时候并发调度就可能让两个语句的行插入过程交错:
- 语句A先插入第一行,拿到SomeKey=1,值为1
- 语句B抢过调度权,插入第一行,拿到SomeKey=2,值为2
- 语句A继续插入第二行,拿到SomeKey=3,值为1
- 语句B继续插入第二行,拿到SomeKey=4,值为2
最终按SomeKey排序的表数据就会呈现交错状态:
| SomeKey | SomeInt |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
| 4 | 2 |
这种状态就是完全可能出现的。
另外还要注意:如果不对查询结果指定ORDER BY SomeKey,堆表的返回顺序是不确定的,即使IDENTITY值是连续的,也可能出现看起来“交错”的结果,但这只是查询显示顺序的问题,并非实际表中IDENTITY值的分配顺序。
内容的提问来源于stack exchange,提问作者Kevin Ganancial
相关产品推荐
相关产品推荐

