Это плохая практика всегда создавать транзакцию?

88

Это плохая практика всегда создавать транзакцию?

Например, это хорошая практика, чтобы создать транзакцию только для одного SELECT?

Какова стоимость создания транзакции, когда она действительно не нужна?

Даже если вы используете уровень изоляции, как READ UNCOMMITTEDэто, это плохая практика?

elranu
источник
1
Глядя на влияние BEGIN TRAN SELECT ... COMMITпротив только SELECTчто, кажется, очень незначительная разница в производительности.
Мартин Смит

Ответы:

100

Плохая практика всегда создавать транзакцию?

Это зависит от того, в каком контексте вы говорите здесь. Если это обновление, я настоятельно рекомендую явно использовать TRANSACTIONS. Если это SELECT, то НЕТ (явно).

Но подождите, чтобы понять больше: сначала все, что есть на сервере sql, содержится в транзакции.

Когда параметр сеанса IMPLICIT_TRANSACTIONSустановлен, OFFи вы явно указываете, begin tranа commit/rollbackзатем это обычно называют явной транзакцией . В противном случае вы получите транзакцию автоматического подтверждения.

Когда IMPLICIT_TRANSACTIONSэто неявная транзакция автоматически запускается при выполнении одного из типов операторов , зарегистрированных в книгах онлайн статье (например , / / ) , и оно должно быть совершенно или отката в явном виде. Выполнение в этом режиме увеличило бы и запустило еще одну «вложенную» транзакцию)ONSELECTUPDATECREATEBEGIN TRAN@@TRANCOUNT

Чтобы переключиться в какой режим вы используете, вы должны использовать

SET IMPLICIT_TRANSACTIONS ON

или же

SET IMPLICIT_TRANSACTIONS OFF

select @@OPTIONS & 2

если выше возвращает 2, вы находитесь в неявном режиме транзакции. Если он возвращает 0, вы находитесь в автокоммите.

сколько стоит создание транзакции, когда это действительно не нужно?

Транзакции необходимы для перевода базы данных из одного согласованного состояния в другое согласованное состояние. Транзакции не имеют стоимости, так как нет альтернативы транзакциям. См. Использование уровней изоляции на основе управления версиями строк.

Даже если вы используете уровень изоляции read_uncomited. Это плохая практика? потому что у него не должно быть проблем с блокировкой.

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

Вы можете использовать это на уровне соединения / запроса, чтобы это не влияло на другие запросы.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

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

РЕДАКТИРОВАТЬ:

Из любопытства я провел некоторый тест, измеряющий влияние на T-log с помощью счетчиков Perfmon, таких как Log Fteshed / Sec, Log Flush Waits / Sec (Количество коммитов в секунду, ожидающих сброса LOG, как показано ниже):

введите описание изображения здесь

образец кода :

create table testTran (id int, Name varchar(8))
go

-- 19 sec
-- Autocommit transaction
declare @i int
set @i = 0
while @i < 100000
begin 
insert into testTran values (1,'Kin Shah')
set @i = @i+1
end
---------------------------------------------------
-- 2 sec
-- Implicit transaction
SET IMPLICIT_TRANSACTIONS ON
declare @i int
set @i = 0
while @i < 100000
begin 
insert into testTran values (1,'Kin Shah')
set @i = @i+1
end
COMMIT;
SET IMPLICIT_TRANSACTIONS OFF


----------------------------------------------------
-- 2 sec
-- Explicit transaction
declare @i int
set @i = 0
BEGIN TRAN
WHILE @i < 100000
Begin
INSERT INTO testTran values (1,'Kin Shah')
set @i = @i+1
End
COMMIT TRAN

Автокоммит транзакций : (отредактировано, как выделено @TravisGan)

  • Вставка заняла 19 секунд.
  • Каждый Autocommit будет сбрасывать буфер T-log на диск из-за autocomit (после выделения @TravisGan, и я пропустил это, чтобы упомянуть).
  • Процесс CHECKPOINT будет завершаться быстро, так как объем грязного буфера журнала, который требуется очистить, будет меньше, так как он часто работает тихо.

ПОДТВЕРЖДАЮТ & Явная Сделка:

  • Вставка заняла 2 сек.
  • Для транзакции EXPLICIT буферы журнала будут сбрасываться только тогда, когда они заполнены.
  • В отличие от транзакции Autocommit, в транзакции EXPLICIT процесс CHECKPOINT будет длиться дольше, так как он будет иметь больше буферов журнала для очистки (помните, что буферы журнала сбрасываются, только когда они заполнены).

Существует DMV sys.dm_tran_database_transactions, которая будет возвращать информацию о транзакциях на уровне базы данных.

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

Из приведенных выше тестов практически не существует различий между неявными и явными транзакциями.

Спасибо @TravisGan за помощь, чтобы добавить больше к ответу.

Кин Шах
источник
35

Оператор SQL всегда выполняется в транзакции. Если вы не запустите его явно, каждый оператор SQL будет выполняться в отдельной транзакции.

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

Andomar
источник
1

Вопрос заключается в том, должна ли группа операций рассматриваться как одно действие. Другими словами, все операции должны быть завершены и зафиксированы успешно, или ни одна из операций не может быть зафиксирована. Если у вас есть сценарий, который требует, чтобы вы прочитали предварительные данные, а затем выполнили обновления на основе этих данных, то первоначальное чтение, вероятно, должно быть частью транзакции. Примечание: я специально избегаю выбора / вставки / обновления. Объем транзакции может фактически быть на уровне приложения и включать несколько операций с базами данных. Подумайте о классических моделях, таких как бронирование места в самолете или запрос / снятие средств с баланса банка. Нужно шире взглянуть на проблему, чтобы гарантировать, что все приложение дает надежные, согласованные данные.

луч
источник