先說一下前提,我的mysql是使用的5.6版本,隔離級別是RR。
表結構
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`c` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `t` VALUES ('0', '0');
INSERT INTO `t` VALUES ('20', '20');
INSERT INTO `t` VALUES ('25', '25');
一.先放兩組SQL。c並沒有索引
(1)begin;
update t set c=1 where c=0;
(2)begin;
insert into t values(1,1);
這個時候無論你先執行哪組語句,後面的語句都會阻塞,那麼我們就分析一下原因。
二.分析原因
假設我們先執行(1)組,那麼這個時候,update語句的原理都是先刪除再插入,那麼就有兩種可能了,第一種是delete的時候會產生阻塞、第二種是insert的時候會產生阻塞,那就只能通過實際的操作來反應一下情況了。
我們使用如下SQL。
(1)begin;
delete from t where c=0;
(2)begin;
insert into t values(1,1);
這個時候已經產生了阻塞。那麼找一下原因:
(1)delete語句會產生鎖,由於c這個字段沒有索引,所以無法直接對索引進行加鎖,就會導致表鎖。
(2)而這個時候,insert語句進來,就會等待表鎖的釋放。
(假設c這個字段有索引的話,那麼c=0這一個條件就會讓delete鎖定索引,只要和insert不衝突就不會存在阻塞的情況)