婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識(shí)庫 > 開發(fā)人員為什么必須要了解數(shù)據(jù)庫鎖詳解

開發(fā)人員為什么必須要了解數(shù)據(jù)庫鎖詳解

熱門標(biāo)簽:南昌高頻外呼系統(tǒng)哪家公司做的好 淄博400電話申請(qǐng) 電銷機(jī)器人各個(gè)細(xì)節(jié)介紹 電銷機(jī)器人 行業(yè) 溫州瑞安400電話怎么申請(qǐng) 百度地圖標(biāo)注后不顯示 昆明電信400電話辦理 電話機(jī)器人市場趨勢 俄國地圖標(biāo)注app

1.鎖?

1.1何為鎖

鎖在現(xiàn)實(shí)中的意義為:封閉的器物,以鑰匙或暗碼開啟。在計(jì)算機(jī)中的鎖一般用來管理對(duì)共享資源的并發(fā)訪問,比如我們java同學(xué)熟悉的Lock,synchronized等都是我們常見的鎖。當(dāng)然在我們的數(shù)據(jù)庫中也有鎖用來控制資源的并發(fā)訪問,這也是數(shù)據(jù)庫和文件系統(tǒng)的區(qū)別之一。

1.2為什么要懂?dāng)?shù)據(jù)庫鎖?

通常來說對(duì)于一般的開發(fā)人員,在使用數(shù)據(jù)庫的時(shí)候一般懂點(diǎn)DQL(select),DML(insert,update,delete)就夠了。

小明是一個(gè)剛剛畢業(yè)在互聯(lián)網(wǎng)公司工作的Java開發(fā)工程師,平常的工作就是完成PM的需求,當(dāng)然在完成需求的同時(shí)肯定逃脫不了spring,springmvc,mybatis的那一套框架,所以一般來說sql還是自己手寫,遇到比較復(fù)雜的sql會(huì)從網(wǎng)上去百度一下。對(duì)于一些比較重要操作,比如交易啊這些,小明會(huì)用spring的事務(wù)來對(duì)數(shù)據(jù)庫的事務(wù)進(jìn)行管理,由于數(shù)據(jù)量比較小目前還涉及不了分布式事務(wù)。

前幾個(gè)月小明過得都還風(fēng)調(diào)雨順,知道有一天,小明接了一個(gè)需求,商家有個(gè)配置項(xiàng),叫優(yōu)惠配置項(xiàng),可以配置買一送一,買一送二等等規(guī)則,當(dāng)然這些配置是批量傳輸給后端的,這樣就有個(gè)問題每個(gè)規(guī)則都得去匹配他到底是刪除還是添加還是修改,這樣后端邏輯就比較麻煩,聰明的小明想到了一個(gè)辦法,直接刪除這個(gè)商家的配置,然后全部添加進(jìn)去。小明馬上開發(fā)完畢,成功上線。

開始上線沒什么毛病,但是日志經(jīng)常會(huì)出現(xiàn)一些mysql-insert-deadlock異常。由于小明經(jīng)驗(yàn)比較淺,對(duì)于這類型的問題第一次遇見,于是去問了他們組的老司機(jī)-大紅,大紅一看見這個(gè)問題,然后看了他的代碼之后,輸出了幾個(gè)命令看了幾個(gè)日志,馬上定位了問題,告訴了小明:這是因?yàn)閐elete的時(shí)候會(huì)加間隙鎖,但是間隙鎖之間卻可以兼容,但是插入新的數(shù)據(jù)的時(shí)候就會(huì)因?yàn)椴迦胍庀蜴i會(huì)被間隙鎖阻塞,導(dǎo)致雙方被資源被互占,導(dǎo)致死鎖。小明聽了之后似懂非懂,由于大紅的事情比較多,不方便一直麻煩大紅,所以決定自己下來自己想。下班過后,小明回想大紅說的話,什么是間隙鎖,什么是插入意向鎖,看來作為開發(fā)者對(duì)數(shù)據(jù)庫不應(yīng)該只會(huì)寫SQL啊,不然遇到一些疑難雜癥完全沒法解決啊。想完,于是小明就踏上了學(xué)習(xí)Mysql鎖這條不歸之路。

2.InnoDB

2.1mysql體系架構(gòu)

小明沒有著急去了解鎖這方面的知識(shí),他首先先了解了下Mysql體系架構(gòu): 

可以發(fā)現(xiàn)Mysql由連接池組件、管理服務(wù)和工具組件、sql接口組件、查詢分析器組件、優(yōu)化器組件、 緩沖組件、插件式存儲(chǔ)引擎、物理文件組成。

