SQL Server Insert query for a forum

Considering a forum table and many users simultaneously inserting messages into it, how safe is this transaction?

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

Here I read last MessageId and increment it. I can't use Identity field because it needs to be incremented for every message inserted in a group (not every message insert into table.)

Answers


Your transaction should be quite safe indeed - check out the MSDN docs on the SERIALIZABLE transaction level:

SERIALIZABLE

Specifies the following:

  • Statements cannot read data that has been modified but not yet committed by other transactions.

  • No other transactions can modify data that has been read by the current transaction until the current transaction completes.

  • Other transactions cannot insert new rows with key values that would fall in the range of keys read by any statements in the current transaction until the current transaction completes.

Range locks are placed in the range of key values that match the search conditions of each statement executed in a transaction. This blocks other transactions from updating or inserting any rows that would qualify for any of the statements executed by the current transaction. This means that if any of the statements in a transaction are executed a second time, they will read the same set of rows. The range locks are held until the transaction completes. This is the most restrictive of the isolation levels because it locks entire ranges of keys and holds the locks until the transaction completes. Because concurrency is lower, use this option only when necessary. This option has the same effect as setting HOLDLOCK on all tables in all SELECT statements in a transaction.

The main problem with this transaction isolation level is that it's a pretty heavy load on the server, and serializes (as the name implies) any access, so your server performance and scalability will suffer, e.g. with very high numbers of users, you'll possibly get lots of timeouts for users waiting for a transaction to finish.

So using the more lightweight approach of a global message id as INT IDENTITY is definitely much better!


Need Your Help

Is normalization useful/necessary in optimization?

matlab optimization mathematical-optimization

I am trying to optimize a device design using Matlab optimization toolbox (using the fmincon function to be precise). To get my point across quickly I am providing a small variable set {l_m, r_m, l...

System Tray notifyIcon won't accept left-click event

c# windows winforms click

I'm creating a System-Tray only application. It's somewhat complicated to have the icon without a main form, but through previous topics on StackOverflow I've worked it out. The right-click works f...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.