В этой статье в основном рассказывается о том, как отладить исходный код MySQL, чтобы узнать, какие блокировки SQL действительно возьмет, чтобы перестать ловить креветок, угадывать или не знать, как поступать со сценариями, которые Бог Хэ Дэнчэн не написал.
После многих сложных одноэтапных отладок посреди ночи я наконец нашел идеальную точку останова и могу видеть большую часть процесса получения блокировок.
код находится вlock0lock.cизstatic enum db_err lock_rec_lock()В функции эта функция будет отображать процесс получения блокировки и успешность получения блокировки.
Для содержания предыдущего блога He Dengcheng (hedengcheng.com/?p=771), давайте проведем эксперименты для проверки один за другим (далее все эксперименты под уровнем изоляции RC)
Сценарий 1: удаление по первичному ключу
Структура таблицы
CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
delete from t1 where id = 10;
Как видите, индекс PRIMARY заблокирован, mode=1027, что значит 1027? 1027 = LOCK_REC_NOT_GAP + LOCK_X (блокировка записи без пробелов и блокировка X)
Процесс выглядит следующим образом
Сценарий 2: Удаление по уникальному индексу
Структура таблицы была доработана, добавлен уникальный индекс для имени
构造数据
CREATE TABLE `t2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`name`)
) ;
INSERT INTO `t2` (`id`, `name`) VALUES
(1,'M'),
(2,'Y'),
(3,'S'),
(4,'Q'),
(5,'L');
测试sql语句
delete from t2 where name = "Y"
Посмотрите на результаты фактической отладки исходного кода первый шаг:
Процесс выглядит следующим образом
Сценарий 3: Удалить через обычный индекс
构造数据
CREATE TABLE `t3` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`)
);
INSERT INTO `t3` (`id`, `name`) VALUES
(1,'N'),
(2,'G'),
(3,'I'),
(4,'N'),
(5,'X');
测试语句:
delete from t3 where name = "N";
Процесс отладки показан на рисунке:
Вывод: При обновлении через обычный индекс все普通索引Добавьте замок X, и в то же время связанный с ним主键索引Добавить X-замок
Процесс выглядит следующим образом
Сценарий 4: Удалить без просмотра индекса
CREATE TABLE `t4` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
)
INSERT INTO `t4` (`id`, `name`) VALUES
(1,'M'),
(2,'Y'),
(3,'S'),
(4,'Q'),
(5,'L');
delete from t4 where name = "S";
Вывод: При обновлении без прохождения индекса sql пойдет聚簇索引(индекс первичного ключа) сканирует всю таблицу, поэтому каждая запись, независимо от того, соответствует ли она условиям, будет заблокирована с помощью X. Это еще не конец...
Однако ради эффективности MySQL был оптимизирован.Для записей, которые не соответствуют условиям, блокировка будет снята после вынесения решения.Последнее удержание - это блокировка записи, которая соответствует условию, но блокировка/освобождение для запись, не удовлетворяющая условию, будет задержана, блокировка не будет пропущена.
Процесс выглядит следующим образом