004--MySQL中鎖的面試題總結(jié)

什么是鎖?MySQL 中提供了幾類鎖命黔?

鎖是實(shí)現(xiàn)數(shù)據(jù)庫并發(fā)控制的重要手段呜呐,可以保證數(shù)據(jù)庫在多人同時操作時能夠正常運(yùn)行。MySQL 提供了全局鎖悍募、行級鎖蘑辑、表級鎖。其中 InnoDB
支持表級鎖和行級鎖坠宴,MyISAM 只支持表級鎖洋魂。

什么是死鎖?

是指兩個或兩個以上的進(jìn)程在執(zhí)行過程中喜鼓,因爭奪資源而造成的一種互相等待的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去副砍。此時稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的過程稱為死鎖庄岖。

死鎖是指兩個或兩個以上的進(jìn)程在執(zhí)行過程中豁翎,因爭奪資源而造成的一種互相等待的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去。此時稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖隅忿,這些永遠(yuǎn)在互相等待的過程稱為死鎖心剥。

常見的死鎖案例有哪些?

  • 將投資的錢拆封幾份借給借款人背桐,這時處理業(yè)務(wù)邏輯就要把若干個借款人一起鎖住 select * from xxx where id in (xx,xx,xx) for update优烧。
  • 批量入庫,存在則更新链峭,不存在則插入畦娄。解決方法 insert into tab(xx,xx) on duplicate key update xx='xx'。

如何處理死鎖熏版?

對待死鎖常見的兩種策略:

  • 通過 innodb lock wait_timeout 來設(shè)置超時時間纷责,一直等待直到超時;
  • 發(fā)起死鎖檢測撼短,發(fā)現(xiàn)死鎖之后再膳,主動回滾死鎖中的某一個事務(wù),讓其它事務(wù)繼續(xù)執(zhí)行曲横。

如何查看死鎖喂柒?

  • 使用命令 show engine innodb status 查看最近的一次死鎖不瓶。
  • InnoDB Lock Monitor 打開鎖監(jiān)控,每 15s 輸出一次日志灾杰。使用完畢后建議關(guān)閉蚊丐,否則會影響數(shù)據(jù)庫性能。

如何避免死鎖艳吠?

  • 為了在單個 InnoDB 表上執(zhí)行多個并發(fā)寫入操作時避免死鎖麦备,可以在事務(wù)開始時通過為預(yù)期要修改的每個元祖(行)使用 SELECT ... FOR UPDATE 語句來獲取必要的鎖,即使這些行的更改語句是在之后才執(zhí)行的昭娩。
  • 在事務(wù)中凛篙,如果要更新記錄,應(yīng)該直接申請足夠級別的鎖栏渺,即排他鎖呛梆,而不應(yīng)先申請共享鎖、更新時再申請排他鎖磕诊,因?yàn)檫@時候當(dāng)用戶再申請排他鎖時填物,其他事務(wù)可能又已經(jīng)獲得了相同記錄的共享鎖,從而造成鎖沖突霎终,甚至死鎖
  • 如果事務(wù)需要修改或鎖定多個表滞磺,則應(yīng)在每個事務(wù)中以相同的順序使用加鎖語句。在應(yīng)用中神僵,如果不同的程序會并發(fā)存取多個表雁刷,應(yīng)盡量約定以相同的順序來訪問表,這樣可以大大降低產(chǎn)生死鎖的機(jī)會
  • 通過 SELECT ... LOCK IN SHARE MODE 獲取行的讀鎖后保礼,如果當(dāng)前事務(wù)再需要對該記錄進(jìn)行更新操作沛励,則很有可能造成死鎖。
  • 改變事務(wù)隔離級別炮障。

InnoDB 默認(rèn)是如何對待死鎖的目派?

InnoDB 默認(rèn)是使用設(shè)置死鎖時間來讓死鎖超時的策略,默認(rèn) innodb lock wait_timeout 設(shè)置的時長是 50s胁赢。

如何開啟死鎖檢測企蹭?

設(shè)置 innodb deadlock detect 設(shè)置為 on 可以主動檢測死鎖,在 Innodb 中這個值默認(rèn)就是 on 開啟的狀態(tài)智末。

什么是全局鎖谅摄?它的應(yīng)用場景有哪些?

