Уровень изоляции транзакции: установить уровень изоляции таблицы по-разному

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

Transaction: READ_COMMITTED
Table Foo: READ_UNCOMMITTED

Например, генератор идентификаторов таблицы JPA

     Entity Type      Next Id
----------------------------------
     EMP                100
     DEPT               5

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

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

Как насчет Mysql, Oracle db, SqlServer?

1 ответ

Решение

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

Использование READ_UNCOMMITTED не решит вашу проблему.

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

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

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

Именно по этой причине все бренды СУБД имеют возможность генерировать значения идентификаторов вне области транзакции.

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

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

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

Другие вопросы по тегам