Каков наилучший уровень изоляции транзакций по умолчанию для ERP, если таковой имеется?

Короткий фон: мы только начинаем мигрировать/переопределять систему ERP на Java с помощью Hibernate, ориентируясь на одновременное количество пользователей 50-100 пользователей, использующих эту систему. Мы используем MS SQL Server в качестве сервера базы данных, что достаточно хорошо для этих нагрузок.

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

Теперь вопрос: что было бы хорошим/разумным уровнем изоляции транзакций по умолчанию для использования в ERP-системе, учитывая использование примерно OLTP OLP на 85% и OLAP на 15%? Или я должен всегда принимать решение о каждой задаче, какой уровень транзакции использовать?

И как напоминание о четырех уровнях изоляции транзакций: ЗАЧИТАЙТЕ НЕОПРЕДЕЛЕННЫЙ, ПРОЧИТАЙТЕ, КОМИТЕТ, ПОВТОРНЫЙ ПРОЧИТАЙТЕ, СЕРИЦИАЛИЗИРОВАННЫЙ

Ответ 1

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

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

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

Ответ 2

На самом деле многое зависит от того, как вы разрабатываете приложение, простой ответ выполняется только на READ_COMMITTED.

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

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

Ответ 3

Для SQL Server (и, вероятно, для большинства основных РСУБД) я придерживаюсь значения по умолчанию. Для SQL Server это READ COMMITTED. Что-нибудь еще, и вы начинаете перегружать БД, что-то меньшее, и у вас проблемы с согласованностью.

Ответ 4

Не забывайте о SNAPSHOT, который находится ниже SERIALIZABLE.

Это зависит от того, насколько важно, чтобы данные были точными в отчетах. Это действительно задача по задаче.

Ответ 5

Чтение Uncommitted, безусловно, является слабым игроком на большинстве форумов. Однако есть причины использовать его, выходящие за рамки "скорости и точности", которые часто указываются.

Скажем, у вас есть:

  • Транзакция T1: записывает B, читает A (еще одна работа), Commit.
  • Транзакция T2: Записывает A, Читает B (еще одна работа), Commit.

При чтении, транзакции, указанные выше, не будут выпущены до фиксации. Затем вы можете столкнуться с ситуацией, когда T1 ожидает, что T2 освободит A, а T2 ждет, когда T1 освободит B. Здесь две транзакции сталкиваются в блокировке.

Вы можете перезаписать эти процедуры, чтобы избежать этого сценария (пример: приобретать ресурсы всегда в алфавитном порядке!). Тем не менее, со слишком большим количеством одновременных пользователей и десятками тысяч строк кода эта проблема может стать очень вероятной и очень сложной для диагностики и устранения.

Альтернативой является использование Read Uncommitted. Затем вы разрабатываете свои транзакции, предполагая, что могут быть грязные чтения. Я лично считаю эту проблему гораздо более локализованной и поддающейся обработке, чем взаимосвязанные тренировки.

Проблемы с грязными чтениями могут быть выгружены с помощью

  • (1) Откат: нет. Это должна быть последняя линия защиты в случае отказа оборудования, сбоя сети или сбоя программы.

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