Вопрос

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

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 Docs на уровне сериализации транзакции:

Сериализация

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top