一張圖徹底搞懂 MySQL 的鎖機制[面試題]
文章導(dǎo)讀
之前分享過一篇有關(guān)MySQL鎖的文章,得到了部分閱讀者的良好反饋,這里在網(wǎng)上搜索了幾道有關(guān)鎖的面試題。
通過看這些面試題,其實都能在這篇文章中找到答案。所以推薦詳細閱讀該文,該文也會不斷更新完善。
1.MySQL中的都有那些瑣?
答:Mysql中鎖的分類按照不同類型的劃分可以分成不同的鎖,按照「鎖的粒度」劃分可以分成:「表鎖、頁鎖、行鎖」;按照「使用的方式」劃分可以分為:「共享鎖」和「排它鎖」;按照思想的劃分:「樂觀鎖」和「悲觀鎖」。
2.MyISAM和InnoDB存儲引擎在鎖上面有什么區(qū)別?
答:MySQL支持表鎖,InnoDB支持行鎖、也支持表鎖。
3.當(dāng)MyISAM存儲引擎發(fā)生鎖競爭時,是如何處理的?
答:
MyISAM存儲引擎中,「假如同時一個讀請求,一個寫請求過來的話,它會優(yōu)先處理寫請求」,因為MyISAM存儲引擎中認為寫請求比都請求重要。 「假如大量的讀寫請求過來,就會導(dǎo)致讀請求長時間的等待,或者"線程餓死",因此MyISAM不適合運用于大量讀寫操作的場景」,這樣會導(dǎo)致長時間讀取不到用戶數(shù)據(jù),用戶體驗感極差。當(dāng)然可以通過設(shè)置low-priority-updates參數(shù),設(shè)置請求鏈接的優(yōu)先級,使得Mysql優(yōu)先處理讀請求。
4.InnoDB存儲引擎支持哪些鎖類型?對應(yīng)的鎖類型是什么情況下會觸發(fā)?
答:
InnoDB中除了有「表鎖」和「行級鎖」的概念,還有單列索引、Gap Lock(間隙鎖)、Next-key Lock鎖。 默認情況下,MySQL是使用的行鎖。 當(dāng)在可重復(fù)讀的情況下,MySQL的鎖是建立在索引列的,如果沒有索引列,則走的是表鎖。 間隙鎖在事務(wù)中做范圍查詢時,會將指定的范圍加鎖。 Next-key Lock是位于單列索引和間隙鎖之間,它會將指定的行進行加鎖,并且會對指定行的兩邊加間隙鎖。
5.InnoDB 行鎖實現(xiàn)都有哪些方式?
答:MySQL中的行鎖有單行索引、間隙鎖和Next-key Lock。
6.如何監(jiān)控MySQL中的鎖情況?
答:
使用show full processlist命令。 show engine innodb status命令。 通過查看MySQL自帶數(shù)據(jù)庫infomation-schema中的INNODB_TRX、INNODB_LOCKS和INNODB_LOCK_WAITS表。
7.如何避免死鎖?
答:
為了在單個innodb表上執(zhí)行多個并發(fā)寫入操作時避免死鎖,可以在事務(wù)開始時,通過為預(yù)期要修改行,使用select …for update語句來獲取必要的鎖,即使這些行的更改語句是在之后才執(zhí)行的在事務(wù)中,如果要更新記錄,應(yīng)該直接申請足夠級別的鎖,即排他鎖,而不應(yīng)先申請共享鎖,更新時在申請排他鎖。因為這時候當(dāng)用戶在申請排他鎖時,其他事務(wù)可能又已經(jīng)獲得了相同記錄的共享鎖。 如果事務(wù)需要修改或鎖定多個表,則應(yīng)在每個事務(wù)中以相同的順序使用加鎖語句。在應(yīng)用中,如果不同的程序會并發(fā)獲取多個表,應(yīng)盡量約定以相同的順序來訪問表,這樣可以大大降低產(chǎn)生死鎖的機會。 通過 select …lock in share mode獲取行的讀鎖后,如果當(dāng)前事務(wù)在需要對該記錄進行更新操作,則很有可能造成死鎖。 改變事務(wù)隔離級別。
8.如何處理死鎖?
答:
通過innodblockwait_timeout來設(shè)置超時時間,一直等待直到超時。 發(fā)起死鎖檢測,發(fā)現(xiàn)死鎖之后,主動回滾死鎖中的事務(wù),不需要其他事務(wù)繼續(xù)。
9.InnoDB是如何處理死鎖的?
答:innodb默認是使用設(shè)置死鎖時間來讓死鎖超時的策略,默認innodblockwait_timeout設(shè)置的時長是50s。
10.什么是悲觀鎖?什么是樂觀鎖?
答:
悲觀鎖是每次在讀數(shù)據(jù)時,都會給數(shù)據(jù)加上鎖,避免其他的讀操作拿到鎖。 樂觀鎖是給數(shù)據(jù)添加一個版本號,通過對比版本號來實現(xiàn)數(shù)據(jù)前后一致性的對比。
11.悲觀鎖和樂觀鎖的區(qū)別?
答:
悲觀鎖:每次去拿數(shù)據(jù)的時候都認為別人會修改,所以每次在拿數(shù)據(jù)的時候都會上鎖,這樣別人想拿這個數(shù)據(jù)都會block直到它拿到鎖。因此,悲觀鎖需要耗時比較的多,跟樂觀鎖比較,悲觀鎖是有數(shù)據(jù)庫自己實現(xiàn)的,用的時候我們直接調(diào)用數(shù)據(jù)的相關(guān)語句就可以悲觀鎖涉及到的另另兩個鎖,他們是共享鎖和排他鎖,共享鎖和排他鎖時悲觀鎖的不同的實現(xiàn),屬于悲觀鎖的范疇。 樂觀鎖是用數(shù)據(jù)版本記錄機制實現(xiàn),這是樂觀鎖最常用的方式,所謂的數(shù)據(jù)版本,為數(shù)據(jù)增加一個版本號的字段,一般是通過為數(shù)據(jù)表增加一個數(shù)據(jù)類型的version字段實現(xiàn),當(dāng)讀取數(shù)據(jù)時,將把二十年字段的值一同讀取出來,數(shù)據(jù)每次更新都需要對version值加一,在我們提交更新的時候,判斷數(shù)據(jù)表對應(yīng)記錄的當(dāng)前版本信息與第一次取出來的version值進行對比,如果數(shù)據(jù)庫的表當(dāng)前版本號魚取出來的version值相等,則給與更新否則認為過期數(shù)據(jù)不給與更新。
12.樂觀鎖有什么優(yōu)點?
答:樂觀鎖雖然叫鎖其實在使用的時候是沒有加鎖,所以執(zhí)行性能高。缺點:會產(chǎn)生ABA的問題,ABA問題指的是有一個變量V初次讀取的時候是A值,并且在準備賦值的時候檢查到他的值還是為A值,會誤認為沒有被修改做為正常的執(zhí)行修改操作,實際上這段時間他的值可能被修改為其他值,之后又被修改為A值。
13.優(yōu)化鎖方面的意見?
答:
使用較低的隔離級別設(shè)計索引,盡量使用索引去訪問數(shù)據(jù),加鎖更加精確,從而減少鎖沖突 選擇合理的事務(wù)大小, 給記錄顯示加鎖時,最好一次性請求足夠級別的鎖。列如,修改數(shù)據(jù)的話,最好申請排他鎖,而不是先申請共享鎖,修改時在申請排他鎖,這樣會導(dǎo)致死鎖 不同的程序訪問一組表的時候,應(yīng)盡量約定一個相同的順序訪問各表,對于一個表而言,盡可能的固定順序的獲取表中的行。這樣大大的減少死鎖的機會。 盡量使用相等條件訪問數(shù)據(jù),這樣可以避免間隙鎖對并發(fā)插入的影響 不要申請超過實際需要的鎖級別 數(shù)據(jù)查詢的時候不是必要,不要使用加鎖。MySQL的MVCC可以實現(xiàn)事務(wù)中的查詢不用加鎖,優(yōu)化事務(wù)性能:MVCC只在committed read(讀提交)和 repeatable read (可重復(fù)讀)兩種隔離級別 對于特定的事務(wù),可以使用表鎖來提高處理速度活著減少死鎖的可能。
推薦閱讀
開發(fā)人員必備的MySQL事務(wù)原理分析與總結(jié)
評論
圖片
表情
