В транзакционной системе с уровнем изоляции READ COMMITTED наблюдается явление неповторяемого чтения и потеря обновления — приведите конкретную последовательность транзакций, демонстрирующую аномалию, и обсудите, какие уровни изоляции или механизмы (MVCC, записи блокировок, сериализация) лучше подходят для OLTP и для аналитических сценариев
Кратко — примерные последовательности и рекомендации. Неповторяемое чтение (READ COMMITTED допускает): Изначально поле balance = 100100100. 111 T1: BEGIN; SELECT balance FROM accounts WHERE id=1; — читает 100100100 222 T2: BEGIN; UPDATE accounts SET balance = balance - 30 WHERE id=1; COMMIT; — теперь 707070 333 T1: SELECT balance FROM accounts WHERE id=1; — читает 707070 (отличается от первого чтения) 444 T1: COMMIT. Потеря обновления (lost update): Изначально balance = 100100100, оба транзакции вычитают по 101010. 111 T1: BEGIN; SELECT balance FROM accounts WHERE id=1; — читает 100100100 222 T2: BEGIN; SELECT balance FROM accounts WHERE id=1; — читает 100100100 333 T1: UPDATE accounts SET balance = 100−10=90100 - 10 = 90100−10=90 WHERE id=1; COMMIT; — пишет 909090 444 T2: UPDATE accounts SET balance = 100−10=90100 - 10 = 90100−10=90 WHERE id=1; COMMIT; — перезаписывает 909090 (эффект: только −10-10−10, а не −20-20−20) Коротко про уровни изоляции и механизмы — что лучше для OLTP и для аналитики: - OLTP (много коротких конкурентных транзакций): - Предпочтение: MVCC или блокировки на уровне строк плюс короткие транзакции. MVCC (snapshot reads) даёт невысокую задержку для чтений; для защищённых изменений использовать явные блокировки (SELECT ... FOR UPDATE) или оптимистичную проверку (compare-and-swap / проверка версии). - Изоляция: часто Read Committed или Snapshot Isolation для производительности; для критической корректности — Repeatable Read или Serializable (или SSI в PostgreSQL), но сериализация дороже по производительности. - Механизмы: row-level locks при высокой конкуренции для предотвращения lost updates; MVCC + retry для высокой конкурентности без блокировки чтений. - Аналитика (долгие читательские запросы, OLAP): - Предпочтение: MVCC с консистентным снимком (snapshot) либо отдельные читающие реплики/OLAP-репозитории. Это позволяет долгим запросам не блокировать писателей. - Изоляция: snapshot / repeatable-read для консистентного вида данных; read-only serializable при необходимости строгой корректности. - Механизмы: избегать блокировок писателей, использовать копии данных/ETL, колонковые хранилища и MPP. Короткое резюме: для OLTP — MVCC + явные блокировки или оптимистичная проверка, иногда Serializable для критичных операций; для аналитики — MVCC snapshot / read replicas (чтобы не блокировать писателей). Serializability полно предотвращает все аномалии, но дорого; Snapshot Isolation предотвращает dirty/non-repeatable reads, но может позволить write skew.
Неповторяемое чтение (READ COMMITTED допускает):
Изначально поле balance = 100100100.
111 T1: BEGIN; SELECT balance FROM accounts WHERE id=1; — читает 100100100
222 T2: BEGIN; UPDATE accounts SET balance = balance - 30 WHERE id=1; COMMIT; — теперь 707070
333 T1: SELECT balance FROM accounts WHERE id=1; — читает 707070 (отличается от первого чтения)
444 T1: COMMIT.
Потеря обновления (lost update):
Изначально balance = 100100100, оба транзакции вычитают по 101010.
111 T1: BEGIN; SELECT balance FROM accounts WHERE id=1; — читает 100100100
222 T2: BEGIN; SELECT balance FROM accounts WHERE id=1; — читает 100100100
333 T1: UPDATE accounts SET balance = 100−10=90100 - 10 = 90100−10=90 WHERE id=1; COMMIT; — пишет 909090
444 T2: UPDATE accounts SET balance = 100−10=90100 - 10 = 90100−10=90 WHERE id=1; COMMIT; — перезаписывает 909090 (эффект: только −10-10−10, а не −20-20−20)
Коротко про уровни изоляции и механизмы — что лучше для OLTP и для аналитики:
- OLTP (много коротких конкурентных транзакций):
- Предпочтение: MVCC или блокировки на уровне строк плюс короткие транзакции. MVCC (snapshot reads) даёт невысокую задержку для чтений; для защищённых изменений использовать явные блокировки (SELECT ... FOR UPDATE) или оптимистичную проверку (compare-and-swap / проверка версии).
- Изоляция: часто Read Committed или Snapshot Isolation для производительности; для критической корректности — Repeatable Read или Serializable (или SSI в PostgreSQL), но сериализация дороже по производительности.
- Механизмы: row-level locks при высокой конкуренции для предотвращения lost updates; MVCC + retry для высокой конкурентности без блокировки чтений.
- Аналитика (долгие читательские запросы, OLAP):
- Предпочтение: MVCC с консистентным снимком (snapshot) либо отдельные читающие реплики/OLAP-репозитории. Это позволяет долгим запросам не блокировать писателей.
- Изоляция: snapshot / repeatable-read для консистентного вида данных; read-only serializable при необходимости строгой корректности.
- Механизмы: избегать блокировок писателей, использовать копии данных/ETL, колонковые хранилища и MPP.
Короткое резюме: для OLTP — MVCC + явные блокировки или оптимистичная проверка, иногда Serializable для критичных операций; для аналитики — MVCC snapshot / read replicas (чтобы не блокировать писателей). Serializability полно предотвращает все аномалии, но дорого; Snapshot Isolation предотвращает dirty/non-repeatable reads, но может позволить write skew.