小明發(fā)現(xiàn)在mysql中存儲(chǔ)引擎是以插件的方式提供的,在Mysql中有多種存儲(chǔ)引擎,每個(gè)存儲(chǔ)引擎都有自己的特點(diǎn)。隨后小明在命令行中打出了:

show engines \G;

一看原來有這么多種引擎。

又打出了下面的命令,查看當(dāng)前數(shù)據(jù)庫默認(rèn)的引擎:

show variables like '%storage_engine%';

小明恍然大悟:原來自己的數(shù)據(jù)庫是使用的InnoDB,依稀記得自己在上學(xué)的時(shí)候好像聽說過有個(gè)引擎叫MyIsAM,小明想這兩個(gè)有啥不同呢?馬上查找了一下資料:

對(duì)比項(xiàng) InnoDB MyIsAM
事務(wù) 支持 不支持
支持MVCC行鎖 表鎖
外鍵 支持 不支持
存儲(chǔ)空間 存儲(chǔ)空間由于需要高速緩存,較大 可壓縮
適用場景 有一定量的update和Insert 大量的select

小明大概了解了一下InnoDB和MyIsAM的區(qū)別,由于使用的是InnoDB,小明就沒有過多的糾結(jié)這一塊。

2.2事務(wù)的隔離性

小明在研究鎖之前,又回想到之前上學(xué)的時(shí)候教過的數(shù)據(jù)庫事務(wù)隔離性,其實(shí)鎖在數(shù)據(jù)庫中其功能之一也是用來實(shí)現(xiàn)事務(wù)隔離性。而事務(wù)的隔離性其實(shí)是用來解決,臟讀,不可重復(fù)讀,幻讀幾類問題。

2.2.1 臟讀

一個(gè)事務(wù)讀取到另一個(gè)事務(wù)未提交的更新數(shù)據(jù)。 什么意思呢?

時(shí)間點(diǎn) 事務(wù)A 事務(wù)B
1 begin;
2 select * from user where id = 1; begin;
3
update user set namm = 'test' where id = 1;
4 select * from user where id = 1;
5 commit; commit;

在事務(wù)A,B中,事務(wù)A在時(shí)間點(diǎn)2,4分別對(duì)user表中id=1的數(shù)據(jù)進(jìn)行了查詢了,但是事務(wù)B在時(shí)間點(diǎn)3進(jìn)行了修改,導(dǎo)致了事務(wù)A在4中的查詢出的結(jié)果其實(shí)是事務(wù)B修改后的。破壞了數(shù)據(jù)庫中的隔離性。

2.2.2 不可重復(fù)讀

在同一個(gè)事務(wù)中,多次讀取同一數(shù)據(jù)返回的結(jié)果不同,和臟讀不同的是這里讀取的是已經(jīng)提交過后的。

時(shí)間點(diǎn) 事務(wù)A 事務(wù)B
1 begin;
2 select * from user where id = 1; begin;
3
update user set namm = 'test' where id = 1;
4
commit;
5 select * from user where id = 1;
6 commit;
在事務(wù)B中提交的操作在事務(wù)A第二次查詢之前,但是依然讀到了事務(wù)B的更新結(jié)果,也破壞了事務(wù)的隔離性。

在事務(wù)B中提交的操作在事務(wù)A第二次查詢之前,但是依然讀到了事務(wù)B的更新結(jié)果,也破壞了事務(wù)的隔離性。 

2.2.3 幻讀

一個(gè)事務(wù)讀到另一個(gè)事務(wù)已提交的insert數(shù)據(jù)。

時(shí)間點(diǎn) 事務(wù)A 事務(wù)B
1 begin;
2 select * from user where id > 1; begin;
3
insert user select 2;
4
commit;
5 select * from user where id > 1;
6 commit;

在事務(wù)A中查詢了兩次id大于1的,在第一次id大于1查詢結(jié)果中沒有數(shù)據(jù),但是由于事務(wù)B插入了一條Id=2的數(shù)據(jù),導(dǎo)致事務(wù)A第二次查詢時(shí)能查到事務(wù)B中插入的數(shù)據(jù)。

事務(wù)中的隔離性:

隔離級(jí)別 臟讀 不可重復(fù)讀 幻讀
未提交讀(RUC) NO NO NO
已提交讀(RC) YES NO NO
可重復(fù)讀(RR) YES YES NO
可串行化 YES YES YES

