真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法

這篇文章主要講解了“MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法”吧!

創(chuàng)新互聯(lián)專注于曲周網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供曲周營銷型網(wǎng)站建設(shè),曲周網(wǎng)站制作、曲周網(wǎng)頁設(shè)計(jì)、曲周網(wǎng)站官網(wǎng)定制、小程序定制開發(fā)服務(wù),打造曲周網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供曲周網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

三類常見引擎:

MyIsam :不支持事務(wù),不支持外鍵,所以訪問速度快。鎖機(jī)制是表鎖,支持全文索引

InnoDB :支持事務(wù)、支持外鍵,所以對比MyISAM,InnoDB的處理效率差一些,并要占更多的磁盤空間保留數(shù)據(jù)和索引。鎖機(jī)制是行鎖,不支持全文索引

Memory:數(shù)據(jù)是存放在內(nèi)存中的,默認(rèn)哈希索引,非常適合存儲(chǔ)臨時(shí)數(shù)據(jù),服務(wù)器關(guān)閉后,數(shù)據(jù)會(huì)丟失掉。

如何選擇存儲(chǔ)引擎:

MyISAM:應(yīng)用是以讀操作和插入操作為主,只有很少的更新和刪除操作,并且對事務(wù)的完整性、并發(fā)性要求不是很高。

InnoDB:用于事務(wù)處理應(yīng)用程序,支持外鍵,如果應(yīng)用對事務(wù)的完整性有比較高的要求,在并發(fā)條件下要求數(shù)據(jù)的一致性。更新刪除等頻繁(InnoDB可以有效的降低由于刪除和更新導(dǎo)致的鎖定),對于數(shù)據(jù)準(zhǔn)確性要求比較高的,此引擎適合。

Memory:通常用于更新不太頻繁的小表,用以快速得到訪問結(jié)果。

Mysql中的鎖

如果熟悉多線程,那么對鎖肯定是有概念的,鎖是計(jì)算機(jī)協(xié)調(diào)多個(gè)進(jìn)程或線程對某一資源并發(fā)訪問的機(jī)制。

Mysql中的鎖分為表鎖和行鎖:

顧名思義,表鎖就是鎖住一張表,而行鎖就是鎖住一行。

表鎖的特點(diǎn):開銷小,不會(huì)產(chǎn)生死鎖,發(fā)生鎖沖突的概率高,并且并發(fā)度低。

行鎖的特點(diǎn):開銷大,會(huì)產(chǎn)生死鎖,發(fā)生鎖沖突的概率低,并發(fā)度高。

因此MyISAM和Memory引擎采用的是表鎖,而InnoDB存儲(chǔ)引擎采用的是行鎖。

MyISAM的鎖機(jī)制:

分為共享讀鎖和獨(dú)占寫鎖。

讀鎖是:當(dāng)某一進(jìn)程對某張表進(jìn)行讀操作時(shí)(select),其他線程也可以讀,但是不能寫。簡單的理解就是,我讀的時(shí)候你不能寫。

寫鎖是:當(dāng)某一進(jìn)程對某種表某張表的寫時(shí)(insert,update,,delete),其他線程不能寫也不能讀??梢岳斫鉃椋覍懙臅r(shí)候,你不能讀,也不能寫。

因此MyISAM的讀操作和寫操作,以及寫操作之間是串行的!MyISAM在執(zhí)行讀寫操作的時(shí)候會(huì)自動(dòng)給表加相應(yīng)的鎖(也就是說不用顯示的使用lock table命令),MyISAM總是一次獲得SQL語句所需要的全部鎖,這也是MyISAM不會(huì)出現(xiàn)死鎖的原因。

下面分別舉關(guān)于寫鎖和讀鎖的例子:

寫鎖:

事務(wù)1事務(wù)2

















取得first_test表的寫鎖:mysql> lock table first_test write;Query OK, 0 rows affected (0.00 sec)


















當(dāng)前事務(wù)對查詢、更新和插入操作都可以執(zhí)行mysql> select * from first_test ;+——+———+idage+——+———+110
211
312
413+——+———+4 rows in set (0.00 sec)mysql> insert into first_test(age) values(14);Query OK, 1 row affected (0.11 sec)其他事務(wù)對鎖定表的查詢被阻塞,需要等到鎖被釋放,才可以執(zhí)行mysql> select * from first_test;等待……


mysql> unlock table;Query OK, 0 rows affected (0.00 sec)等待


















mysql> select * from first_test;+——+———+idage+——+———+110
211
312
413
514+——+———+5 rows in set (9 min 45.02 sec)

讀鎖例子如下:

事務(wù)1事務(wù)2



































獲得表first_read的鎖定mysql> lock table first_test read;Query OK, 0 rows affected (0.00 sec)




































