仅当总计数小于阈值时,才将行插入SQL Server表

Pra*_*eep 2 sql t-sql sql-server

我正在使用SQL Server 2012.

我有用于存储用户的表.允许的最大用户数为100万.我有一个我正在注册用户的sproc.当我插入时,我想确保users表中的总行数不超过100万.我宁愿使用允许最大并发性的方法.

我相信我可以使用具有SERIALIZABLE的ISOLATION LEVEL的事务,然后首先计算行数并在总计数小于1百万时插入.我的理解是SERIALIZABLE是非常严格的,并且随着并发性的增加会导致性能下降.

IF(SELECT COUNT(*) FROM Users) < 100000
BEGIN
    INSERT INTO Users VALUES (@Name, @Email, @Password)
END
Run Code Online (Sandbox Code Playgroud)

如何以原子方式执行此操作以确保总行数小于100万,但同时我执行最小锁定以防止阻止其他事务?

这种情况的任何解决方案/最佳实践?

Pre*_*red 6

您可以创建一个SELECT以检查用户数并检索新用户的数据,并使用该选项插入表中:

INSERT INTO users (
  name, email, [password]
)
SELECT
  'newUser' AS name
  , 'email@example.com' AS email
  , 'fsfsfs' AS [password]
FROM
  users
HAVING
  COUNT(*) < 100000;
Run Code Online (Sandbox Code Playgroud)

SELECT当数据库中的用户少于100000时,该语句将返回一行;当有100000个或更多用户时,该语句将返回0.

整个statement(INSERT..SELECT)在每种情况下都有效,但是当SELECTpart返回0行时,INSERT不会插入任何内容.

使用SERIALIZABLE事务级别,可以保证concurent写入不会相互干扰.COUNT(*)使用最有效的索引/键来计算行数,这意味着锁定时间将是最小的.

由于整个操作在一个语句中完成,因此可以防止执行SELECT和之间的插入INSERT

SQL小提琴演示