小明注意到在收集資料的過程中,有資料寫到InnoDB和其他數(shù)據(jù)庫有點(diǎn)不同,InnoDB的可重復(fù)讀其實(shí)就能解決幻讀了,小明心想:這InnoDB還挺牛逼的,我得好好看看到底是怎么個(gè)原理。

2.3 InnoDB鎖類型

小明首先了解一下Mysql中常見的鎖類型有哪些:

2.3.1 S or X

在InnoDb中實(shí)現(xiàn)了兩個(gè)標(biāo)準(zhǔn)的行級(jí)鎖,可以簡單的看為兩個(gè)讀寫鎖:

  • S-共享鎖:又叫讀鎖,其他事務(wù)可以繼續(xù)加共享鎖,但是不能繼續(xù)加排他鎖。
  • X-排他鎖: 又叫寫鎖,一旦加了寫鎖之后,其他事務(wù)就不能加鎖了。

兼容性:是指事務(wù)A獲得一個(gè)某行某種鎖之后,事務(wù)B同樣的在這個(gè)行上嘗試獲取某種鎖,如果能立即獲取,則稱鎖兼容,反之叫沖突。

縱軸是代表已有的鎖,橫軸是代表嘗試獲取的鎖。

. X S
X 沖突 沖突
S 沖突 兼容

2.3.2 意向鎖

意向鎖在InnoDB中是表級(jí)鎖,和他的名字一樣他是用來表達(dá)一個(gè)事務(wù)想要獲取什么。意向鎖分為:

  • 意向共享鎖:表達(dá)一個(gè)事務(wù)想要獲取一張表中某幾行的共享鎖。
  • 意向排他鎖:表達(dá)一個(gè)事務(wù)想要獲取一張表中某幾行的排他鎖。

這個(gè)鎖有什么用呢?為什么需要這個(gè)鎖呢? 首先說一下如果沒有這個(gè)鎖,如果要給這個(gè)表加上表鎖,一般的做法是去遍歷每一行看看他是否有行鎖,這樣的話效率太低,而我們有意向鎖,只需要判斷是否有意向鎖即可,不需要再去一行行的去掃描。

在InnoDB中由于支持的是行級(jí)的鎖,因此InnboDB鎖的兼容性可以擴(kuò)展如下:

. IX IS X S
IX 兼容 兼容 沖突 沖突
IS 兼容 兼容 沖突 兼容
X 沖突 沖突 沖突 沖突
S 沖突 兼容 沖突 兼容

2.3.3 自增長鎖

自增長鎖是一種特殊的表鎖機(jī)制,提升并發(fā)插入性能。對(duì)于這個(gè)鎖有幾個(gè)特點(diǎn):

  • 在sql執(zhí)行完就釋放鎖,并不是事務(wù)執(zhí)行完。
  • 對(duì)于Insert...select大數(shù)據(jù)量插入會(huì)影響插入性能,因?yàn)闀?huì)阻塞另外一個(gè)事務(wù)執(zhí)行。
  • 自增算法可以配置。

在MySQL5.1.2版本之后,有了很多優(yōu)化,可以根據(jù)不同的模式來進(jìn)行調(diào)整自增加鎖的方式。小明看到了這里打開了自己的MySQL發(fā)現(xiàn)是5.7之后,于是便輸入了下面的語句,獲取到當(dāng)前鎖的模式:

mysql> show variables like 'innodb_autoinc_lock_mode';

+--------------------------+-------+

| Variable_name | Value |

+--------------------------+-------+

| innodb_autoinc_lock_mode | 2 |

+--------------------------+-------+

1 row in set (0.01 sec)

在MySQL中innodbautoinclock_mode有3種配置模式:0、1、2,分別對(duì)應(yīng)”傳統(tǒng)模式”, “連續(xù)模式”, “交錯(cuò)模式”。

  • 傳統(tǒng)模式:也就是我們最上面的使用表鎖。
  • 連續(xù)模式:對(duì)于插入的時(shí)候可以確定行數(shù)的使用互斥量,對(duì)于不能確定行數(shù)的使用表鎖的模式。
  • 交錯(cuò)模式:所有的都使用互斥量,為什么叫交錯(cuò)模式呢,有可能在批量插入時(shí)自增值不是連續(xù)的,當(dāng)然一般來說如果不看重自增值連續(xù)一般選擇這個(gè)模式,性能是最好的。

2.4InnoDB鎖算法

小明已經(jīng)了解到了在InnoDB中有哪些鎖類型,但是如何去使用這些鎖,還是得靠鎖算法。

2.4.1 記錄鎖(Record-Lock)

