日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

MySQL中的读锁和写锁

發(fā)布時(shí)間:2023/12/3 数据库 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL中的读锁和写锁 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載自?MySQL中的讀鎖和寫(xiě)鎖

?

在數(shù)據(jù)庫(kù)的鎖機(jī)制中介紹過(guò),數(shù)據(jù)的鎖主要用來(lái)保證數(shù)據(jù)的一致性的,數(shù)據(jù)庫(kù)的鎖從鎖定的粒度上可以分為表級(jí)鎖、行級(jí)鎖和頁(yè)級(jí)鎖。在我的博客中重點(diǎn)介紹過(guò)MySQL數(shù)據(jù)庫(kù)的行級(jí)鎖。這篇文章主要來(lái)介紹一下MySQL數(shù)據(jù)庫(kù)中的表級(jí)鎖。

本文提到的讀鎖和寫(xiě)鎖都是MySQL數(shù)據(jù)庫(kù)的MyISAM引擎支持的表鎖的。而對(duì)于行級(jí)鎖的共享讀鎖和互斥寫(xiě)鎖請(qǐng)閱讀MySQL中的共享鎖與排他鎖。我習(xí)慣在描述表鎖的時(shí)候按照讀寫(xiě)來(lái)區(qū)分,在表述行鎖的時(shí)候按照共享和互斥來(lái)區(qū)分。其實(shí)無(wú)論是表鎖還是行鎖。共享鎖指的就是讀鎖!互斥鎖、排他鎖、獨(dú)占鎖值得都是寫(xiě)鎖。

重點(diǎn)知識(shí)回顧

MySQL的鎖機(jī)制比較簡(jiǎn)單,其最顯著的特點(diǎn)是不同的存儲(chǔ)引擎支持不同的鎖機(jī)制。比如,MyISAM和MEMORY存儲(chǔ)引擎采用的是表級(jí)鎖(table-level locking);BDB 存儲(chǔ)引擎采用的是頁(yè)面鎖(page-level locking),但也支持表級(jí)鎖;InnoDB存儲(chǔ)引擎既支持行級(jí)鎖(row-level locking),也支持表級(jí)鎖,但默認(rèn)情況下是采用行級(jí)鎖。

  • 表級(jí)鎖:開(kāi)銷(xiāo)小,加鎖快;不會(huì)出現(xiàn)死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。

  • 行級(jí)鎖:開(kāi)銷(xiāo)大,加鎖慢;會(huì)出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。

  • 頁(yè)面鎖:開(kāi)銷(xiāo)和加鎖時(shí)間界于表鎖和行鎖之間;會(huì)出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。

MyISAM表鎖

MyISAM 存儲(chǔ)引擎只支持表鎖,MySQL 的表級(jí)鎖有兩種模式:表共享讀鎖(Table Read Lock)和表獨(dú)占寫(xiě)鎖(Table Write Lock)。

對(duì)于讀操作,可以增加讀鎖,一旦數(shù)據(jù)表被加上讀鎖,其他請(qǐng)求可以對(duì)該表再次增加讀鎖,但是不能增加寫(xiě)鎖。(當(dāng)一個(gè)請(qǐng)求在讀數(shù)據(jù)時(shí),其他請(qǐng)求也可以讀,但是不能寫(xiě),因?yàn)橐坏┝硗庖粋€(gè)線程寫(xiě)了數(shù)據(jù),就會(huì)導(dǎo)致當(dāng)前線程讀取到的數(shù)據(jù)不是最新的了。這就是不可重復(fù)讀現(xiàn)象)

對(duì)于寫(xiě)操作,可以增加寫(xiě)鎖,一旦數(shù)據(jù)表被加上寫(xiě)鎖,其他請(qǐng)求無(wú)法在對(duì)該表增加讀鎖和寫(xiě)鎖。(當(dāng)一個(gè)請(qǐng)求在寫(xiě)數(shù)據(jù)時(shí),其他請(qǐng)求不能執(zhí)行任何操作,因?yàn)樵诋?dāng)前事務(wù)提交之前,其他的請(qǐng)求無(wú)法看到本次修改的內(nèi)容。這有可能產(chǎn)生臟讀、不可重復(fù)讀和幻讀)

