Подтвердить что ты не робот

Транзакции для доступа только для чтения?

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

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

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

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

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

Существует также аналогичная дискуссия по списку рассылки EclipseLink здесь.

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

Насколько я вижу, это имеет значение только в том случае, если уровень изоляции выше, чем "read commit". Правильно ли это?

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

4b9b3361

Ответ 1

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

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

Стандартный SQL требует, чтобы даже запрос должен начать новую транзакцию, если в настоящий момент транзакция отсутствует. Существуют СУБД, где это не то, что происходит - например, с режимом autocommit (оператор запускает транзакцию и немедленно ее завершает, завершение оператора). Другие СУБД делают по умолчанию атомальные (фактически autocommit), но начинают явную транзакцию с инструкцией типа "BEGIN WORK", отменяя автообновление до следующего COMMIT или ROLLBACK (динамический сервер IBM Informix - один из них - когда база данных не является MODE ANSI).

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

Вот хорошая статья, суммирующая все это. Подробности специфичны для Oracle, но концепции носят общий характер.