Назад | Перейти на главную страницу

Почему «Начать транзакцию» до «Вставить запрос» блокирует всю таблицу?

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

Почему Begin Transaction блокирует всю таблицу? Писатели не должны блокировать Читателей. По умолчанию он должен быть включен.

Я использую SQL-Server 2005 Express. Я также хочу знать, как Oracle и MySQL справляются с одной и той же ситуацией.

Begin Transaction - это начало транзакции - никакие другие данные не могут быть записаны в таблицу, пока вы не завершите транзакцию, это сделано специально, чтобы обеспечить соблюдение критериев ACID в базе данных. http://en.wikipedia.org/wiki/ACID

Вы используете транзакцию, если вам нужно выполнить несколько запросов, как если бы они были одной атомарной операцией. Если вам не нужна атомарность, не используйте транзакции!

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

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

Если вы хотите, чтобы другие пользователи могли читать ваши данные, пока вы их еще изменяете, вы можете установить для TIL значение READ UNCOMMITED:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITED

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

Больше информации здесь:

http://msdn.microsoft.com/en-us/library/ms189122.aspx
http://msdn.microsoft.com/en-us/library/ms173763.aspx

Что ж, я не специалист по SQL Server, поэтому я не буду об этом говорить.

Но поскольку вопрос помечен как «oracle», а на плакате также спрашивалось, как это работает в Oracle, я обращусь к этой части.

В Oracle уровень изоляции транзакции по умолчанию - READ COMMITTED. Далее Oracle всегда блокирует на уровне строки и никогда не увеличивает блокировку до уровня блока (который называется страницей в SQL Server?).

Итак, если вы заблокируете строку «a» в таблице, а затем другой сеанс попытается заблокировать строку «b» в той же таблице, эта блокировка будет успешной, четный если строки находятся в одном блоке.

Что касается «начала транзакции», то в Oracle любой DML неявно начинает транзакцию, если она еще не началась. Эта транзакция будет оставаться открытой до тех пор, пока сеанс явно не зафиксирует, не откатится или не будет уничтожен (в этом случае Oracle откатит транзакцию).

Однако в Oracle есть синтаксис «начать транзакцию», то есть «установить транзакцию». Это можно использовать для начала транзакции только для чтения или чтения-записи или для установки уровня изоляции.

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

Писатели не должны блокировать читателей

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

Почему массовая вставка блокирует всю таблицу?

На самом деле это может быть правдой, а может и нет. Поведение под вашим контролем:

ТАБЛОК

Указывает, что блокировка уровня таблицы устанавливается на время операции массового импорта. Таблица может быть загружена одновременно несколькими клиентами, если таблица не имеет индексов и указан параметр TABLOCK. По умолчанию поведение блокировки определяется параметром таблицы table lock on bulk load.

Подробнее читайте в технических характеристиках продукта: Управление блокировкой для массового импорта.