讀鎖和寫(xiě)鎖都是阻塞鎖。

如果t1對(duì)數(shù)據(jù)表增加了寫(xiě)鎖,這是t2請(qǐng)求對(duì)數(shù)據(jù)表增加寫(xiě)鎖,這時(shí)候t2并不會(huì)直接返回,而是會(huì)一直處于阻塞狀態(tài),直到t1釋放了對(duì)表的鎖,這時(shí)t2便有可能加鎖成功,獲取到結(jié)果。

表鎖的加鎖/解鎖方式

MyISAM 在執(zhí)行查詢語(yǔ)句(SELECT)前,會(huì)自動(dòng)給涉及的所有表加讀鎖,在執(zhí)行更新操作 (UPDATE、DELETE、INSERT?等)前,會(huì)自動(dòng)給涉及的表加寫(xiě)鎖,這個(gè)過(guò)程并不需要用戶干預(yù),因此,用戶一般不需要直接用LOCK TABLE命令給MyISAM表顯式加鎖。

如果用戶想要顯示的加鎖可以使用以下命令:

鎖定表:LOCK TABLES tbl_name {READ | WRITE},[ tbl_name {READ | WRITE},…] 解鎖表:UNLOCK TABLES

在用?LOCK TABLES?給表顯式加表鎖時(shí),必須同時(shí)取得所有涉及到表的鎖。

在執(zhí)行?LOCK TABLES?后,只能訪問(wèn)顯式加鎖的這些表,不能訪問(wèn)未加鎖的表;

如果加的是讀鎖,那么只能執(zhí)行查詢操作,而不能執(zhí)行更新操作。

在自動(dòng)加鎖的情況下也基本如此,MyISAM 總是一次獲得 SQL 語(yǔ)句所需要的全部鎖。這也正是 MyISAM 表不會(huì)出現(xiàn)死鎖(Deadlock Free)的原因。

對(duì)表test_table增加讀鎖:

LOCK TABLES test_table READ UNLOCK test_table

對(duì)表test_table增加寫(xiě)鎖

LOCK TABLES test_table WRITE UNLOCK test_table
  • 當(dāng)使用 LOCK TABLES 時(shí),不僅需要一次鎖定用到的所有表,而且,同一個(gè)表在 SQL 語(yǔ)句中出現(xiàn)多少次,就要通過(guò)與 SQL 語(yǔ)句中相同的別名鎖定多少次,否則也會(huì)出錯(cuò)!

比如如下SQL語(yǔ)句:

select a.first_name,b.first_name, from actor a,actor b where a.first_name = b.first_name;

該Sql語(yǔ)句中,actor表以別名的方式出現(xiàn)了兩次,分別是a,b,這時(shí)如果要在該Sql執(zhí)行之前加鎖就要使用以下Sql:

lock table actor as a read,actor as b read;

并發(fā)插入

上文 到過(guò) MyISAM 表的讀和寫(xiě)是串行的,但這是就總體而言的。在一定條件下,MyISAM表也支持查詢和插入操作的并發(fā)進(jìn)行。 MyISAM存儲(chǔ)引擎有一個(gè)系統(tǒng)變量concurrent_insert,專門(mén)用以控制其并發(fā)插入的行為,其值分別可以為0、1或2。

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

當(dāng)concurrent_insert設(shè)置為1時(shí),如果MyISAM表中沒(méi)有空洞(即表的中間沒(méi)有被刪除的 行),MyISAM允許在一個(gè)進(jìn)程讀表的同時(shí),另一個(gè)進(jìn)程從表尾插入記錄。這也是MySQL 的默認(rèn)設(shè)置。

當(dāng)concurrent_insert設(shè)置為2時(shí),無(wú)論MyISAM表中有沒(méi)有空洞,都允許在表尾并發(fā)插入記錄。

可以利用MyISAM存儲(chǔ)引擎的并發(fā)插入特性,來(lái)解決應(yīng)用中對(duì)同一表查詢和插入的鎖爭(zhēng)用。

MyISAM的鎖調(diào)度

