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

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

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

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

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

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

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

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

насколько я могу видеть только сделайте разницу, если уровень изоляции выше, чем "Read committed". Правильно ли это?

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

3 ответов


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

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

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

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

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


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

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

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

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


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

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

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

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

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