考虑到论坛表格和许多用户同时向其中插入消息,此交易的安全性如何?
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
这里我读了最后一条MessageId并递增它。我不能使用Identity字段,因为它需要针对组中插入的每条消息递增(不是每个消息都插入到表中。)
答案 0 :(得分:2)
您的交易确实非常安全 - 请查看MSDN docs on the SERIALIZABLE transaction level:
SERIALIZABLE
指定以下内容:
语句无法读取已修改的数据但尚未读取 由其他交易承诺。
没有其他交易可以修改已被读取的数据 当前交易直到当前 交易完成。
其他事务无法插入具有键值的新行 会落在读键的范围内 通过当前的任何陈述 交易直到当前 交易完成。
范围锁定位于与之匹配的键值范围内 每个陈述的搜索条件 在交易中执行。这块 来自更新或的其他交易 插入符合条件的任何行 对于任何执行的语句 当前的交易。这意味着 如果任何一个陈述 交易执行一秒钟 那时候,他们会读同一套 行。范围锁保持到 交易完成。这是 最严格的隔离 级别,因为它锁定整个范围 按键并保持锁直到 交易完成。因为 并发性较低,请使用此选项 只在必要时。这个选项有 与设置HOLDLOCK的效果相同 所有SELECT语句中的所有表 交易。
此事务隔离级别的主要问题是它在服务器上的负载相当大,并且序列化(顾名思义)任何访问,因此您的服务器性能和可伸缩性将受到影响,例如:如果用户数量非常多,那么等待交易完成的用户可能会获得大量超时。
因此,使用全局消息ID的更轻量级方法INT IDENTITY
肯定要好得多!