CREATE TABLE 'z' (
'a' int(11) NOT NULL,
'b' int(11) DEFAULT NULL,
PRIMARY KEY ('a'),
KEY 'b' ('b')
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO 'test'.'z' ('a', 'b') VALUES (1, 1);
INSERT INTO 'test'.'z' ('a', 'b') VALUES (3, 1);
INSERT INTO 'test'.'z' ('a', 'b') VALUES (5, 3);
INSERT INTO 'test'.'z' ('a', 'b') VALUES (7, 6);
INSERT INTO 'test'.'z' ('a', 'b') VALUES (10, 8);
INSERT INTO 'test'.'z' ('a', 'b') VALUES (20, 30);
INSERT INTO 'test'.'z' ('a', 'b') VALUES (50, 60);
INSERT INTO 'test'.'z' ('a', 'b') VALUES (45, 90);
INSERT INTO 'test'.'z' ('a', 'b') VALUES (2, 99);
transaction_isolation = REPEATABLE-READ
tx_isolation = REPEATABLE-READ
СЕССИЯ 1
начать;
выберите * from z, где b = 60 для обновления;
СЕССИЯ 2
начать;
вставить в z выбрать 4, 90; /* почему это невозможно вставить? */
ERROR 1205 (HY000): превышено время ожидания блокировки; попробуйте перезапустить транзакцию
вставить в z выбрать 46, 90; /* Но это можно вставить? */
Запрос ОК, 1 строка затронута (0.00 сек)
Записи: 1 Дубликаты: 0 Предупреждения: 0
Как вышеописанный шаг: можно вставить, но другого не может быть. они имеют одинаковое значение - 90.
Да, это зазор.
Эти две вставки на самом деле не пытаются вставить одно и то же значение, поскольку вторичные индексы также сохраняют копию первичного ключа в конце (это то, как поиск индекса находит исходную строку, если на столбцы ссылаются больше, чем в индексе).
В индексе b
строки, о которых идет речь, будут отсортированы следующим образом.
b a
60, 50
90, 4
90, 45
90, 46
Из этой иллюстрации видно, что (4,90) принадлежит в промежутке сразу после (60,50), но (46,90) находится не в этом промежутке.