全局鎖就是對整個數(shù)據(jù)庫實(shí)例加鎖系馆,它的典型使用場景就是做全庫邏輯備份送漠。
這個命令可以使整個庫處于只讀狀態(tài)。使用該命令之后由蘑,數(shù)據(jù)更新語句闽寡、數(shù)據(jù)定義語句代兵、更新類事務(wù)的提交語句等操作都會被阻塞。

什么是共享鎖爷狈?

共享鎖又稱讀鎖 (read
lock)植影,是讀取操作創(chuàng)建的鎖。其他用戶可以并發(fā)讀取數(shù)據(jù)涎永,但任何事務(wù)都不能對數(shù)據(jù)進(jìn)行修改(獲取數(shù)據(jù)上的排他鎖)思币,直到已釋放所有共享鎖。當(dāng)如果事務(wù)對讀鎖進(jìn)行修改操作羡微,很可能會造成死鎖支救。

什么是排它鎖?

排他鎖 exclusive lock(也叫 writer lock)又稱寫鎖拷淘。

若某個事物對某一行加上了排他鎖,只能這個事務(wù)對其進(jìn)行讀寫指孤,在此事務(wù)結(jié)束之前启涯,其他事務(wù)不能對其進(jìn)行加任何鎖,其他進(jìn)程可以讀取,不能進(jìn)行寫操作恃轩,需等待其釋放结洼。

排它鎖是悲觀鎖的一種實(shí)現(xiàn),在上面悲觀鎖也介紹過叉跛。

若事務(wù) 1 對數(shù)據(jù)對象 A 加上 X 鎖松忍,事務(wù) 1 可以讀 A 也可以修改 A,其他事務(wù)不能再對 A 加任何鎖筷厘,直到事物 1 釋放 A
上的鎖鸣峭。這保證了其他事務(wù)在事物 1 釋放 A 上的鎖之前不能再讀取和修改 A。排它鎖會阻塞所有的排它鎖和共享鎖酥艳。

使用全局鎖會導(dǎo)致什么問題?

如果在主庫備份,在備份期間不能更新幢竹,業(yè)務(wù)停擺峻厚,所以更新業(yè)務(wù)會處于等待狀態(tài)。

如果在從庫備份骤铃,在備份期間不能執(zhí)行主庫同步的 binlog拉岁,導(dǎo)致主從延遲。

如何處理邏輯備份時惰爬,整個數(shù)據(jù)庫不能插入的情況喊暖?

如果使用全局鎖進(jìn)行邏輯備份就會讓整個庫成為只讀狀態(tài),幸好官方推出了一個邏輯備份工具 MySQLdump 來解決了這個問題补鼻,只需要在使用 MySQLdump
時哄啄,使用參數(shù) -single-transaction 就會在導(dǎo)入數(shù)據(jù)之前啟動一個事務(wù)來保證數(shù)據(jù)的一致性雅任,并且這個過程是支持?jǐn)?shù)據(jù)更新操作的。

如何設(shè)置數(shù)據(jù)庫為全局只讀鎖咨跌?

使用命令 flush tables with read lock(簡稱 FTWRL)就可以實(shí)現(xiàn)設(shè)置數(shù)據(jù)庫為全局只讀鎖沪么。

除了 FTWRL 可以設(shè)置數(shù)據(jù)庫只讀外,還有什么別的方法锌半?

除了使用 FTWRL 外禽车,還可以使用命令 set global readonly=true 設(shè)置數(shù)據(jù)庫為只讀。

FTWRL 和 set global readonly=true 有什么區(qū)別刊殉?

FTWRL 和 set global readonly=true 都是設(shè)置整個數(shù)據(jù)庫為只讀狀態(tài)殉摔,但他們最大的區(qū)別就是,當(dāng)執(zhí)行 FTWRL
的客戶端斷開之后记焊,整個數(shù)據(jù)庫會取消只讀逸月,而 set global readonly=true 會一直讓數(shù)據(jù)處于只讀狀態(tài)。

如何實(shí)現(xiàn)表鎖遍膜?

MySQL 里標(biāo)記鎖有兩種:表級鎖碗硬、元數(shù)據(jù)鎖(meta data lock)簡稱 MDL。表鎖的語法是 lock tables t read/write瓢颅。

可以用 unlock tables 主動釋放鎖恩尾,也可以在客戶端斷開的時候自動釋放。lock tables
語法除了會限制別的線程的讀寫外挽懦,也限定了本線程接下來的操作對象翰意。