記錄鎖是鎖住記錄的,這里要說明的是這里鎖住的是索引記錄,而不是我們真正的數(shù)據(jù)記錄。

  • 如果鎖的是非主鍵索引,會(huì)在自己的索引上面加鎖之后然后再去主鍵上面加鎖鎖住.
  • 如果沒有表上沒有索引(包括沒有主鍵),則會(huì)使用隱藏的主鍵索引進(jìn)行加鎖。
  • 如果要鎖的列沒有索引,則會(huì)進(jìn)行全表記錄加鎖。

2.4.2 間隙鎖

間隙鎖顧名思義鎖間隙,不鎖記錄。鎖間隙的意思就是鎖定某一個(gè)范圍,間隙鎖又叫g(shù)ap鎖,其不會(huì)阻塞其他的gap鎖,但是會(huì)阻塞插入間隙鎖,這也是用來防止幻讀的關(guān)鍵。

2.4.3 next-key鎖

這個(gè)鎖本質(zhì)是記錄鎖加上gap鎖。在RR隔離級(jí)別下(InnoDB默認(rèn)),Innodb對(duì)于行的掃描鎖定都是使用此算法,但是如果查詢掃描中有唯一索引會(huì)退化成只使用記錄鎖。為什么呢? 因?yàn)槲ㄒ凰饕艽_定行數(shù),而其他索引不能確定行數(shù),有可能在其他事務(wù)中會(huì)再次添加這個(gè)索引的數(shù)據(jù)會(huì)造成幻讀。

這里也說明了為什么Mysql可以在RR級(jí)別下解決幻讀。

2.4.4 插入意向鎖

插入意向鎖Mysql官方對(duì)其的解釋:

An insert intention lock is a type of gap lock set by INSERT operations prior to row insertion. This lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap. Suppose that there are index records with values of 4 and 7. Separate transactions that attempt to insert values of 5 and 6, respectively, each lock the gap between 4 and 7 with insert intention locks prior to obtaining the exclusive lock on the inserted row, but do not block each other because the rows are nonconflicting.

可以看出插入意向鎖是在插入的時(shí)候產(chǎn)生的,在多個(gè)事務(wù)同時(shí)寫入不同數(shù)據(jù)至同一索引間隙的時(shí)候,并不需要等待其他事務(wù)完成,不會(huì)發(fā)生鎖等待。假設(shè)有一個(gè)記錄索引包含鍵值4和7,不同的事務(wù)分別插入5和6,每個(gè)事務(wù)都會(huì)產(chǎn)生一個(gè)加在4-7之間的插入意向鎖,獲取在插入行上的排它鎖,但是不會(huì)被互相鎖住,因?yàn)閿?shù)據(jù)行并不沖突。

這里要說明的是如果有間隙鎖了,插入意向鎖會(huì)被阻塞。

2.5 MVCC

MVCC,多版本并發(fā)控制技術(shù)。在InnoDB中,在每一行記錄的后面增加兩個(gè)隱藏列,記錄創(chuàng)建版本號(hào)和刪除版本號(hào)。通過版本號(hào)和行鎖,從而提高數(shù)據(jù)庫系統(tǒng)并發(fā)性能。

在MVCC中,對(duì)于讀操作可以分為兩種讀:

  • 快照讀:讀取的歷史數(shù)據(jù),簡單的select語句,不加鎖,MVCC實(shí)現(xiàn)可重復(fù)讀,使用的是MVCC機(jī)制讀取undo中的已經(jīng)提交的數(shù)據(jù)。所以它的讀取是非阻塞的。
  • 當(dāng)前讀:需要加鎖的語句,update,insert,delete,select...for update等等都是當(dāng)前讀。

在RR隔離級(jí)別下的快照讀,不是以begin事務(wù)開始的時(shí)間點(diǎn)作為snapshot建立時(shí)間點(diǎn),而是以第一條select語句的時(shí)間點(diǎn)作為snapshot建立的時(shí)間點(diǎn)。以后的select都會(huì)讀取當(dāng)前時(shí)間點(diǎn)的快照值。

在RC隔離級(jí)別下每次快照讀均會(huì)創(chuàng)建新的快照。

具體的原理是通過每行會(huì)有兩個(gè)隱藏的字段一個(gè)是用來記錄當(dāng)前事務(wù),一個(gè)是用來記錄回滾的指向Undolog。利用undolog就可以讀取到之前的快照,不需要單獨(dú)開辟空間記錄。

3.加鎖分析

小明到這里,已經(jīng)學(xué)習(xí)很多mysql鎖有關(guān)的基礎(chǔ)知識(shí),所以決定自己創(chuàng)建一個(gè)表搞下實(shí)驗(yàn)。首先創(chuàng)建了一個(gè)簡單的用戶表:

CREATE TABLE `user` (

`id` int(11) unsigned NOT NULL AUTO_INCREMENT,

`name` varchar(11) CHARACTER SET utf8mb4 DEFAULT NULL,

`comment` varchar(11) CHARACTER SET utf8 DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `index_name` (`name`)

) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

然后插入了幾條實(shí)驗(yàn)數(shù)據(jù):

insert user select 20,333,333;

insert user select 25,555,555;

insert user select 20,999,999;

數(shù)據(jù)庫事務(wù)隔離選擇了RR

3.1 實(shí)驗(yàn)1

小明開啟了兩個(gè)事務(wù),進(jìn)行實(shí)驗(yàn)1.

時(shí)間點(diǎn) 事務(wù)A 事務(wù)B
1 begin;
2 select * from user where name = '555' for update; begin;
3
insert user select 31,'556','556';
4
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

小明開啟了兩個(gè)事務(wù)并輸入了上面的語句,發(fā)現(xiàn)事務(wù)B居然出現(xiàn)了超時(shí),小明看了一下自己明明是對(duì)name = 555這一行進(jìn)行的加鎖,為什么我想插入name=556給我阻塞了。于是小明打開命令行輸入:

select * from information_schema.INNODB_LOCKS

發(fā)現(xiàn)在事務(wù)A中給555加了Next-key鎖,事務(wù)B插入的時(shí)候會(huì)首先進(jìn)行插入意向鎖的插入,于是得出下面結(jié)論:

 

可以看見事務(wù)B由于間隙鎖和插入意向鎖的沖突,導(dǎo)致了阻塞。

3.2 實(shí)驗(yàn)2

小明發(fā)現(xiàn)上面查詢條件用的是普通的非唯一索引,于是小明就試了一下主鍵索引:

時(shí)間點(diǎn) 事務(wù)A 事務(wù)B
1 begin;
2 select * from user where id = 25 for update; begin;
3
insert user select 26,'666','666';
4
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0

居然發(fā)現(xiàn)事務(wù)B并沒有發(fā)生阻塞,哎這個(gè)是咋回事呢,小明有點(diǎn)疑惑,按照實(shí)驗(yàn)1的套路應(yīng)該會(huì)被阻塞啊,因?yàn)?5-30之間會(huì)有間隙鎖。于是小明又祭出了命令行,發(fā)現(xiàn)只加了X記錄鎖。原來是因?yàn)槲ㄒ凰饕龝?huì)降級(jí)記錄鎖,這么做的理由是:非唯一索引加next-key鎖由于不能確定明確的行數(shù)有可能其他事務(wù)在你查詢的過程中,再次添加這個(gè)索引的數(shù)據(jù),導(dǎo)致隔離性遭到破壞,也就是幻讀。唯一索引由于明確了唯一的數(shù)據(jù)行,所以不需要添加間隙鎖解決幻讀。

3.3 實(shí)驗(yàn)3

上面測試了主鍵索引,非唯一索引,這里還有個(gè)字段是沒有索引,如果對(duì)其加鎖會(huì)出現(xiàn)什么呢?

時(shí)間點(diǎn) 事務(wù)A 事務(wù)B
1 begin;
2 select * from user where comment = '555' for update; begin;
3
insert user select 26,'666','666';
4
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
5
insert user select 31,'3131','3131';
6
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
7
insert user select 10,'100','100';
8
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
小明一看哎喲我去,這個(gè)咋回事呢,咋不管是用實(shí)驗(yàn)1非間隙鎖范圍的數(shù)據(jù),還是用間隙鎖里面的數(shù)據(jù)都不行,難道是加了表鎖嗎?

的確,如果用沒有索引的數(shù)據(jù),其會(huì)對(duì)所有聚簇索引上都加上next-key鎖。

所以大家平常開發(fā)的時(shí)候如果對(duì)查詢條件沒有索引的,一定進(jìn)行一致性讀,也就是加鎖讀,會(huì)導(dǎo)致全表加上索引,會(huì)導(dǎo)致其他事務(wù)全部阻塞,數(shù)據(jù)庫基本會(huì)處于不可用狀態(tài)。

4.回到事故

4.1 死鎖

小明做完實(shí)驗(yàn)之后總算是了解清楚了加鎖的一些基本套路,但是之前線上出現(xiàn)的死鎖又是什么東西呢?

