我正在使用 SQL Server 2012。
我有一个存储用户的表。允许的最大用户数为 100 万。我有一个正在注册用户的存储过程。当我插入时,我想确保 users 表中的总行数不会超过 100 万。我更愿意使用允许最大并发性的方法。
我相信我可以使用隔离级别为 SERIALIZABLE 的事务,然后首先计算行数,如果总计数小于 100 万则插入。我的理解是 SERIALIZABLE 限制性很大,并且会随着并发的增加而导致性能下降。
IF(SELECT COUNT(*) FROM Users) < 100000
BEGIN
INSERT INTO Users VALUES (@Name, @Email, @Password)
END
如何以原子方式执行此操作,以便保证总行数小于 100 万行,但同时执行最小锁定以防止阻塞其他事务?
对于这种情况有什么解决方案/最佳实践吗?
您可以创建一个SELECT
检查用户计数并检索新用户的数据并使用该选择插入表中:
INSERT INTO users (
name, email, [password]
)
SELECT
'newUser' AS name
, '[email protected] /cdn-cgi/l/email-protection' AS email
, 'fsfsfs' AS [password]
FROM
users
HAVING
COUNT(*) < 100000;
The SELECT
当数据库中的用户数少于 100000 时,该语句将返回 1 行;当数据库中有 100000 个用户或更多时,该语句将返回 0 条记录。
整个声明(INSERT..SELECT
)在每种情况下都有效,但是当SELECT
部分返回 0 行,INSERT
不会插入任何东西。
随着SERIALIZABLE
事务级别,保证并发写入不会互相干扰。 COUNT(*) 使用最有效的索引/键来计算行数,这意味着锁定时间将是最短的。
由于整个操作是在一个语句中完成的,这可以防止在执行之间插入SELECT
and INSERT
SQL Fiddle 演示 http://sqlfiddle.com/#!3/8dd03/3
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)