當(dāng)前事務(wù)可以查詢該表記錄:mysql> select * from first_test;+——+———+idage+——+———+110
211
312
413
514+——+———+5 rows in set (0.00 sec)其他事務(wù)也可以查到該表信息mysql> select * from first_test;+——+———+idage+——+———+110
211
312
413
514+——+———+5 rows in set (0.00 sec)
但是當(dāng)前事務(wù)不能查詢沒有鎖定的表:mysql> select * from goods;ERROR 1100 (HY000): Table ‘goods’ was not locked with LOCK TABLES其他事務(wù)可以查詢或更新未鎖定的表:mysql> select * from goods;+——+——————+———+idnamenum+——+——————+———+1firstGoods11
3ThirdGoods11
4fourth11+——+——————+———+10 rows in set (0.00 sec)



















而且插入更新鎖定的表都會(huì)報(bào)錯(cuò):mysql> insert into first_test(age) values(15);ERROR 1099 (HY000): Table ‘first_test’ was locked with a READ lock and can’t be updatedmysql> update first_test set age=100 where id =1;ERROR 1099 (HY000): Table ‘first_test’ was locked with a READ lock and can’t be updated當(dāng)更新被鎖定的表時(shí)會(huì)等待:mysql> update first_test set age=100 where id =1;等待……



































mysql> unlock table;Query OK, 0 rows affected (0.00 sec)mysql> update first_test set age=100 where id =1;Query OK, 1 row affected (38.82 sec)Rows matched: 1  Changed: 1  Warnings: 0



































并發(fā)插入

剛說到Mysql在插入和修改的時(shí)候都是串行的,但是MyISAM也支持查詢和插入的并發(fā)操作。

MyISAM中有一個(gè)系統(tǒng)變量concurrent_insert(默認(rèn)為1),用以控制并發(fā)插入(用戶在表尾插入數(shù)據(jù))行為。

當(dāng)concurrent_insert為0時(shí),不允許并發(fā)插入。

當(dāng)concurrent_insert為1時(shí),如果表中沒有空洞(中間沒有被刪除的行),MyISAM允許一個(gè)進(jìn)程在讀表的同時(shí),另一個(gè)進(jìn)程從表尾插入記錄。

當(dāng)concurrent_insert為2時(shí),無論MyISAM表中有沒有空洞,都可以在末尾插入記錄

事務(wù)1事務(wù)2























mysql> lock table first_test read local;Query OK, 0 rows affected (0.00 sec)—加入local選項(xiàng)是說明,在表滿足并發(fā)插入的前提下,允許在末尾插入數(shù)據(jù)
























當(dāng)前進(jìn)程不能進(jìn)行插入和更新操作mysql> insert into first_test(age) values(15);ERROR 1099 (HY000): Table ‘first_test’ was locked with a READ lock and can’t be updatedmysql> update first_test set age=200 where id =1;ERROR 1099 (HY000): Table ‘first_test’ was locked with a READ lock and can’t be updated其他進(jìn)程可以進(jìn)行插入,但是更新會(huì)等待:mysql> insert into first_test(age) values(15);Query OK, 1 row affected (0.00 sec)mysql> update first_test set age=200 where id =2;等待…..























當(dāng)前進(jìn)程不能不能訪問其他進(jìn)程插入的數(shù)據(jù)mysql> select * from first_test;+——+———+idage+——+———+1100
211
312
413
514
614+——+———+6 rows in set (0.00 sec)



釋放鎖以后皆大歡喜mysql> unlock table;Query OK, 0 rows affected (0.00 sec)等待























插入的和更新的都出來的:mysql> select * from first_test;+——+———+idage+——+———+1100
2200
312
413
514
614
715+——+———+7 rows in set (0.00 sec)mysql> update first_test set age=200 where id =2;Query OK, 1 row affected (1 min 39.75 sec)Rows matched: 1  Changed: 1  Warnings: 0

需要注意的:

并發(fā)插入是解決對同一表中的查詢和插入的鎖爭用。

如果對有空洞的表進(jìn)行并發(fā)插入會(huì)產(chǎn)生碎片,所以在空閑時(shí)可以利用optimize table命令回收因刪除記錄產(chǎn)生的空洞。

鎖調(diào)度

在MyISAM中當(dāng)一個(gè)進(jìn)程請求某張表的讀鎖,而另一個(gè)進(jìn)程同時(shí)也請求寫鎖,Mysql會(huì)先讓后者獲得寫鎖。即使讀請求比寫請求先到達(dá)鎖等待隊(duì)列,寫鎖也會(huì)插入到讀鎖之前。

