Отношение уровней изоляции транзакций с блокировками на столе

Я прочитал около 4 уровней изоляции:

Isolation Level       Dirty Read    Nonrepeatable Read  Phantom Read  
READ UNCOMMITTED      Permitted       Permitted           Permitted
READ COMMITTED              --        Permitted           Permitted
REPEATABLE READ             --             --             Permitted
SERIALIZABLE                --             --              --

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

READ UNCOMMITTED - no lock on table
READ COMMITTED - lock on committed data
REPEATABLE READ - lock on block of sql(which is selected by using select query)
SERIALIZABLE - lock on full table(on which Select query is fired)

ниже представлены три явления, которые могут возникать при изоляции транзакций
Dirty Read - без блокировки
Невосстановимое чтение - не грязное чтение как блокировка зафиксированных данных
Phantom Прочитайте - заблокируйте блок sql (который выбран с помощью запроса выбора)

Я хочу понять, где мы определяем эти уровни изоляции: только на уровне jdbc/hibernate или в DB также

PS: Я прошел через ссылки в Уровнях изоляции в оракуле, но они выглядят неуклюжими и говорят о специфичных для базы данных

Ответ 1

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

Например, у вас есть 3 параллельных процесса A, B и C. A запускает транзакцию, записывает данные и фиксирует/откатывает (в зависимости от результатов). B просто выполняет инструкцию SELECT для чтения данных. C считывает и обновляет данные. Все эти процессы работают в одной таблице T.

  • READ UNCOMMITTED - нет блокировки на столе. Вы можете читать данные в таблице во время записи на нем. Это означает, что A записывает данные (не работает), а B может читать эти данные и использовать их (для любых целей). Если A выполняет откат, B все еще прочитал данные и использовал их. Это самый быстрый, но самый небезопасный способ работы с данными, поскольку может привести к появлению данных в не связанных физически таблицах (да, две таблицы могут быть логически, но физически не связаны в приложениях реального мира = \).
  • READ COMMITTED - блокировка зафиксированных данных. Вы можете прочитать данные, которые были только совершены. Это означает, что A записывает данные, а B не может читать данные, сохраненные A, до тех пор, пока A не выполнит фиксацию. Проблема здесь в том, что C может обновлять данные, которые были прочитаны и использованы для клиентов B и B, не будет иметь обновленных данных.
  • REPEATABLE READ - блокировка блока sql (который выбирается с помощью select query). Это означает, что B считывает данные при некотором условии i.e. WHERE aField > 10 AND aField < 20, A вставляет данные, где значение aField составляет от 10 до 20, тогда B снова считывает данные и получает другой результат.
  • SERIALIZABLE - блокировка полной таблицы (по которой запускается запрос выбора). Это означает, что B считывает данные, а никакая другая транзакция не может изменять данные в таблице. Это самый безопасный, но самый медленный способ работы с данными. Кроме того, поскольку простая операция чтения блокирует таблицу, это может привести к серьезным проблемам с производством: представьте, что таблица T - таблица счетов, пользователь X хочет знать счета-фактуры дня, а пользователь Y хочет для создания нового счета-фактуры, поэтому, когда X выполняет чтение счетов-фактур, Y не может добавить новый счет-фактуру (а когда речь идет о деньгах, люди становятся действительно сумасшедшими, особенно боссы).

Я хочу понять, где мы определяем эти уровни изоляции: только на уровне jdbc/hibernate или в DB также

Используя JDBC, вы определяете его с помощью Connection#setTransactionIsolation.

Использование Hibernate:

<property name="hibernate.connection.isolation">2</property>

Где

  • 1: ПРОЧИТАТЬ НЕОБХОДИМЫЕ
  • 2: ЧИТАЙТЕ КОМИТЕТЫ
  • 4: ПОВТОРНОЕ ПРОЧИТАНИЕ
  • 8: SERIALIZABLE

Конфигурация спящего режима, взятая из здесь (извините, это на испанском языке).

Кстати, вы можете установить уровень изоляции на СУРБД:

и далее и далее...

Ответ 2

Как говорит brb tea, зависит от реализации базы данных и алгоритма, который они используют: MVCC или двухфазная блокировка.

CUBRID (СУРБ с открытым исходным кодом) объясняет идею этих двух алгоритмов:

  • Двухфазная блокировка (2PL)

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

  • Управление несколькими версиями concurrency (MVCC)

