Вопрос

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

Цитата из статьи DeveloperWorks Стратегии транзакций:Обзор моделей и стратегий:

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

В качестве противоположного мнения приводится следующая цитата из документации Hibernate. Нетранзакционный доступ к данным и режим автоматической фиксации

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

Подобные дебаты также ведутся в списке рассылки EclipseLink. здесь.

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

Насколько я понимаю, это имеет значение только в том случае, если уровень изоляции выше, чем «чтение зафиксировано».Это верно?

Каков опыт и рекомендации?

Это было полезно?

Решение

Стивен Девивер привел несколько веских причин для запуска транзакций, даже если операции предназначены только для чтения базы данных:

  • Установите таймауты или режимы блокировки
  • Установить уровень изоляции

Стандартный SQL требует, чтобы даже запрос начинал новую транзакцию, если в данный момент ни одна транзакция не выполняется.Существуют СУБД, в которых этого не происходит - например, с режимом автоматической фиксации (оператор запускает транзакцию и фиксирует ее сразу же после завершения инструкции).Другие СУБД по умолчанию создают операторы атомарно (фактически автоматически фиксируют), но начинают явную транзакцию с такого оператора, как «BEGIN WORK», отменяя автофиксацию до следующего COMMIT или ROLLBACK (один из таких — IBM Informix Dynamic Server — когда база данных не находится в режиме MODE). АНСИ).

Я не уверен насчет совета никогда не откатывать назад.Это не имеет никакого значения для транзакции только для чтения, и если это раздражает ваших администраторов баз данных, то лучше избегать ROLLBACK.Но если ваша программа завершает работу без выполнения COMMIT, СУБД должна выполнить откат для вашей незавершенной транзакции - конечно, если она изменила базу данных, и (для простоты) даже если вы только выбрали данные.

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

Другие советы

Во-первых, это звучит как преждевременная оптимизация. Как отметил Стивен, большинство здравомыслящих баз данных в любом случае приведут вас к транзакции, и все, что они на самом деле делают, это вызывает commit после каждого оператора. Таким образом, с этой точки зрения, autocommit может быть менее производительным, поскольку каждый оператор должен начинать новую транзакцию. А может и нет. Только сравнительный анализ покажет, и я держу пари, что это не имеет никакого значения для вашего приложения.

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

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

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

Вот хорошая статья, подводящая итог . Подробности относятся к Oracle, но общие понятия.

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

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

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

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

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