Что означает уровень изоляции транзакций REPEATABLE_READ?

Ответ

REPEATABLE_READ — это уровень изоляции транзакций, который гарантирует, что если транзакция повторно читает одни и те же данные, она получит идентичный результат. Он предотвращает Dirty Reads и Non-repeatable Reads, но может допускать Phantom Reads.

Характеристики и проблемы:

  • Предотвращает:
    • Dirty Read.
    • Non-repeatable Read.
  • Допускает:
    • Phantom Read: Транзакция может увидеть новые строки, добавленные другими зафиксированными транзакциями после ее начала.

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

Практический пример:

-- Транзакция 1 (уровень REPEATABLE_READ)
BEGIN TRANSACTION;
SELECT COUNT(*) FROM users WHERE active = true; -- Возвращает 5

-- Транзакция 2
BEGIN TRANSACTION;
INSERT INTO users (name, active) VALUES ('NewUser', true);
COMMIT;

-- Транзакция 1 (продолжение)
SELECT COUNT(*) FROM users WHERE active = true; -- Все еще возвращает 5 (Phantom Read предотвращен в некоторых СУБД)
UPDATE users SET active = false WHERE active = true; -- Может заблокировать больше строк, чем ожидалось
COMMIT;

Важно: В MySQL (с движком InnoDB) и некоторых других СУБД реализация REPEATABLE_READ с использованием механизма snapshot также предотвращает Phantom Reads за счет использования next-key locks. В PostgreSQL и Oracle этот уровень эквивалентен SERIALIZABLE в смысле snapshot изоляции.

Ответ 18+ 🔞

А, слушай, вот эта ваша REPEATABLE_READ, ну, блядь, классика жанра, ебать мои старые костыли! Представь, ты в транзакции как будто в зазеркалье застрял. Ты там в начале, блядь, глянул на данные — и всё, пиздец, ты их заморозил для себя, как суп в холодильнике.

Что он, этот уровень, делает, а?

  • От чего спасает: От говённых Dirty Read — чтобы ты чужой, недоделанной хуйни не увидел. И от Non-repeatable Read — чтобы, прочитав строку, ты через секунду не обосрался, потому что она уже другая. Не, тут такого нет.
  • А что может пролезть: А вот Phantom Read, сука, может! Это когда ты два раза считал, сколько у тебя, там, активных юзеров, а между этими чтениями какая-то мартышлюшка нового юзера впихнула и закоммитила. И вот ты в своём мирке, а реальность-то уже другая, блядь!

Как оно, блядь, работает? Да очень просто! Транзакция, как только первое чтение сделала — хвать! — и сделала себе снимок данных на этот момент. И всё, дальше она живёт в этой фотографии, как в матрице. Хоть весь мир вокруг гори синим пламенем и обновляется — ей похуй. Она в своём 2007-м году осталась, блядь.

Ну и примерчик, чтобы совсем пизда:

-- Транзакция 1 (сидит на REPEATABLE_READ, как на троне)
BEGIN TRANSACTION;
SELECT COUNT(*) FROM users WHERE active = true; -- Видит, ну, скажем, 5 штук. Запомнил.

-- Транзакция 2 (какая-то шустрая пидораска)
BEGIN TRANSACTION;
INSERT INTO users (name, active) VALUES ('НовыйРаспиздяй', true); -- Впихнула нового!
COMMIT; -- И похвалилась!

-- Транзакция 1 (просыпается, ни хуя не подозревая)
SELECT COUNT(*) FROM users WHERE active = true; -- А ей всё ещё 5 показывает! Снимок, блядь, старый!
UPDATE users SET active = false WHERE active = true; -- А вот тут, сука, может быть сюрприз! Если СУБД хитрая, она может больше строк заблокировать, чем в её снимке было!
COMMIT;

А вот тут, ёпта, внимание, блядь, важный момент! Это ж как в политике — у всех своя правда. В MySQL (с этим ихним InnoDB) они такие хитрожопые, что их REPEATABLE_READ за счёт каких-то там next-key locks и фантомные чтения в жопу посылает. А в PostgreSQL или Oracle — так это вообще почти SERIALIZABLE получается, тоже на снепшотах. Короче, читай мануал, а не тупи, как Герасим, который только «Му-му» и мог сказать!