死鎖:是指兩個(gè)或兩個(gè)以上的事務(wù)在執(zhí)行過程中,因爭奪資源而造成的一種互相等待的現(xiàn)象。說明有等待才會(huì)有死鎖,解決死鎖可以通過去掉等待,比如回滾事務(wù)。

解決死鎖的兩個(gè)辦法:

  • 等待超時(shí):當(dāng)某一個(gè)事務(wù)等待超時(shí)之后回滾該事務(wù),另外一個(gè)事務(wù)就可以執(zhí)行了,但是這樣做效率較低,會(huì)出現(xiàn)等待時(shí)間,還有個(gè)問題是如果這個(gè)事務(wù)所占的權(quán)重較大,已經(jīng)更新了很多數(shù)據(jù)了,但是被回滾了,就會(huì)導(dǎo)致資源浪費(fèi)。
  • 等待圖(wait-for-graph): 等待圖用來描述事務(wù)之間的等待關(guān)系,當(dāng)這個(gè)圖如果出現(xiàn)回路如下:

 

就出現(xiàn)回滾,通常來說InnoDB會(huì)選擇回滾權(quán)重較小的事務(wù),也就是undo較小的事務(wù)。

4.2 線上問題

小明到這里,基本需要的基本功都有了,于是在自己的本地表中開始復(fù)現(xiàn)這個(gè)問題:

時(shí)間點(diǎn) 事務(wù)A 事務(wù)B
1 begin; begin;
2 delete from user where name = '777'; delete from user where name = '666';
3 insert user select 27,'777','777'; insert user select 26,'666','666';
4 ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction Query OK, 1 row affected (14.32 sec) Records: 1 Duplicates: 0 Warnings: 0

可以看見事務(wù)A出現(xiàn)被回滾了,而事務(wù)B成功執(zhí)行。 具體每個(gè)時(shí)間點(diǎn)發(fā)生了什么呢?

時(shí)間點(diǎn)2:事務(wù)A刪除name = '777'的數(shù)據(jù),需要對(duì)777這個(gè)索引加上next-Key鎖,但是其不存在,所以只對(duì)555-999之間加間隙鎖,同理事務(wù)B也對(duì)555-999之間加間隙鎖。間隙鎖之間是兼容的。

時(shí)間點(diǎn)3:事務(wù)A,執(zhí)行Insert操作,首先插入意向鎖,但是555-999之間有間隙鎖,由于插入意向鎖和間隙鎖沖突,事務(wù)A阻塞,等待事務(wù)B釋放間隙鎖。事務(wù)B同理,等待事務(wù)A釋放間隙鎖。于是出現(xiàn)了A->B,B->A回路等待。

時(shí)間點(diǎn)4:事務(wù)管理器選擇回滾事務(wù)A,事務(wù)B插入操作執(zhí)行成功。

4.3 修復(fù)BUG

這個(gè)問題總算是被小明找到了,就是因?yàn)殚g隙鎖,現(xiàn)在需要解決這個(gè)問題,這個(gè)問題的原因是出現(xiàn)了間隙鎖,那就來去掉他吧:

  • 方案一:隔離級(jí)別降級(jí)為RC,在RC級(jí)別下不會(huì)加入間隙鎖,所以就不會(huì)出現(xiàn)毛病了,但是在RC級(jí)別下會(huì)出現(xiàn)幻讀,可提交讀都破壞隔離性的毛病,所以這個(gè)方案不行。
  • 方案二:隔離級(jí)別升級(jí)為可序列化,小明經(jīng)過測試后發(fā)現(xiàn)不會(huì)出現(xiàn)這個(gè)問題,但是在可序列化級(jí)別下,性能會(huì)較低,會(huì)出現(xiàn)較多的鎖等待,同樣的也不考慮。
  • 方案三:修改代碼邏輯,不要直接刪,改成每個(gè)數(shù)據(jù)由業(yè)務(wù)邏輯去判斷哪些是更新,哪些是刪除,那些是添加,這個(gè)工作量稍大,小明寫這個(gè)直接刪除的邏輯就是為了不做這些復(fù)雜的事的,所以這個(gè)方案先不考慮。
  • 方案四:較少的修改代碼邏輯,在刪除之前,可以通過快照查詢(不加鎖),如果查詢沒有結(jié)果,則直接插入,如果有通過主鍵進(jìn)行刪除,在之前第三節(jié)實(shí)驗(yàn)2中,通過唯一索引會(huì)降級(jí)為記錄鎖,所以不存在間隙鎖。

