SQL Server Вставить запрос для форума - PullRequest
2 голосов
/ 04 декабря 2010

Учитывая, что таблица форума и многие пользователи одновременно вставляют в нее сообщения, насколько безопасна эта транзакция?

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 Ответ

2 голосов
/ 04 декабря 2010

Ваша транзакция должна быть действительно безопасной - проверьте документы MSDN на уровне транзакции SERIALIZABLE :

SERIALIZABLE

Указывает следующее:

  • Заявления не может прочитать данные, которые были изменены , но еще не зафиксированы другими транзакциями.

  • Нет других транзакцийможет изменять данные , которые были прочитаны текущей транзакцией, пока текущая транзакция не завершится.

  • Другие транзакции не могут вставлять новые строки со значениями ключей, которые попадают в диапазон считанных ключейлюбыми операторами в текущей транзакции, пока текущая транзакция не завершится.

Блокировки диапазона помещаются в диапазон значений ключа, которые соответствуют условиям поиска каждого оператора, выполненного в транзакции.Это блокирует другие транзакции от обновления или вставки любых строк, которые соответствуют требованиям любого из операторов, выполняемых текущей транзакцией.Это означает, что если какой-либо из операторов в транзакции выполняется во второй раз, они будут читать тот же набор строк.Блокировки диапазона удерживаются до завершения транзакции.Это наиболее ограничивающий уровень изоляции, поскольку он блокирует все диапазоны ключей и удерживает блокировки до завершения транзакции.Поскольку параллелизм ниже, используйте эту опцию только при необходимости.Этот параметр имеет тот же эффект, что и установка HOLDLOCK для всех таблиц во всех инструкциях SELECT в транзакции.

Основная проблема с этим уровнем изоляции транзакции заключается в том, что это довольно большая нагрузка на сервер, и она сериализуется(как следует из названия) любой доступ, поэтому пострадают производительность и масштабируемость вашего сервера, например, при очень большом количестве пользователей вы, возможно, получите много тайм-аутов для пользователей, ожидающих завершения транзакции.

Итакиспользование более легкого подхода к глобальному идентификатору сообщения, так как INT IDENTITY определенно намного лучше!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...