因?yàn)镸ysql總是認(rèn)為寫請求一般比讀請求重要,這也就是MyISAM不太適合有大量的讀寫操作的應(yīng)用的原因,因?yàn)榇罅康膶懻埱髸?huì)讓查詢操作很難獲取到讀鎖,有可能永遠(yuǎn)阻塞。

處理辦法:

1、指定Insert、update、delete語句的low_priority屬性,降低其優(yōu)先級。

2、指定啟動(dòng)參數(shù)low-priority-updates,使得MyISAM默認(rèn)給讀請求優(yōu)先的權(quán)利。

3、執(zhí)行命令set low_priority_updates=1,使該連接發(fā)出的請求降低。

4、指定max_write_lock_count設(shè)置一個(gè)合適的值,當(dāng)寫鎖達(dá)到這個(gè)值后,暫時(shí)降低寫請求的優(yōu)先級,讓讀請求獲取鎖。

但是上面的處理辦法造成的原因就是當(dāng)遇到復(fù)雜的查詢語句時(shí),寫請求可能很難獲取到鎖,這是一個(gè)很糾結(jié)的問題,所以我們一般避免使用復(fù)雜的查詢語句,如果如法避免,則可以再數(shù)據(jù)庫空閑階段(深夜)執(zhí)行。

我們知道m(xù)ysql在以前,存儲(chǔ)引擎默認(rèn)是MyISAM,但是隨著對事務(wù)和并發(fā)的要求越來越高,便引入了InnoDB引擎,它具有支持事務(wù)安全等一系列特性。

InnoDB鎖模式

InnoDB實(shí)現(xiàn)了兩種類型的行鎖。

共享鎖(S):允許一個(gè)事務(wù)去讀一行,阻止其他事務(wù)獲得相同的數(shù)據(jù)集的排他鎖。

排他鎖(X):允許獲得排他鎖的事務(wù)更新數(shù)據(jù),但是組織其他事務(wù)獲得相同數(shù)據(jù)集的共享鎖和排他鎖。

可以這么理解:

共享鎖就是我讀的時(shí)候,你可以讀,但是不能寫。排他鎖就是我寫的時(shí)候,你不能讀也不能寫。其實(shí)就是MyISAM的讀鎖和寫鎖,但是針對的對象不同了而已。

除此之外InnoDB還有兩個(gè)表鎖:

意向共享鎖(IS):表示事務(wù)準(zhǔn)備給數(shù)據(jù)行加入共享鎖,也就是說一個(gè)數(shù)據(jù)行加共享鎖前必須先取得該表的IS鎖

意向排他鎖(IX):類似上面,表示事務(wù)準(zhǔn)備給數(shù)據(jù)行加入排他鎖,說明事務(wù)在一個(gè)數(shù)據(jù)行加排他鎖前必須先取得該表的IX鎖。

InnoDB行鎖模式兼容列表:

MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法

注意:

當(dāng)一個(gè)事務(wù)請求的鎖模式與當(dāng)前的鎖兼容,InnoDB就將請求的鎖授予該事務(wù);反之如果請求不兼容,則該事務(wù)就等待鎖釋放。

意向鎖是InnoDB自動(dòng)加的,不需要用戶干預(yù)。

對于insert、update、delete,InnoDB會(huì)自動(dòng)給涉及的數(shù)據(jù)加排他鎖(X);對于一般的Select語句,InnoDB不會(huì)加任何鎖,事務(wù)可以通過以下語句給顯示加共享鎖或排他鎖。

共享鎖:select * from table_name where …..lock in share mode

排他鎖:select * from table_name where …..for update

加入共享鎖的例子:

MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法

MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法

利用select ….for update加入排他鎖

MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法

鎖的實(shí)現(xiàn)方式:

InnoDB行鎖是通過給索引項(xiàng)加鎖實(shí)現(xiàn)的,如果沒有索引,InnoDB會(huì)通過隱藏的聚簇索引來對記錄加鎖。

也就是說:如果不通過索引條件檢索數(shù)據(jù),那么InnoDB將對表中所有數(shù)據(jù)加鎖,實(shí)際效果跟表鎖一樣。

行鎖分為三種情形:

Record lock :對索引項(xiàng)加鎖,即鎖定一條記錄。

Gap lock:對索引項(xiàng)之間的‘間隙’、對第一條記錄前的間隙或最后一條記錄后的間隙加鎖,即鎖定一個(gè)范圍的記錄,不包含記錄本身

Next-key Lock:鎖定一個(gè)范圍的記錄并包含記錄本身(上面兩者的結(jié)合)。

注意:InnoDB默認(rèn)級別是repeatable-read級別,所以下面說的都是在RR級別中的。

之前一直搞不懂Gap Lock和Next-key Lock的區(qū)別,直到在網(wǎng)上看到一句話豁然開朗,希望對各位有幫助。

