面試官:MySQL 唯一索引為什么會導致死鎖?
閱讀本文大概需要 4 分鐘。
來自:cnblogs.com/hongdada/p/9970176.html
唯一性索引unique影響
唯一性索引表創(chuàng)建
DROP TABLE IF EXISTS `sc`;
CREATE TABLE `sc` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) CHARACTER SET utf8 DEFAULT NULL,
`class` varchar(200) CHARACTER SET utf8 DEFAULT NULL,
`score` int(11) DEFAULT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`create_user_id` bigint(11) DEFAULT NULL COMMENT '創(chuàng)建人id',
`modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改時間',
`modify_user_id` bigint(11) DEFAULT NULL COMMENT '最后修改人id',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='學生信息表';
在其中創(chuàng)建了唯一索引name,就是說這個學生表同名的學生只能由一位。
alter table sc add unique (name);
alter table sc add unique key `name_score` (`name`,`score`);
alter table sc drop index `name`;
唯一性索引作用
insert into sc (name,class,score) values ('呂布','一年二班',67);
insert into sc (name,class,score) values ('趙云','一年二班',90);
insert into sc (name,class,score) values ('典韋','一年二班',89);
insert into sc (name,class,score) values ('關羽','一年二班',70);
show create table sc;
CREATE TABLE `sc` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) CHARACTER SET utf8 DEFAULT NULL,
`class` varchar(200) CHARACTER SET utf8 DEFAULT NULL,
`score` int(11) DEFAULT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`create_user_id` bigint(11) DEFAULT NULL COMMENT '創(chuàng)建人id',
`modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改時間',
`modify_user_id` bigint(11) DEFAULT NULL COMMENT '最后修改人id',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='學生信息表';
insert into sc (name,class,score) values ('呂布','二年二班',77)
> 1062 - Duplicate entry '呂布' for key 'name'
> 時間: 0.01s
unique除了在插入重復數據的時候會報錯,還會使auto_increment自動增長
unique與primary key的區(qū)別
(1) 唯一性約束所在的列允許空值,但是主鍵約束所在的列不允許空值。 (2) 可以把唯一性約束放在一個或者多個列上,這些列或列的組合必須有唯一的。但是,唯一性約束所在的列并不是表的主鍵列。 (3) 唯一性約束強制在指定的列上創(chuàng)建一個唯一性索引。在默認情況下,創(chuàng)建唯一性的非聚簇索引,但是,也可以指定所創(chuàng)建的索引是聚簇索引。 (4) 建立主鍵的目的是讓外鍵來引用. (5) 一個表最多只有一個主鍵,但可以有很多唯一鍵
存在唯一鍵沖突時,避免策略
insert ignore
insert ignore into sc (name,class,score) values ('呂布','二年二班',77)
replace into
replace into 首先嘗試插入數據到表中。如果發(fā)現表中已經有此行數據(根據主鍵或者唯一索引判斷)則先刪除此行數據,然后插入新的數據,否則,直接插入新數據。 使用replace into,你必須具有delete和insert權限
replace into sc (name,class,score) values ('呂布','二年二班',77);
insert on duplicate key update
如果在insert into 語句末尾指定了on duplicate key update,并且插入行后會導致在一個UNIQUE索引或PRIMARY KEY中出現重復值,則在出現重復值的行執(zhí)行UPDATE;如果不會導致重復的問題,則插入新行,跟普通的insert into一樣。 使用insert into,你必須具有insert和update權限 如果有新記錄被插入,則受影響行的值顯示1;如果原有的記錄被更新,則受影響行的值顯示2;如果記錄被更新前后值是一樣的,則受影響行數的值顯示0
insert into sc (name,class,score) values ('關羽','二年二班',80) on duplicate key update score=100;
> Affected rows: 2
> 時間: 0.008s
4 關羽 一年二班 100 2018-11-16 15:32:18 2018-11-16 15:51:51
死鎖

1、盡量對存在多個唯一鍵的table使用該語句 2、在有可能有并發(fā)事務執(zhí)行的insert 的內容一樣情況下不使用該語句
結論:
這三種方法都能避免主鍵或者唯一索引重復導致的插入失敗問題。 insert ignore能忽略重復數據,只插入不重復的數據。 replace into和insert … on duplicate key update,都是替換原有的重復數據,區(qū)別在于replace
推薦閱讀:
給你看個寶貝:GitHub 最野的開源庫,把你拿捏的死死的。。。
最近面試BAT,整理一份面試資料《Java面試BATJ通關手冊》,覆蓋了Java核心技術、JVM、Java并發(fā)、SSM、微服務、數據庫、數據結構等等。
朕已閱 