經(jīng)過考慮小明選擇了第四種,馬上進(jìn)行了修復(fù),然后上線觀察驗(yàn)證,發(fā)現(xiàn)現(xiàn)在已經(jīng)不會(huì)出現(xiàn)這個(gè)Bug了,這下小明總算能睡個(gè)安穩(wěn)覺了。

4.4 如何防止死鎖

小明通過基礎(chǔ)的學(xué)習(xí)和平常的經(jīng)驗(yàn)總結(jié)了如下幾點(diǎn):

  • 以固定的順序訪問表和行。交叉訪問更容易造成事務(wù)等待回路。
  • 盡量避免大事務(wù),占有的資源鎖越多,越容易出現(xiàn)死鎖。建議拆成小事務(wù)。
  • 降低隔離級(jí)別。如果業(yè)務(wù)允許(上面4.3也分析了,某些業(yè)務(wù)并不能允許),將隔離級(jí)別調(diào)低也是較好的選擇,比如將隔離級(jí)別從RR調(diào)整為RC,可以避免掉很多因?yàn)間ap鎖造成的死鎖。
  • 為表添加合理的索引。防止沒有索引出現(xiàn)表鎖,出現(xiàn)的死鎖的概率會(huì)突增。

最后

由于篇幅有限很多東西并不能介紹全如果感興趣的同學(xué)可以閱讀《Mysql技術(shù)內(nèi)幕-InnoDB引擎》第6章 以及 何大師的MySQL 加鎖處理分析。作者本人水平有限,如果有什么錯(cuò)誤,還請(qǐng)指正。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

您可能感興趣的文章:
  • Mysql數(shù)據(jù)庫鎖定機(jī)制詳細(xì)介紹
  • mysql 數(shù)據(jù)庫死鎖原因及解決辦法
  • mysql數(shù)據(jù)庫鎖的產(chǎn)生原因及解決辦法
  • Mysql 數(shù)據(jù)庫死鎖過程分析(select for update)
  • MySQL數(shù)據(jù)庫的一次死鎖實(shí)例分析
  • MySQL數(shù)據(jù)庫之Purge死鎖問題解析