Next-Key Lock是行鎖與間隙鎖的組合,這樣,當(dāng)InnoDB掃描索引記錄的時(shí)候,會(huì)首先對選中的索引記錄加上行鎖(Record Lock),再對索引記錄兩邊的間隙加上間隙鎖(Gap Lock)。如果一個(gè)間隙被事務(wù)T1加了鎖,其它事務(wù)是不能在這個(gè)間隙插入記錄的。

干巴巴的說沒意思,我們來看看具體實(shí)例:

假設(shè)我們有一張表:

+——+———+

| id | age  |

+——+———+

|  1 |    3 |

|  2 |    6 |

|  3 |    9 |

+——+———+

表結(jié)構(gòu)如下:

CREATE TABLE test (
 id int(11) NOT NULL AUTO_INCREMENT,
 age int(11) DEFAULT NULL,
 PRIMARY KEY (id),
 KEY keyname (age)
) ENGINE=InnoDB AUTO_INCREMENT=302 DEFAULT CHARSET=gbk ;

這樣我們age段的索引就分為

(negative infinity, 3],

(3,6],

(6,9],

(9,positive infinity);

我們來看一下幾種情況:

1、當(dāng)事務(wù)A執(zhí)行以下語句:

mysql> select * from fenye where age=6for update ;

不僅使用行鎖鎖住了相應(yīng)的數(shù)據(jù)行,同時(shí)也在兩邊的區(qū)間,(5,6]和(6,9] 都加入了gap鎖。

這樣事務(wù)B就無法在這個(gè)兩個(gè)區(qū)間insert進(jìn)新數(shù)據(jù),但是事務(wù)B可以在兩個(gè)區(qū)間外的區(qū)間插入數(shù)據(jù)。

2、當(dāng)事務(wù)A執(zhí)行

select * from fenye where age=7 for update ;

那么就會(huì)給(6,9]這個(gè)區(qū)間加鎖,別的事務(wù)無法在此區(qū)間插入或更新數(shù)據(jù)。

3、如果查詢的數(shù)據(jù)不再范圍內(nèi),

比如事務(wù)A執(zhí)行 select * from fenye where age=100 for update ;

那么加鎖區(qū)間就是(9,positive infinity)。

小結(jié):

行鎖防止別的事務(wù)修改或刪除,GAP鎖防止別的事務(wù)新增,行鎖和GAP鎖結(jié)合形成的的Next-Key鎖共同解決了RR級別在寫數(shù)據(jù)時(shí)的幻讀問題。

何時(shí)在InnoDB中使用表鎖:

InnoDB在絕大部分情況會(huì)使用行級鎖,因?yàn)槭聞?wù)和行鎖往往是我們選擇InnoDB的原因,但是有些情況我們也考慮使用表級鎖。

1、當(dāng)事務(wù)需要更新大部分?jǐn)?shù)據(jù)時(shí),表又比較大,如果使用默認(rèn)的行鎖,不僅效率低,而且還容易造成其他事務(wù)長時(shí)間等待和鎖沖突。

2、事務(wù)比較復(fù)雜,很可能引起死鎖導(dǎo)致回滾。

死鎖:

我們說過MyISAM中是不會(huì)產(chǎn)生死鎖的,因?yàn)镸yISAM總是一次性獲得所需的全部鎖,要么全部滿足,要么全部等待。而在InnoDB中,鎖是逐步獲得的,就造成了死鎖的可能。

在上面的例子中我們可以看到,當(dāng)兩個(gè)事務(wù)都需要獲得對方持有的鎖才能夠繼續(xù)完成事務(wù),導(dǎo)致雙方都在等待,產(chǎn)生死鎖。

發(fā)生死鎖后,InnoDB一般都可以檢測到,并使一個(gè)事務(wù)釋放鎖回退,另一個(gè)獲取鎖完成事務(wù)。

避免死鎖:

有多種方法可以避免死鎖,這里只介紹常見的三種:

1、如果不同程序會(huì)并發(fā)存取多個(gè)表,盡量約定以相同的順序訪問表,可以大大降低死鎖機(jī)會(huì)。

2、在同一個(gè)事務(wù)中,盡可能做到一次鎖定所需要的所有資源,減少死鎖產(chǎn)生概率;

3、對于非常容易產(chǎn)生死鎖的業(yè)務(wù)部分,可以嘗試使用升級鎖定顆粒度,通過表級鎖定來減少死鎖產(chǎn)生的概率;

感謝各位的閱讀,以上就是“MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!


文章題目:MyIsam與InnoDB引擎的鎖實(shí)現(xiàn)以及避免死鎖產(chǎn)生的方法
網(wǎng)站鏈接:http://weahome.cn/article/pgshse.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部