@AlexeyK77Ну вообще же ребята неверно. Откуда только что берете? Во - первых, не "Phantom read", а "Phantom". Это уже потом выводится, что "Phantom" это "read" Во - вторых, "NON-repeatable read" это про Update/Delete. "Phantom" это "INSERT" Все эти определения идут от Стандарта ISO/IEC 9075, согласно нему(стр84): P2 (‘‘Non-repeatable read’’): SQL-transaction T1 reads a row. SQL-transaction T2 then modifies or deletes that row P3 (‘‘Phantom’’): SQL-transaction T1 reads the set of rows N that satisfy some . SQL-transaction T2 then executes SQL-statements that generate one or more rows
Все верно автор говорит. Смотрим в Стандарт 92: ‘‘Non-repeatable read’’ : SQL-transaction T1 reads a row. SQL-transaction T2 then modifies or deletes that row and performs a COMMIT. (UPDATE|DELETE) ‘‘Phantom’’ : SQL-transaction T2 then executes SQL-statements that generate one or more rows that satisfy the used by SQL-transaction T1 (INSERT)
Сами-то уровни будут работать одинаково (как им предписано стандартом),
И даже не так. Взять, к примеру, Oracle. В Стандарте 92 сказано: "The execution of concurrent SQL-transactions at isolation level SERIALIZABLE is guaranteed to be serializable. A serializable execution is defined to be an execution of the operations of concurrently executing SQL-transactions that produces the same effect as some serial execution of those same SQL-transactions." Но если взять аномалию Write Skew, то она на этом уровне Oracle не предотвращается. Т.е. де - факто, Oracle не соответствует Стандарту. Даже у Кайта написано: "Уровень изолированности SERIALIZABLE не означает, что все пользовательские транзакции дают такой же результат, как и при последовательном выполнении"
В MS SQL лучше (с точки зрения корректности данных и отсутствия взаимоблокировок) в пишущей транзакции для тех таблиц, которые меняются в данной транзакции использовать как можно раньше serializable.
Слишком общее утверждение. В зависимости от задачи. К примеру, тот же Skewed Write не происходит и на уровне Read Committed
И главное - тестирование. Тестирование того, как себя поведут запросы при конкурентном доступе. Во многих IDE можно открыть две консоли соединения с сервером СУБД, в том же IDEA и VSCCODE. Либо на худой конец косольную утилиту вроде psql.
Очень суженый взгляд на уровень Repeatable Read. Лучше бы просто было написать про то, какие уровни какие аномалии должны предотвращать. Но вы начали писать про то, как они это делают. И тут вступили на хрупкий лед. В классическом понимании с блокировками - а что это за классическое понимание такое? Если говорим про блокировки - сделал SELECT FOR UPDATE <диапазон> в Mysql на уровне Repeatable read - проблема фантомов решена. Предикатная блокировка, она же gap lock/Next-Key Locks в Mysql - не даст вставить в диапазон новые строки Далее,
Вторая транзакция заблокируется на `SELECT balance...`, пока первая не сделает commit/rollback.REPEATABLE READ блокирует любой доступ к строке, пока транзакция лок не отпустит.
Надо наверное уточнить, в какой СУБД так делается? А именно, SQL SERVER. MYSQL, PosgreSQL, Oracle так не делают, а как раз - таки роняют одну из транзакций
Не совсем понимаю логику gap locks в плане предотвращения фантомов. Вот зачем? На мой взгляд, такой подход только вредит производительности. Не так сильно, как SQL Server конечно, но те же PostgreSQL и Oracle подощли к этому, на мой взгляд, лучше. Потому что есть два конкретных инструмента - MVCC или снимки данных и предикатная блокировка. Предикатная блокировка в смысле такой блокировки определенного промежутка данных, при которой попытка выполнить команду Insert в другой транзакции заблокируется. PostgreSQL подобный подход не использует, как и Oracle. Потому что есть два разных понятия - 1) Возникновение фантома 2) Чтение фантома И аномалия то, согласно Стандарту ISO/IEC 9075 - как раз таки чтение фантома Так что необходимости использовать gap lock я не вижу совершенно. Как и Next-Key Locks
PostgreSQL в такой ситуации оборвет одну из транзакций при попытке фиксации
Не совсем понял, про какую ситуацию речь. Мы же про INSERT|SELECT транзакции говорили в рамках Repeatable Read. Когда PostgreSQL оборвет одну из транзакций при попытке фиксации?
Вообще говоря, картинка Рис. 2.17. двойственная. С одной стороны, read uncommitted в PostgreSQL все - таки реализован, хотя по поведению соответствует уровню Read committed. Но его можно установить как уровень изоляции. А вот в Oracle попытка его установить приведет к ошибке. Если рассуждать с позиций соответствия Стандарту, то read uncommitted в PostgreSQL как раз - таки снова соответствует Стандарту, т.к. в Стандарте определяются аномалии, которые должны отсутствовать на определенном уровне изоляции. И грязная запись на нем отсутствует. А вот как - раз таки Oracle со своим уровнем изоляции Serializable Стандарту не соответствует, т.к. не препятствует аномалии Write Skew, которая попадает под категорию "Другие" по Рис. 2.16. Но это если придираться. А для понимания новичками я бы оставил Рис. 2.17 как есть, в целом он правильный
До реализации таких блокировок в какой-либо системе дело, насколько мне известно, не дошло
А как насчет gap lock и Next-Key Locks в Mysql? Не являются ли они по сути теми же предикатными блокировками? К примеру, установим уровень изоляции Repeatable Read. И возьмем две транзакции в разных сессиях: 1) SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN; Select amount from invoices WHERE id BETWEEN 10 and 30 FOR UPDATE; COMMIT; 2) SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN; INSERT INTO invoices(id, user_id, amount) VALUES (15, 2, 15); COMMIT; Выполним Select в первой транзакции, затем - Insert во второй В PostgreSQL никакой блокировки не будет. В Mysql же Insert заблокируется. Хотя опять же непонятно, если Mysql реализует честный MVCC, то зачем ему вообще такого рода блокировки. Насчет Serializable не проверял, но на уровне Read Committed уже Insert отработает По определению, данному в этой статье вот очень похоже на предикатную блокировку.
На мой взгляд не хватает конкретных примеров использования рекомендательных блокировок. Это вообще класс явных блокировок, с которым у меня возникли наибольшие сложности в понимании. Т.е. даже после прочтения документации все равно неясно, в каких случаях разработчику приложения может понадобится такой тип блокировок
Да, совершенно верно, пропустил этот момент в Стандарте. Serializable - это уровень изоляции, на котором результат выполнения операций должен быть такой, как будто операции выполнялись последовательно. Т.е. никакие аномалии на нем действительно не должны допускаться.
Стандарт определяет и еще один уровень — Serializable, — на котором не допускаются никакие аномалии. И это совсем не то же самое, что запрет на потерянное обновление и на грязное, неповторяющееся и фантомное чтения.
А так ли это? Можно цитату из стандарта, где это прямо говорится? Четкое указание и домыслы - разные вещи. Я думаю, что согласно Стандарту, Serializable - это как раз - таки уровень, на котором не допускаются грязное, неповторяющееся и фантомное чтение. И не более того. Т.е. все как раз - таки vice versa, наоборот. Надо быть осторожным в этом плане с домыслами. Приведу пример: Как - то встретил утверждение, что "Serializable - это уровень изоляции, на котором результат выполнения операций, согласно Стандарту ISO/IEC 9075, должен быть такой, как будто операции выполнялись последовательно. Поэтому де-факто Oracle не соответствует стандарту". Но на поверку говоривший не смог найти подобное утверждение в Стандарте, т.е. это утверждение оказалось не более, чем домысл
Если так трактовать стандарт, то получается, что ни одна СУБД не соответствует Стандарту ISO/IEC 9075 - по крайней мере, SQL SERVER, MySQL, Oracle и PostgreSQL, кстати, тоже. Вообще удивительно, как одно предложение может по - разному трактоваться. Здесь буду отталкиваться от статьи A Critique of ANSI SQL Isolation Levels https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf. Согласно которой - Lost Update - new phenomena, не упоминаемая в Стандарте, т.е. данное предложение
Ну, воображение он точно помогает развить))
Это же он сказал в Государе:
"ибо люди всегда дурны, пока их не принудит к добру необходимость" ? (:
@AlexeyK77Ну вообще же ребята неверно. Откуда только что берете? Во - первых, не "Phantom read", а "Phantom". Это уже потом выводится, что "Phantom" это "read"
Во - вторых, "NON-repeatable read" это про Update/Delete.
"Phantom" это "INSERT"
Все эти определения идут от Стандарта ISO/IEC 9075, согласно нему(стр84):
P2 (‘‘Non-repeatable read’’): SQL-transaction T1 reads a row. SQL-transaction T2 then modifies or deletes that row
P3 (‘‘Phantom’’): SQL-transaction T1 reads the set of rows N that satisfy some . SQL-transaction T2 then executes SQL-statements that generate one or more rows
Статья получилась бы намного большой в объеме и сложной в написании
Все верно автор говорит.
Смотрим в Стандарт 92:
‘‘Non-repeatable read’’ : SQL-transaction T1 reads a row. SQL-transaction T2 then modifies or deletes that row and performs a COMMIT. (UPDATE|DELETE)
‘‘Phantom’’ : SQL-transaction T2 then executes SQL-statements that generate one or more rows that satisfy the used by SQL-transaction T1 (INSERT)
И даже не так. Взять, к примеру, Oracle. В Стандарте 92 сказано: "The execution of concurrent SQL-transactions at isolation level SERIALIZABLE is guaranteed to be serializable. A serializable execution is defined to be an execution of the operations of concurrently executing SQL-transactions that produces the same effect as some serial execution of those same SQL-transactions."
Но если взять аномалию Write Skew, то она на этом уровне Oracle не предотвращается. Т.е. де - факто, Oracle не соответствует Стандарту. Даже у Кайта написано: "Уровень изолированности SERIALIZABLE не означает, что все пользовательские транзакции дают такой же результат, как и при последовательном выполнении"
Слишком общее утверждение. В зависимости от задачи. К примеру, тот же Skewed Write не происходит и на уровне Read Committed
И главное - тестирование. Тестирование того, как себя поведут запросы при конкурентном доступе. Во многих IDE можно открыть две консоли соединения с сервером СУБД, в том же IDEA и VSCCODE. Либо на худой конец косольную утилиту вроде psql.
Уверены? А в какой СУБД? Обычный
SELECT balance FROM users WHERE id = 1;
блочит всю таблицу целиком? Это где вообще такое есть?Никакой конкретики
Очень суженый взгляд на уровень Repeatable Read. Лучше бы просто было написать про то, какие уровни какие аномалии должны предотвращать.
Но вы начали писать про то, как они это делают. И тут вступили на хрупкий лед.
В классическом понимании с блокировками - а что это за классическое понимание такое? Если говорим про блокировки - сделал SELECT FOR UPDATE <диапазон> в Mysql на уровне Repeatable read - проблема фантомов решена. Предикатная блокировка, она же gap lock/Next-Key Locks в Mysql - не даст вставить в диапазон новые строки
Далее,
Надо наверное уточнить, в какой СУБД так делается? А именно, SQL SERVER. MYSQL, PosgreSQL, Oracle так не делают, а как раз - таки роняют одну из транзакций
Не совсем понимаю логику gap locks в плане предотвращения фантомов. Вот зачем? На мой взгляд, такой подход только вредит производительности. Не так сильно, как SQL Server конечно, но те же PostgreSQL и Oracle подощли к этому, на мой взгляд, лучше.
Потому что есть два конкретных инструмента - MVCC или снимки данных и предикатная блокировка. Предикатная блокировка в смысле такой блокировки определенного промежутка данных, при которой попытка выполнить команду Insert в другой транзакции заблокируется.
PostgreSQL подобный подход не использует, как и Oracle.
Потому что есть два разных понятия - 1) Возникновение фантома 2) Чтение фантома
И аномалия то, согласно Стандарту ISO/IEC 9075 - как раз таки чтение фантома
Так что необходимости использовать gap lock я не вижу совершенно. Как и Next-Key Locks
Понятней не стало, но на всякий случай буду знать, что такие блокировки есть)
Да, это хорошо показано в вашей статье
Не совсем понял, про какую ситуацию речь. Мы же про INSERT|SELECT транзакции говорили в рамках Repeatable Read. Когда PostgreSQL оборвет одну из транзакций при попытке фиксации?
Вообще говоря, картинка Рис. 2.17. двойственная. С одной стороны, read uncommitted в PostgreSQL все - таки реализован, хотя по поведению соответствует уровню Read committed. Но его можно установить как уровень изоляции. А вот в Oracle попытка его установить приведет к ошибке.
Если рассуждать с позиций соответствия Стандарту, то read uncommitted в PostgreSQL как раз - таки снова соответствует Стандарту, т.к. в Стандарте определяются аномалии, которые должны отсутствовать на определенном уровне изоляции. И грязная запись на нем отсутствует.
А вот как - раз таки Oracle со своим уровнем изоляции Serializable Стандарту не соответствует, т.к. не препятствует аномалии Write Skew, которая попадает под категорию "Другие" по Рис. 2.16.
Но это если придираться. А для понимания новичками я бы оставил Рис. 2.17 как есть, в целом он правильный
А как насчет gap lock и Next-Key Locks в Mysql? Не являются ли они по сути теми же предикатными блокировками?
К примеру, установим уровень изоляции Repeatable Read.
И возьмем две транзакции в разных сессиях:
1)
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
Select amount from invoices WHERE id BETWEEN 10 and 30 FOR UPDATE;
COMMIT;
2) SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
INSERT INTO invoices(id, user_id, amount) VALUES (15, 2, 15);
COMMIT;
Выполним Select в первой транзакции, затем - Insert во второй
В PostgreSQL никакой блокировки не будет.
В Mysql же Insert заблокируется.
Хотя опять же непонятно, если Mysql реализует честный MVCC, то зачем ему вообще такого рода блокировки. Насчет Serializable не проверял, но на уровне Read Committed уже Insert отработает
По определению, данному в этой статье вот очень похоже на предикатную блокировку.
На мой взгляд не хватает конкретных примеров использования рекомендательных блокировок.
Это вообще класс явных блокировок, с которым у меня возникли наибольшие сложности в понимании.
Т.е. даже после прочтения документации все равно неясно, в каких случаях разработчику приложения может понадобится такой тип блокировок
Да, совершенно верно, пропустил этот момент в Стандарте. Serializable - это уровень изоляции, на котором результат выполнения операций должен быть такой, как будто операции выполнялись последовательно. Т.е. никакие аномалии на нем действительно не должны допускаться.
А так ли это? Можно цитату из стандарта, где это прямо говорится? Четкое указание и домыслы - разные вещи.
Я думаю, что согласно Стандарту, Serializable - это как раз - таки уровень, на котором не допускаются грязное, неповторяющееся и фантомное чтение. И не более того. Т.е. все как раз - таки vice versa, наоборот.
Надо быть осторожным в этом плане с домыслами. Приведу пример: Как - то встретил утверждение, что "Serializable - это уровень изоляции, на котором результат выполнения операций, согласно Стандарту ISO/IEC 9075, должен быть такой, как будто операции выполнялись последовательно. Поэтому де-факто Oracle не соответствует стандарту". Но на поверку говоривший не смог найти подобное утверждение в Стандарте, т.е. это утверждение оказалось не более, чем домысл
Если так трактовать стандарт, то получается, что ни одна СУБД не соответствует Стандарту ISO/IEC 9075 - по крайней мере, SQL SERVER, MySQL, Oracle и PostgreSQL, кстати, тоже.
Вообще удивительно, как одно предложение может по - разному трактоваться.
Здесь буду отталкиваться от статьи A Critique of ANSI SQL Isolation Levels https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf. Согласно которой - Lost Update - new phenomena, не упоминаемая в Стандарте, т.е. данное предложение
Было трактовано неправильно и в статье неточность
Вот, к примеру https://www.sao.ru/hq/zhe/DDBMS/book/KyteOracleTips.pdf - страница 150, блокировки транзакций