標(biāo)簽:甘南 拉薩 安徽 海口 葫蘆島 嘉峪關(guān) 吐魯番 洛陽

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《開發(fā)人員為什么必須要了解數(shù)據(jù)庫鎖詳解》,本文關(guān)鍵詞  開發(fā),人員,為什么,必,須要,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《開發(fā)人員為什么必須要了解數(shù)據(jù)庫鎖詳解》相關(guān)的同類信息!
  • 本頁收集關(guān)于開發(fā)人員為什么必須要了解數(shù)據(jù)庫鎖詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    国产欧美日韩在线看| 美日韩一区二区| 久久久电影一区二区三区| 日韩欧美色电影| 一区二区三区四区蜜桃| 91一区一区三区| 3d动漫精品啪啪一区二区竹菊| 亚洲精品一区二区三区99| 亚洲另类中文字| 日韩美女久久久| 亚洲精品在线观看视频| 亚洲成a人片在线不卡一二三区| 日韩久久久精品| 亚洲一区在线观看网站| 国产一区福利在线| 亚洲成人综合网站| 国产91在线看| 国产三级一区二区| 精品少妇一区二区三区视频免付费| 日韩成人免费电影| 制服丝袜亚洲播放| 日韩欧美一级特黄在线播放| 一本一道综合狠狠老| 国产精品伦一区二区三级视频| 99久久777色| 91在线国产观看| 午夜免费欧美电影| 久久综合999| 91色视频在线| 国产精品视频一区二区三区不卡| 91成人免费网站| 免费高清不卡av| 国产精品福利av | 黑人巨大精品欧美黑白配亚洲| 欧美男男青年gay1069videost| 日韩一区二区三区电影在线观看| 国产一区二区看久久| 亚洲色图欧美在线| 亚洲一区二区三区美女| 欧美一区二区精美| 99久久精品国产观看| 青青草97国产精品免费观看| 欧美国产一区在线| 欧美三级电影精品| 日韩av电影天堂| 欧美三级电影网| 亚洲三级电影网站| 高清不卡在线观看av| 亚洲一二三四区不卡| 欧美亚洲一区二区三区四区| 日韩av成人高清| 2021国产精品久久精品| 99热精品国产| 日韩1区2区3区| 国产精品电影一区二区| 宅男在线国产精品| 久久亚洲私人国产精品va媚药| av男人天堂一区| 蜜桃视频第一区免费观看| 国产精品性做久久久久久| 日本最新不卡在线| 日本一区二区视频在线| 精品欧美乱码久久久久久| 欧美色大人视频| 成人免费毛片高清视频| 中文无字幕一区二区三区| 欧美日韩一级大片网址| 99久久国产综合色|国产精品| 国产一区二区剧情av在线| 人人超碰91尤物精品国产| 亚洲大片一区二区三区| 亚洲自拍与偷拍| 国产精品久久久久久福利一牛影视 | 欧美男女性生活在线直播观看| 欧美va亚洲va在线观看蝴蝶网| 欧美日韩精品一区二区天天拍小说 | 日韩精品在线网站| 777a∨成人精品桃花网| 欧美视频完全免费看| 日本韩国欧美在线| 欧美伊人精品成人久久综合97| 日韩专区一卡二卡| 午夜免费欧美电影| 成人高清伦理免费影院在线观看| 国产精品久久久久久久久免费桃花 | 久久精品av麻豆的观看方式| 日韩精品午夜视频| 国产精品婷婷午夜在线观看| 久久97超碰国产精品超碰| 欧美精品免费视频| 日本欧美在线观看| 国产日韩欧美制服另类| 成人一二三区视频| 亚洲欧洲综合另类在线| 99riav久久精品riav| 一区二区免费在线播放| 欧美日韩一卡二卡三卡| 午夜久久久久久久久| 欧美精品丝袜中出| 国产麻豆精品在线观看| 亚洲欧美自拍偷拍色图| 国产精品传媒视频| 欧美日韩小视频| 一本久道久久综合中文字幕| 欧美午夜视频网站| 93久久精品日日躁夜夜躁欧美| 国产精一区二区三区| 91精品在线观看入口| 欧美日韩成人激情| 精品免费视频.| 国产精品久久久久四虎| 日韩美女啊v在线免费观看| 一本大道久久a久久精品综合| 国产欧美日韩在线看| 色一情一乱一乱一91av| 国产精一区二区三区| 日韩精品欧美精品| 日韩精品91亚洲二区在线观看 | 丝袜亚洲另类欧美| 亚洲大片精品永久免费| 亚洲成a人片综合在线| 亚洲成av人片一区二区| 一区二区三区日韩欧美| 一区二区三区四区亚洲| 一区二区三区精品| 亚洲福利视频一区| 日本亚洲最大的色成网站www| 五月综合激情婷婷六月色窝| 韩国女主播一区| aaa国产一区| 欧美一级在线观看| 宅男在线国产精品| 久久亚洲精华国产精华液| 欧美不卡一区二区三区四区| 国产欧美中文在线| 亚洲免费三区一区二区| 免费观看成人av| 久久国产精品99精品国产| 国产成人av一区二区三区在线 | 另类调教123区| 欧美揉bbbbb揉bbbbb| 国产精品久线在线观看| 色综合久久久久综合99| www.欧美精品一二区| 亚洲mv在线观看| 亚洲永久免费av| 欧美久久久久久久久| 国产精品一区二区在线观看网站| 亚洲精品视频一区| 综合激情网...| 日本一区二区三区四区| 久久先锋影音av鲁色资源| fc2成人免费人成在线观看播放| 国产乱对白刺激视频不卡| 亚洲一二三区视频在线观看| 久久看人人爽人人| 色综合天天综合色综合av| 久草在线在线精品观看| 激情六月婷婷久久| 天堂资源在线中文精品| 国产成人福利片| 久久午夜羞羞影院免费观看| 麻豆91在线观看| 久久品道一品道久久精品| 裸体歌舞表演一区二区| 欧美刺激脚交jootjob| 麻豆freexxxx性91精品| 久久婷婷国产综合精品青草| 成人激情免费视频| 中文字幕一区三区| 色噜噜狠狠色综合中国| 亚洲国产aⅴ成人精品无吗| 欧美色图12p| 久草精品在线观看| 亚洲精品va在线观看| 日韩欧美一区二区久久婷婷| 不卡高清视频专区| 五月激情综合网| 久久精品视频一区二区三区| 91啪亚洲精品| 国产一二三精品| 午夜日韩在线观看| 国产婷婷色一区二区三区四区| 91香蕉国产在线观看软件| 91精品中文字幕一区二区三区| 中文字幕电影一区| 欧美性猛交xxxxxx富婆| 国产成人日日夜夜| 韩国一区二区在线观看| 日韩二区在线观看| 国产精品三级在线观看| 国产日韩欧美a| 337p日本欧洲亚洲大胆精品| 欧美一区二区视频在线观看2022 | 五月婷婷激情综合| 一区在线观看视频| 国产日产精品1区| 国产三级久久久| 国产精品三级视频| 欧美国产一区二区|