Лучший уровень изоляции SQL Server для веб-приложения? - PullRequest
2 голосов
/ 02 ноября 2009

У нас есть веб-сайт, использующий ASP.NET MVC и SQL Server 2008, и мы используем уровень изоляции транзакции по умолчанию, который является Сериализуемым. Но это делает приложение непригодным для использования, если открыта какая-либо транзакция, так как у нас есть таблица, которая используется почти всем, и она работает как

select * from table1 where id = 1

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

Я читал, что может быть лучшим вариантом для веб-приложений с большим количеством транзакций.

Я вроде продан на уровне изоляции Snapshot. Которые дают лучшее из всего:

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

Какой уровень изоляции может быть для веб-приложения согласно вашему опыту?

Edit: Уровень изоляции по умолчанию - от Transactionscope, просто чтобы прояснить, почему я упомянул сериализуемый в качестве значения по умолчанию.

Я читаю множество блогов и ответов здесь, предлагая использовать no_lock для выбора, но если вы спросите меня, это своего рода хак. В реальной жизни, возможно, в 99,99% случаев все будет в порядке. И это хорошо для Facebook, Twitter или Stack Overflow. Кому интересно, если данные повреждены. Но я считаю, что если мы используем изоляцию транзакций, то она должна быть на 100% гарантированной архитектурой. В противном случае не используйте его вообще и добавьте некоторые другие проверки целостности данных с помощью триггера или чего-то еще.

Ответы [ 6 ]

3 голосов
/ 03 ноября 2009

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

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

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

3 голосов
/ 02 ноября 2009

Полагаю, этот вопрос лучше подходит для serverfault.com, где сказано, что я понимаю эту тему:

Во-первых, так как, когда уровень изоляции по умолчанию стал Serializable, я подумал, что это Read Committed!

Во-вторых, снимок может быть не очень хорошей идеей, поскольку он эффективно использует базу данных tempdb (которая по большей части находится в памяти) для хранения одновременных версий данных, поэтому, если вам повезет, вам не хватит оперативной памяти на 1- 2-3.

В-третьих, уровень сериализации не является делом «все или ничего», вместо этого вы должны смотреть на каждый запрос и устанавливать его для каждого запроса, используя подсказки запроса или что-то еще. Я бы сказал, что для вашего магического оператора select, который используется везде, где вы, возможно, даже захотите использовать подсказку (nolock) (при условии, что базовая таблица предназначена для чтения только на 99,99%; кстати, если вы заметили, что делаете слишком много операций только для чтения, это указывает на то, что вы должны искать в кеширование, будь то собственный кеш ASP.NET или Memcached или что-то еще), в то время как остальные могут использовать зафиксированное чтение. Только в редких случаях (например, автоматически поддерживаемая таблица поиска) вы хотите что-то выше этого.

Далее, не злоупотребляйте пессимистической блокировкой вообще. Более разумный выбор - использовать оптимистическую блокировку, например вставьте, надеясь, что нет никакого заблуждения и разберитесь с невыполненным ограничением впоследствии и тому подобными вещами. Для обновлений вы можете добавить столбец отметки времени и включить его в предложение where. Если кто-то похитил обновление до вас, количество строк будет равно 0. И т.д.

Надеюсь, это имеет смысл.

2 голосов
/ 03 ноября 2009

Одна из лучших стратегий - Управление версиями строк . Вы можете установить это на уровне базы данных как:

ALTER DATABASE YourDatabaseName SET READ_COMMITTED_SNAPSHOT ON;

Это в основном делает неблокирующие чтения по умолчанию. См. Также Уровни изоляции на основе управления версиями строк в компоненте Database Engine .

1 голос
/ 02 ноября 2009

Вам нужно пойти с read committed и сделать оптимистическую блокировку в вашем приложении. Это кажется более надежным в большинстве случаев.

Также взгляните , как команда stackoverflow решила свои проблемы с блокировкой.

1 голос
/ 02 ноября 2009

Хорошая СУБД будет блокировать только строку, указанную "id = 1", а не всю таблицу, когда вы запускаете такой SELECT. Сериализуемый уровень изоляции очень хорош при условии, что база данных обеспечивает разумную блокировку строк и что все ожидающие блокировки снимаются в конце каждого веб-запроса; как правило, это означает закрытие соединения с базой данных в конце запроса или, альтернативно, выдачу ROLLBACK или COMMIT, если соединение необходимо повторно использовать для последующего запроса.

0 голосов
/ 15 февраля 2014

Я думаю, что лучшим уровнем изоляции является уровень изоляции моментальных снимков, поскольку он будет считывать последние сохраненные данные в таблице, если другая транзакция не будет завершена и не будет заблокирована и нет грязного чтения. Поэтому лучше использовать уровень изоляции моментальных снимков лучше, чем Read Committed

Как вы можете сделать это двумя путями

1-измененный набор для тестирования базы данных allow_SnapShot_Isolation on; или же Набор для проверки базы данных с двумя изменениями Read_Committed_Snapshot on;

Я надеюсь быть полезным для читателя Махмуд Шахин Египет 0201288846966

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