Главная » Spring » Определение атрибутов транзакций Spring

0

В Spring декларативные транзакции определяются с помощью атрибутов транзакций. Атрибуты транзакции – это описание осо- бенностей применения транзакции к методу. Всего имеется пять раз- личных атрибутов транзакции, как показано на рис. 7.3.

Фреймворк Spring предоставляет несколько механизмов объявле- ния транзакций, однако все они опираются на эти пять параметров,

Рис. 7.3. Декларативные транзакции определяются в терминах правил распространения, уровня изоляции, признака «только для чтения», предельного времени ожидания и правил отмены

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

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

Правила распространения

Первый атрибут, который мы рассмотрим, определяет прави- ла распространения транзакции. Этот атрибут назначает границы транзакции. Всего фреймворк Spring определяет семь разных пра- вил распространения, которые перечислены в табл. 7.2.

Константы, описывающие правила  распространения.  Прави- ла распространения транзакций, перечисленные в табл. 7.2, опреде- лены в виде констант в интерфейсе org.springframework.transaction. TransactionDefinition.

Правила распространения транзакций, перечисленные в табл. 7.2, кому-то могут показаться знакомыми.  И  это  неудивительно,  потому что они отражают правила распространения транзакций, управляемых контейнером, в EJB (container-managed transactions,  CMT).  Напри- мер, правило PROPAGATION_REQUIRES_NEW в Spring эквивалентно правилу RequiresNew в CMT. Однако в Spring добавлено одно дополнительное правило распространения, отсутствующее в CMT, – PROPAGATION_NESTED, обеспечивающее   поддержку   вложенных   транзакций.

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

Таблица 7.2. Правила распространения определяют, когда будет запущена новая транзакция, а когда использоваться имеющаяся. Фреймворк Spring предлагает на выбор несколько правил

Правило распространения

Описание

PROPAGATION_MANDATORY

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

не будет запущена транзакция, фреймворк возбудит исключение

PROPAGATION_NESTED

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

PROPAGATION_NEVER

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

PROPAGATION_NOT_SUPPORTED

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

к TransactionManager

PROPAGATION_REQUIRED

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

в рамках этой транзакции. В противном случае будет запущена новая транзакция

PROPAGATION_REQUIRES_NEW

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

Таблица 7.2 (окончание)

Правило распространения

Описание

PROPAGATION_SUPPORTS

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

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

Уровни изоляции

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

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

#  Чтение неподтвержденных данных – когда одна транзакция чи-

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

#  Неповторимость получаемых результатов – когда транзакция

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

#  Чтение фантомных данных – напоминает неповторимость по-

лучаемых результатов. Эта ситуация может возникать, когда транзакция (T1) читает несколько строк, а затем вторая транз- акция (T2), выполняющаяся параллельно, вставляет несколь- ко строк. При выполнении последующих запросов первая транзакция (T1) будет обнаруживать дополнительные строки, отсутствовавшие прежде.

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

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

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

Уровень изоляции

Описание

ISOLATION_DEFAULT

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

ISOLATION_READ_UNCOMMITTED

Позволяет читать неподтвержденные изменения. Может привести к проблеме чтения неподтверж- денных данных, неповторимости получаемых результатов и чтения фантомных данных

ISOLATION_READ_COMMITTED

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

ISOLATION_REPEATABLE_READ

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

ISOLATION_SERIALIZABLE

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

Константы, описывающие уровни изоляции. Уровни изоляций, пере- численные в табл. 7.3, определены в виде констант в интерфейсе org. springframework.transaction.TransactionDefinition.

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

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

Только для чтения

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

Поскольку оптимизация доступа к данным только для чтения вы- полняется хранилищем данных в начале транзакции, этот признак имеет смысл использовать лишь при объявлении транзакций для методов,  для  которых  правило   распространения   допускает   созда- ние новой транзакции (PROPAGATION_REQUIRED, PROPAGATION_REQUIRES_NEW и PROPAGATION_NESTED).

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

Время ожидания

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

теристикой в объявлениях транзакций является параметр, опреде- ляющий время ожидания.

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

Поскольку отсчет времени ожидания начинается с момента  за- пуска транзакции,  объявлять  предельное  время  ожидания  имеет смысл только при объявлении транзакций  для  методов,  для  кото- рых правило распространения допускает создание новой транзакции (PROPAGATION_REQUIRED, PROPAGATION_REQUIRES_NEW  и PROPAGATION_NESTED).

Правила отмены

Последней гранью пятиугольника, изображенного на рис. 7.3, является набор правил, определяющих, какие исключения должны приводить к отмене транзакции, а какие нет. По умолчанию транз- акции отменяются только в случае появления исключений времени выполнения, но не в случае контролируемых исключений (checked exceptions). (Это соответствует правилам отмены, применяемым в EJB.)

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

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

Источник:   Уоллс К., Spring в действии. – М.: ДМК Пресс, 2013. – 752 с.: ил.

По теме:

  • Комментарии