Другой - разрешить каждой из них транзакции T1 и T2, чтобы имеют свои измененные версии. Даже когда транзакция T1 имеет изменил запись A с 1 на 2, транзакция T1 покидает исходное значение 1 как есть и пишет, что версия транзакции T1 записи A равно 2. Затем следующая транзакция T2 изменяет A запись от 1 до 3, а не от 2 до 4, и пишет, что T2 транзакционная версия записи A равна 3.

Когда транзакция T1 откатывается назад, не имеет значения, если 2, версия транзакции T1, не применяется к записи A. После что, если транзакция T2 совершена, транзакция 3, T2 версия, будет применена к записи A. Если транзакция T1 совершенные до транзакции T2, запись A изменяется на 2, а затем до 3 во время совершения транзакции T2. Финал статус базы данных идентичен статусу выполнения каждого транзакция независимо, без какого-либо влияния на другие транзакции. Следовательно, он удовлетворяет свойству ACID. Этот метод называется Управление несколькими версиями concurrency (MVCC).

MVCC разрешает одновременные изменения за счет увеличения объема служебных данных в памяти (поскольку он должен поддерживать разные версии одних и тех же данных) и вычислений (на уровне REPETEABLE_READ вы не можете потерять обновления, чтобы он проверял версии данных, как Hiberate делает с Optimistick Locking).

В 2PL Уровни изоляции транзакций управляют следующим:

  • Выполняются ли блокировки при чтении данных и какие типы блокировок запрашиваются.

  • Как долго сохраняются блокировки чтения.

  • Операция чтения, ссылающаяся на строки, измененные другой транзакцией:

    • Блокировать до освобождения исключительной блокировки строки.

    • Получить заверенную версию строки, существовавшей в момент запуска оператора или транзакции.

    • Прочитайте изменения незафиксированных данных.

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

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

Конкретные примеры отношения между блокировками и уровнями изоляции в SQL Server (используйте 2PL, кроме READ_COMMITED с READ_COMMITTED_SNAPSHOT = ON)

  • READ_UNCOMMITED: не выдавайте блокировки общего доступа, чтобы другие транзакции не изменяли данные, прочитанные текущей транзакцией. READ UNCOMMITTED транзакции также не блокируются эксклюзивными блокировками, которые помешали бы текущей транзакции считывать строки, которые были изменены, но не были совершены другими транзакциями. [...]

  • READ_COMMITED:

    • Если для READ_COMMITTED_SNAPSHOT установлено значение ВЫКЛ (по умолчанию): использует общие блокировки, чтобы другие транзакции не изменяли строки, в то время как текущая транзакция выполняет операцию чтения. Совлокальные блокировки также блокируют оператор из чтения строк, измененных другими транзакциями, до тех пор, пока другая транзакция не будет завершена. [...] Блокировки строк освобождаются до обработки следующей строки. [...]
    • Если для параметра READ_COMMITTED_SNAPSHOT установлено значение ON, то Database Engine использует управление версиями строк для представления каждого оператора с транзакционным согласованным моментальным снимком данных, как он существовал в начале инструкции. Замки не используются для защиты данных от обновлений другими транзакциями.
  • REPETEABLE_READ: общие блокировки размещаются во всех данных, считываемых каждым оператором в транзакции и сохраняются до завершения транзакции.

  • SERIALIZABLE: Блокировки диапазона помещаются в диапазон значений ключей, которые соответствуют условиям поиска для каждого оператора, выполняемого в транзакции. [...] Блокировки диапазона сохраняются до завершения транзакции.

Ответ 3

Блокировки всегда выполняются на уровне БД: -

Официальный документ Oracle: - Чтобы избежать конфликтов во время транзакции, СУБД использует блокировки, механизмы блокировки доступа других к данным, к которым осуществляется транзакция. (Обратите внимание, что в режиме автоматической фиксации, где каждый оператор является транзакцией, блокировки сохраняются только для одного оператора.) После того, как блокировка установлена, она остается в силе до тех пор, пока транзакция не будет выполнена или откат. Например, СУБД может блокировать строку таблицы до тех пор, пока не будут зафиксированы ее обновления. Эффект этой блокировки будет заключаться в том, чтобы предотвратить доступ пользователя к грязному чтению, то есть к чтению значения до того, как он станет постоянным. (Доступ к обновленному значению, которое не было зафиксировано, считается грязным, потому что это можно вернуть к его предыдущему значению. Если вы прочитаете значение, которое позже будет отменено, вы будете читать недопустимое значение. )

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

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