SQL Server插入论坛的查询

时间:2010-12-04 08:04:04

标签: sql sql-server concurrency transaction-isolation

考虑到论坛表格和许多用户同时向其中插入消息,此交易的安全性如何?

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字段,因为它需要针对组中插入的每条消息递增(不是每个消息都插入到表中。)

1 个答案:

答案 0 :(得分:2)

您的交易确实非常安全 - 请查看MSDN docs on the SERIALIZABLE transaction level

SERIALIZABLE

  

指定以下内容:

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

  •   
  • 没有其他交易可以修改已被读取的数据   当前交易直到当前   交易完成。

  •   
  • 其他事务无法插入具有键值的新行   会落在读键的范围内   通过当前的任何陈述   交易直到当前   交易完成。

  •   
     

范围锁定位于与之匹配的键值范围内   每个陈述的搜索条件   在交易中执行。这块   来自更新或的其他交易   插入符合条件的任何行   对于任何执行的语句   当前的交易。这意味着   如果任何一个陈述   交易执行一秒钟   那时候,他们会读同一套   行。范围锁保持到   交易完成。这是   最严格的隔离   级别,因为它锁定整个范围   按键并保持锁直到   交易完成。因为   并发性较低,请使用此选项   只在必要时。这个选项有   与设置HOLDLOCK的效果相同   所有SELECT语句中的所有表   交易。

此事务隔离级别的主要问题是它在服务器上的负载相当大,并且序列化(顾名思义)任何访问,因此您的服务器性能和可伸缩性将受到影响,例如:如果用户数量非常多,那么等待交易完成的用户可能会获得大量超时。

因此,使用全局消息ID的更轻量级方法INT IDENTITY肯定要好得多!