前面講過(guò),MyISAM 存儲(chǔ)引擎的讀鎖和寫(xiě)鎖是互斥的,讀寫(xiě)操作是串行的。那么,一個(gè)進(jìn)程請(qǐng)求某個(gè) MyISAM 表的讀鎖,同時(shí)另一個(gè)進(jìn)程也請(qǐng)求同一表的寫(xiě)鎖,MySQL 如何處理呢??

答案是寫(xiě)進(jìn)程先獲得鎖。

不僅如此,即使讀請(qǐng)求先到鎖等待隊(duì)列,寫(xiě)請(qǐng)求后到,寫(xiě)鎖也會(huì)插到讀鎖請(qǐng)求之前!這是因?yàn)?MySQL 認(rèn)為寫(xiě)請(qǐng)求一般比讀請(qǐng)求要重要。這也正是 MyISAM 表不太適合于有大量更新操作和查詢操作應(yīng)用的原因,因?yàn)?大量的更新操作會(huì)造成查詢操作很難獲得讀鎖,從而可能永遠(yuǎn)阻塞。這種情況有時(shí)可能會(huì)變得非常糟糕!

幸好我們可以通過(guò) 一些設(shè)置來(lái)調(diào)節(jié) MyISAM 的調(diào)度行為。

通過(guò)指定啟動(dòng)參數(shù)low-priority-updates,使MyISAM引擎默認(rèn)給予讀請(qǐng)求以優(yōu)先的權(quán)利。?

通過(guò)執(zhí)行命令SET LOWPRIORITYUPDATES=1,使該連接發(fā)出的更新請(qǐng)求優(yōu)先級(jí)降低。?

通過(guò)指定INSERT、UPDATE、DELETE語(yǔ)句的LOW_PRIORITY屬性,降低該語(yǔ)句的優(yōu)先級(jí)。

另外,MySQL也 供了一種折中的辦法來(lái)調(diào)節(jié)讀寫(xiě)沖突,即給系統(tǒng)參數(shù)max_write_lock_count?設(shè)置一個(gè)合適的值,當(dāng)一個(gè)表的讀鎖達(dá)到這個(gè)值后,MySQL就暫時(shí)將寫(xiě)請(qǐng)求的優(yōu)先級(jí)降低, 給讀進(jìn)程一定獲得鎖的機(jī)會(huì)。

總結(jié)

數(shù)據(jù)庫(kù)中的鎖從鎖定的粒度上分可以分為行級(jí)鎖、頁(yè)級(jí)鎖和表級(jí)鎖。

MySQL的MyISAM引擎支持表級(jí)鎖。

表級(jí)鎖分為兩種:共享讀鎖、互斥寫(xiě)鎖。這兩種鎖都是阻塞鎖。

可以在讀鎖上增加讀鎖,不能在讀鎖上增加寫(xiě)鎖。在寫(xiě)鎖上不能增加寫(xiě)鎖。

默認(rèn)情況下,MySql在執(zhí)行查詢語(yǔ)句之前會(huì)加讀鎖,在執(zhí)行更新語(yǔ)句之前會(huì)執(zhí)行寫(xiě)鎖。

如果想要顯示的加鎖/解鎖的花可以使用LOCK TABLES和UNLOCK來(lái)進(jìn)行。

在使用LOCK TABLES之后,在解鎖之前,不能操作未加鎖的表。

在加鎖時(shí),如果顯示的指明是要增加讀鎖,那么在解鎖之前,只能進(jìn)行讀操作,不能執(zhí)行寫(xiě)操作。

如果一次Sql語(yǔ)句要操作的表以別名的方式多次出現(xiàn),那么就要在加鎖時(shí)都指明要加鎖的表的別名。

MyISAM存儲(chǔ)引擎有一個(gè)系統(tǒng)變量concurrent_insert,專門(mén)用以控制其并發(fā)插入的行為,其值分別可以為0、1或2。

由于讀鎖和寫(xiě)鎖互斥,那么在調(diào)度過(guò)程中,默認(rèn)情況下,MySql會(huì)本著寫(xiě)鎖優(yōu)先的原則。可以通過(guò)low-priority-updates來(lái)設(shè)置。

參考資料

《深入淺出MySQL》

?

總結(jié)

以上是生活随笔為你收集整理的MySQL中的读锁和写锁的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。