對于 InnoDB 這種支持行鎖的引擎,一般不使用 lock tables 命令來控制并發(fā)信柿,畢竟鎖住整個表的影響面還是太大冀偶。

MDL:不需要顯式使用,在訪問一個表的時候會被自動加上渔嚷。

MDL 的作用:保證讀寫的正確性蔫磨。

在對一個表做增刪改查操作的時候,加 MDL 讀鎖圃伶;當(dāng)要對表做結(jié)構(gòu)變更操作的時候堤如,加 MDL 寫鎖。

讀鎖之間不互斥窒朋,讀寫鎖之間搀罢,寫鎖之間是互斥的,用來保證變更表結(jié)構(gòu)操作的安全性侥猩。

MDL 會直到事務(wù)提交才會釋放榔至,在做表結(jié)構(gòu)變更的時候,一定要小心不要導(dǎo)致鎖住線上查詢和更新欺劳。

悲觀鎖和樂觀鎖有什么區(qū)別唧取?

顧名思義铅鲤,就是很悲觀,每次去拿數(shù)據(jù)的時候都認(rèn)為別人會修改枫弟,所以每次在拿數(shù)據(jù)的時候都會上鎖邢享,這樣別人想拿這個數(shù)據(jù)就會 block
直到它拿到鎖。正因?yàn)槿绱说^鎖需要耗費(fèi)較多的時間骇塘,另外與樂觀鎖相對應(yīng)的,悲觀鎖是由數(shù)據(jù)庫自己實(shí)現(xiàn)了的韩容,要用的時候款违,我們直接調(diào)用數(shù)據(jù)庫的相關(guān)語句就可以了。

說到這里群凶,由悲觀鎖涉及到的另外兩個鎖概念就出來了插爹,它們就是共享鎖與排它鎖。共享鎖和排它鎖是悲觀鎖的不同的實(shí)現(xiàn)请梢,它倆都屬于悲觀鎖的范疇递惋。

樂觀鎖是用數(shù)據(jù)版本(Version)記錄機(jī)制實(shí)現(xiàn),這是樂觀鎖最常用的一種實(shí)現(xiàn)方式溢陪。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個版本標(biāo)識睛廊,一般是通過為數(shù)據(jù)庫表增加一個數(shù)字類型的
version 字段來實(shí)現(xiàn)形真。當(dāng)讀取數(shù)據(jù)時,將 version 字段的值一同讀出超全,數(shù)據(jù)每更新一次咆霜,對此 version 值加
1。當(dāng)我們提交更新的時候嘶朱,判斷數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息與第一次取出來的version值進(jìn)行比對蛾坯,如果數(shù)據(jù)庫表當(dāng)前版本號與第一次取出來的 version
值相等,則予以更新疏遏,否則認(rèn)為是過期數(shù)據(jù)脉课。

比如: 1、數(shù)據(jù)庫表三個字段财异,分別是id倘零、value、version select id,value,version from t where id=#{id} 2戳寸、每次更新表中的value字段時呈驶,為了防止發(fā)生沖突,需要這樣操作

update t
set value=2,version=version+1
where id=#{id} and version=#{version}

樂觀鎖有什么優(yōu)點(diǎn)和缺點(diǎn)疫鹊?

因?yàn)闆]有加鎖所以樂觀鎖的優(yōu)點(diǎn)就是執(zhí)行性能高袖瞻。它的缺點(diǎn)就是有可能產(chǎn)生 ABA 的問題司致,ABA 問題指的是有一個變量 V 初次讀取的時候是 A
值,并且在準(zhǔn)備賦值的時候檢查到它仍然是 A 值聋迎,會誤以為沒有被修改會正常的執(zhí)行修改操作脂矫,實(shí)際上這段時間它的值可能被改了其他值,之后又改回為 A
值砌庄,這個問題被稱為 ABA 問題羹唠。

InnoDB 存儲引擎有幾種鎖算法?

  • Record Lock — 單個行記錄上的鎖娄昆;
  • Gap Lock — 間隙鎖佩微,鎖定一個范圍,不包括記錄本身萌焰;
  • Next-Key Lock — 鎖定一個范圍哺眯,包括記錄本身。

InnoDB 如何實(shí)現(xiàn)行鎖扒俯?

