考虑一个论坛表,许多用户同时将消息插入其中,此交易有多安全?

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION

 DECLARE @LastMessageId SMALLINT
 SELECT @LastMessageId = MAX(MessageId)
 FROM Discussions
 WHERE ForumId = @ForumId AND DiscussionId = @DiscussionId

 INSERT INTO Discussions
 (ForumId, DiscussionId, MessageId, ParentId, MessageSubject, MessageBody)
 VALUES
 (@ForumId, @DiscussionId, @LastMessageId + 1, @ParentId, @MessageSubject, @MessageBody)

IF @@ERROR = 0
BEGIN
 COMMIT TRANSACTION
 RETURN 0
END

ROLLBACK TRANSACTION
RETURN 1

在这里,我阅读了最后一条消息,并将其递增。我不能使用身份字段,因为需要对组中插入的每个消息进行递增(并非每个消息插入表中。)。

有帮助吗?

解决方案

您的交易确实应该很安全 - 查看 可序列化交易级别的MSDN文档:

可序列化

指定以下内容:

  • 语句 无法读取已修改的数据 但尚未由其他交易实施。

  • 没有其他交易可以修改数据 当前交易已经阅读,直到当前交易完成为止。

  • 其他交易无法用键值插入新行,这些键值将属于当前交易中的任何语句读取的键范围,直到当前交易完成为止。

范围锁放置在与交易中执行的每个语句的搜索条件相匹配的键值范围内。这会阻止其他交易更新或插入将有资格获得当前事务执行的任何语句的行。这意味着,如果第二次执行交易中的任何语句,他们将读取相同的行。保留范围锁,直到交易完成为止。这是对隔离级别的最限制,因为它锁定了整个钥匙范围,并保留锁直到交易完成。因为并发较低,因此仅在必要时才使用此选项。此选项在交易中所有选择语句中的所有表中都具有与设置holdlock相同的效果。

此交易隔离级别的主要问题是,它是服务器上的一个很重的负载,并且序列化(如名称所示)任何访问权限,因此您的服务器性能和可伸缩性将受到影响,例如,用户数量很高,您将对于用户等待交易完成的用户可能会获得大量超时。

因此,使用全局消息ID的更轻巧的方法作为 INT IDENTITY 绝对好多了!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top