<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          面試官:MySQL 唯一索引為什么會導(dǎo)致死鎖?

          共 8120字,需瀏覽 17分鐘

           ·

          2021-05-23 20:29

          作者 | hongdada

          來源 | www.cnblogs.com/hongdada/p/9970176.html

          唯一性索引unique影響

          唯一性索引表創(chuàng)建

              DROP TABLE IF EXISTS `sc`;
          CREATE TABLE `sc` (
                                `id` int(11NOT NULL AUTO_INCREMENT,
                                `name` varchar(200CHARACTER SET utf8 DEFAULT NULL,
                                `class` varchar(200CHARACTER SET utf8 DEFAULT NULL,
                                `score` int(11DEFAULT NULL,
                                `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
                                `create_user_id` bigint(11DEFAULT NULL COMMENT '創(chuàng)建人id',
                                `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改時間',
                                `modify_user_id` bigint(11DEFAULT NULL COMMENT '最后修改人id',
                                PRIMARY KEY (`id`),
                                UNIQUE KEY `name` (`name`)
          ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='學(xué)生信息表';
          在其中創(chuàng)建了唯一索引name,就是說這個學(xué)生表同名的學(xué)生只能由一位。
          命令添加unique:

              alter table sc add unique (name);

          alter table sc add unique key `name_score` (`name`,`score`);

          刪除:

              alter table sc drop index `name`;

          唯一性索引作用

          先行插入部分?jǐn)?shù)據(jù):

              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 ('關(guān)羽','一年二班',70);

          再次查看表定義:

              show create table sc;

          CREATE TABLE `sc` (
                                `id` int(11NOT NULL AUTO_INCREMENT,
                                `name` varchar(200CHARACTER SET utf8 DEFAULT NULL,
                                `class` varchar(200CHARACTER SET utf8 DEFAULT NULL,
                                `score` int(11DEFAULT NULL,
                                `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
                                `create_user_id` bigint(11DEFAULT NULL COMMENT '創(chuàng)建人id',
                                `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改時間',
                                `modify_user_id` bigint(11DEFAULT NULL COMMENT '最后修改人id',
                                PRIMARY KEY (`id`),
                                UNIQUE KEY `name` (`name`)
          ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='學(xué)生信息表';

          這時的Auto_Increment=5 再次執(zhí)行sql:

              insert into sc (name,class,score) values ('呂布','二年二班',77)
              > 1062 - Duplicate entry '呂布' for key 'name'
              > 時間: 0.01s

          此時再次查看表定義,會發(fā)現(xiàn)Auto_Increment=6
          unique除了在插入重復(fù)數(shù)據(jù)的時候會報錯,還會使auto_increment自動增長

          unique與primary key的區(qū)別

          簡單的講,primary key=unique+not null
          具體的區(qū)別:
          (1) 唯一性約束所在的列允許空值,但是主鍵約束所在的列不允許空值。
          (2) 可以把唯一性約束放在一個或者多個列上,這些列或列的組合必須有唯一的。但是,唯一性約束所在的列并不是表的主鍵列。
          (3) 唯一性約束強制在指定的列上創(chuàng)建一個唯一性索引。在默認(rèn)情況下,創(chuàng)建唯一性的非聚簇索引,但是,也可以指定所創(chuàng)建的索引是聚簇索引。
          (4) 建立主鍵的目的是讓外鍵來引用.
          (5) 一個表最多只有一個主鍵,但可以有很多唯一鍵

          存在唯一鍵沖突時,避免策略

          insert ignore

          insert ignore會忽略數(shù)據(jù)庫中已經(jīng)存在的數(shù)據(jù)(根據(jù)主鍵或者唯一索引判斷),如果數(shù)據(jù)庫沒有數(shù)據(jù),就插入新的數(shù)據(jù),如果有數(shù)據(jù)的話就跳過這條數(shù)據(jù).

              insert ignore into sc (name,class,score) values ('呂布','二年二班',77)

          執(zhí)行上面的語句,會發(fā)現(xiàn)并沒有報錯,但是主鍵還是自動增長了。

          replace into

          • replace into 首先嘗試插入數(shù)據(jù)到表中。如果發(fā)現(xiàn)表中已經(jīng)有此行數(shù)據(jù)(根據(jù)主鍵或者唯一索引判斷)則先刪除此行數(shù)據(jù),然后插入新的數(shù)據(jù),否則,直接插入新數(shù)據(jù)。
          • 使用replace into,你必須具有delete和insert權(quán)限

              replace into sc (name,class,score) values ('呂布','二年二班',77);

          此時會發(fā)現(xiàn)呂布的班級跟年齡都改變了,但是id也變成最新的了,所以不是更新,是刪除再新增

          insert on duplicate key update

          • 如果在insert into 語句末尾指定了on duplicate key update,并且插入行后會導(dǎo)致在一個UNIQUE索引或PRIMARY KEY中出現(xiàn)重復(fù)值,則在出現(xiàn)重復(fù)值的行執(zhí)行UPDATE;如果不會導(dǎo)致重復(fù)的問題,則插入新行,跟普通的insert into一樣。
          • 使用insert into,你必須具有insert和update權(quán)限
          • 如果有新記錄被插入,則受影響行的值顯示1;如果原有的記錄被更新,則受影響行的值顯示2;如果記錄被更新前后值是一樣的,則受影響行數(shù)的值顯示0

              insert into sc (name,class,score) values ('關(guān)羽','二年二班',80on duplicate key update score=100;
          > Affected rows: 2
              > 時間: 0.008s

          舊數(shù)據(jù)中關(guān)羽是一年二班,70分,現(xiàn)在插入,最后發(fā)現(xiàn)只有分?jǐn)?shù)變成了100,班級并沒有改變。

              4 關(guān)羽  一年二班  100 2018-11-16 15:32:18   2018-11-16 15:51:51

          id沒有發(fā)生變化,數(shù)據(jù)只更新,但是auto_increment還是增長1了。

          死鎖

          insert … on duplicate key 在執(zhí)行時,innodb引擎會先判斷插入的行是否產(chǎn)生重復(fù)key錯誤,如果存在,在對該現(xiàn)有的行加上S(共享鎖)鎖,如果返回該行數(shù)據(jù)給mysql,然后mysql執(zhí)行完duplicate后的update操作, 然后對該記錄加上X(排他鎖),最后進行update寫入。
          如果有兩個事務(wù)并發(fā)的執(zhí)行同樣的語句,那么就會產(chǎn)生death lock,如

          img
          解決辦法:
          • 1、盡量對存在多個唯一鍵的table使用該語句
          • 2、在有可能有并發(fā)事務(wù)執(zhí)行的insert 的內(nèi)容一樣情況下不使用該語句

          結(jié)論:

          • 這三種方法都能避免主鍵或者唯一索引重復(fù)導(dǎo)致的插入失敗問題。
          • insert ignore能忽略重復(fù)數(shù)據(jù),只插入不重復(fù)的數(shù)據(jù)。
          • replace into和insert … on duplicate key update,都是替換原有的重復(fù)數(shù)據(jù),區(qū)別在于replace
          into是刪除原有的行后,在插入新行,如有自增id,這個會造成自增id的改變;insert … on duplicate key update在遇到重復(fù)行時,會直接更新原有的行,具體更新哪些字段怎么更新,取決于update后的語句。

          1、Intellij IDEA這樣 配置注釋模板,讓你瞬間高出一個逼格!
          2、吊炸天的 Docker 圖形化工具 Portainer,必須推薦給你!
          3、最牛逼的 Java 日志框架,性能無敵,橫掃所有對手!
          4、把Redis當(dāng)作隊列來用,真的合適嗎?
          5、驚呆了,Spring Boot居然這么耗內(nèi)存!你知道嗎?
          6、全網(wǎng)最全 Java 日志框架適配方案!還有誰不會?
          7、Spring中毒太深,離開Spring我居然連最基本的接口都不會寫了

          點分享

          點收藏

          點點贊

          點在看

          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  男女互操视频 | 国产综合久久久 | 日韩av电影在线播放 | 黄色一级网址 | 欧美三级又粗又硬 |