行級鎖是 MySQL 中粒度最小的一種鎖奶卓,他能大大減少數(shù)據(jù)庫操作的沖突。

INNODB 的行級鎖有共享鎖(S LOCK)和排他鎖(X
LOCK)兩種撼玄。共享鎖允許事物讀一行記錄夺姑,不允許任何線程對該行記錄進(jìn)行修改。排他鎖允許當(dāng)前事物刪除或更新一行記錄掌猛,其他線程不能操作該記錄盏浙。

共享鎖:SELECT ... LOCK IN SHARE MODE,MySQL
會對查詢結(jié)果集中每行都添加共享鎖荔茬,前提是當(dāng)前線程沒有對該結(jié)果集中的任何行使用排他鎖废膘,否則申請會阻塞。

排他鎖:select * from t where id=1 for update慕蔚,其中 id 字段必須有索引丐黄,MySQL
會對查詢結(jié)果集中每行都添加排他鎖,在事物操作中孔飒,任何對記錄的更新與刪除操作會自動加上排他鎖灌闺。前提是當(dāng)前沒有線程對該結(jié)果集中的任何行使用排他鎖或共享鎖,否則申請會阻塞坏瞄。

優(yōu)化鎖方面你有什么建議菩鲜?

  • 盡量使用較低的隔離級別。
  • 精心設(shè)計索引惦积, 并盡量使用索引訪問數(shù)據(jù)接校, 使加鎖更精確, 從而減少鎖沖突的機(jī)會。
  • 選擇合理的事務(wù)大小蛛勉,小事務(wù)發(fā)生鎖沖突的幾率也更小鹿寻。
  • 給記錄集顯示加鎖時,最好一次性請求足夠級別的鎖诽凌。比如要修改數(shù)據(jù)的話毡熏,最好直接申請排他鎖,而不是先申請共享鎖侣诵,修改時再請求排他鎖痢法,這樣容易產(chǎn)生死鎖。
  • 不同的程序訪問一組表時杜顺,應(yīng)盡量約定以相同的順序訪問各表财搁,對一個表而言,盡可能以固定的順序存取表中的行躬络。這樣可以大大減少死鎖的機(jī)會尖奔。
  • 盡量用相等條件訪問數(shù)據(jù),這樣可以避免間隙鎖對并發(fā)插入的影響穷当。
  • 不要申請超過實(shí)際需要的鎖級別提茁。
  • 除非必須,查詢時不要顯示加鎖馁菜。 MySQL 的 MVCC 可以實(shí)現(xiàn)事務(wù)中的查詢不用加鎖茴扁,優(yōu)化事務(wù)性能;MVCC 只在 COMMITTED READ(讀提交)和 REPEATABLE READ(可重復(fù)讀)兩種隔離級別下工作汪疮。
  • 對于一些特定的事務(wù)峭火,可以使用表鎖來提高處理速度或減少死鎖的可能。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铲咨,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蜓洪,更是在濱河造成了極大的恐慌纤勒,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隆檀,死亡現(xiàn)場離奇詭異摇天,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)恐仑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門泉坐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人裳仆,你說我怎么就攤上這事腕让。” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵纯丸,是天一觀的道長偏形。 經(jīng)常有香客問我,道長觉鼻,這世上最難降的妖魔是什么俊扭? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮坠陈,結(jié)果婚禮上萨惑,老公的妹妹穿的比我還像新娘。我一直安慰自己仇矾,他們只是感情好庸蔼,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著若未,像睡著了一般朱嘴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粗合,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天萍嬉,我揣著相機(jī)與錄音,去河邊找鬼隙疚。 笑死壤追,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的供屉。 我是一名探鬼主播行冰,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼伶丐!你這毒婦竟也來了悼做?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤哗魂,失蹤者是張志新(化名)和其女友劉穎肛走,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體录别,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朽色,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了组题。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葫男。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖崔列,靈堂內(nèi)的尸體忽然破棺而出梢褐,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布利职,位于F島的核電站趣效,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏猪贪。R本人自食惡果不足惜跷敬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望热押。 院中可真熱鬧西傀,春花似錦、人聲如沸桶癣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牙寞。三九已至饺鹃,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間间雀,已是汗流浹背悔详。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惹挟,地道東北人茄螃。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像连锯,于是被迫代替她去往敵國和親归苍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容