Серия сотен вопросов Mysql: что такое фантомное чтение?

MySQL

вопрос:

1. Какая ситуация называется фантомным чтением?
2. Можно ли предотвратить фантомное чтение при уровне изоляции повторяющегося чтения Mysql?
3. Что такое текущее чтение и что такое чтение моментального снимка?

Определение фантомного чтения:

Транзакция А считывает данные по определенным условиям, при этом транзакция Б вставляет новые данные с теми же условиями поиска, а когда транзакция А снова читает по исходным условиям, находит транзакцию Б新插入的数据 称为幻读

Если транзакция A выполняет поиск в соответствии с определенными условиями, транзакция B удаляет определенную часть данных, которая соответствует условиям, в результате чего при повторном чтении транзакцией A становится на одну единицу данных меньше. Этот случай классифицируется как неповторяющееся чтение

Готов к работе:

Уровень изоляции Mysql可重复读;

CREATE TABLE `author` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

INSERT into author VALUES (1,'g1',20),(5,'g5',20),(15,'g15',30),(20,'g20',30);

Найдите авторов, которым исполнилось 20 лет, и измените их имена на G0.

время Session 1 Session2
begin;
T1 select * from author where age = 20;
Результат: (1,g1,20),(5,g5,20)
T2 INSERT into author VALUES (25,'g25',20);
T3 select * from author where age = 20;
Результат: (1,g1,20),(5,g5,20)
T4 update author set name = 'G0' where age = 20
Результат: количество затронутых строк отображается как 3 строки.
T5 select * from author where age = 20;
Результат: (1,g0,20),(5,g0,20),(25,g0,20)

Проанализируем следующую ситуацию:

  1. В T1 считываются данные возраста 20, и Session1 получает 2 записи.
  2. В момент времени T2 другой процесс Session2 вставил новую запись с возрастом 20 лет.
  3. При времени T3 Session1 считывает данные, возраст которых снова составляет 20 и обнаруживает, что есть еще 2 штуки данных.貌似Вновь вставленные данные Session2 не влияют на чтение транзакции Session1.

Для ситуации в момент времени Т1 -- Т3, по результатам, в可重复度读Кажется, это решается на уровне изоляции幻读Проблема.

  1. На этапе T4 Session1 изменяет данные, возраст которых равен 20, и обнаруживает, что количество затронутых строк равно 3. Почему в T3 можно найти только 2 фрагмента данных, а сейчас изменены 3 фрагмента данных?
  2. На T5 сеанс 1 снова считывает данные с возрастом 20 и обнаруживает, что результат стал равным 3. Мы знаем, что третий модифицированный — это тот, который был добавлен сеансом 2 на момент времени T2.

По результатам T4 и T5 Session1 прочитал данные, недавно вставленные Session2. произведено幻读Феномен

В конце концов, при уровне изоляции повторяющегося чтения была ли решена проблема фантомного чтения?

Учащиеся, знакомые с MVCC, должны знать или слышать о нем.当前读,а также快照读。(Студенты, которые не знают, вы можете найти соответствующую информацию для понимания, конечно, в продолжении у меня будет статья, посвященная MVCC).
Первое, что нужно знать, это способность MVCC создавать моментальные снимки данных за считанные секунды в InnoDB.快照读То есть при чтении данных данные видимой версии транзакции будут считываться по определенным правилам. а также当前读Просто прочитайте последнюю версию данных.
При каких обстоятельствах используется чтение моментального снимка: (чтение моментального снимка, без блокировки)

Общий оператор select * from .... где ... - это прочитанный снимок

При каких обстоятельствах используется текущее чтение: (текущее чтение будет заблокировано при поиске)

select * from .... where  ... for update select * from .... where  ... lock in share mode update .... set .. where ... delete from. . where ..

如果事务中都使用快照读,那么就不会产生幻读现象,但是快照读和当前读混用就会产生幻读。

Если используется текущее чтение, можно ли решить проблему фантомного чтения?

Давайте сначала восстановим данные в исходное состояние

TRUNCATE TABLE author;
INSERT into author VALUES (1,'g1',20),(5,'g5',20),(15,'g15',30),(20,'g20',30);
время Session 1 Session2
begin;
T1 select * from author where age = 20 for update;
Результат: (1,g1,20),(5,g5,20)
T2 INSERT into author VALUES (25,'g25',20);
блокировка, ожидание блокировки
T3 select * from author where age = 20 for update;
Результат: (1,g1,20),(5,g5,20)

Вы можете видеть, что сеанс 2 заблокирован. Необходимо дождаться, пока Session1 зафиксирует транзакцию для завершения. Когда мы используем каждое чтение в транзакции, используя当前读, то есть вручную превращая InnoDB в串行化. Это в определенной степени снижает параллелизм, но также позволяет избежать фантомных чтений.
Почему текущий прочитал блокировать вставку новых данных, в основном потому, что间隙锁запорный механизм. (MysqlЭто тоже большая проблема, и в продолжении будет отдельная глава)

Суммировать:

  • Я надеюсь, что благодаря этой статье я смогу понять определение галлюцинаций. читать другие транзакции新插入的数据, это явление называется фантомным чтением.
  • Разница между текущим чтением и чтением моментального снимка, а также знание того, когда происходит чтение моментального снимка, а когда текущее чтение.
  • Под повторямым уровнем изоляции чтения только текущий чтение или только снимка можно использовать в транзакции, чтобы избежать чтения Phantom.