Транзакции для доступа к БД только для чтения? - PullRequest
46 голосов
/ 04 мая 2009

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

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

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

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

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

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

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

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

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

Ответы [ 3 ]

21 голосов
/ 04 мая 2009

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

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

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

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

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

11 голосов
/ 04 мая 2009

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

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

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

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

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

10 голосов
/ 04 мая 2009

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...