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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL数据库:锁机制

發(fā)布時間:2024/9/30 数据库 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL数据库:锁机制 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

當數(shù)據(jù)庫中多個事務并發(fā)存取同一數(shù)據(jù)的時候,若對并發(fā)操作不加控制就可能會讀取和存儲不正確的數(shù)據(jù),破壞數(shù)據(jù)庫的一致性。MySQL鎖機制的基本工作原理就是,事務在修改數(shù)據(jù)庫之前,需要先獲得相應的鎖,獲得鎖的事務才可以修改數(shù)據(jù);在該事務操作期間,這部分的數(shù)據(jù)是鎖定,其他事務如果需要修改數(shù)據(jù),需要等待當前事務提交或回滾后釋放鎖。

按照不同的分類方式,鎖的種類可以分為以下幾種:

(1)按鎖的粒度劃分:表級鎖、行級鎖、頁級鎖;?

(2)按鎖的類型劃分:共享鎖(S鎖)、排他鎖(X鎖);

(3)按鎖的使用策略劃分:樂觀鎖、悲觀鎖;

?

一、Mysql中的表級鎖、行級鎖、頁級鎖:

(1)表級鎖:最大粒度的鎖級別,發(fā)生鎖沖突的概率最高,并發(fā)度最低,但開銷小,加鎖快,不會出現(xiàn)死鎖;

(2)行級鎖:最小粒度的所級別,發(fā)生鎖沖突的概率最小,并發(fā)度最高,但開銷大,加鎖慢,會發(fā)生死鎖,行鎖是作用在索引的;

(3)頁級鎖:鎖粒度界于表級鎖和行級鎖之間,對表級鎖和行級鎖的折中,并發(fā)度一般。開銷和加鎖時間也界于表鎖和行鎖之間,會出現(xiàn)死鎖;

不同的存儲引擎支持不同的鎖機制:

(1)InnoDB存儲引擎支持行級鎖和表級鎖,默認情況下使用行級鎖,但只有通過索引進行查詢數(shù)據(jù),才使用行級鎖,否就使用表級鎖。

(2)MyISAM和MEMORY存儲引擎采用的是表級鎖;

(3)BDB存儲引擎使用的是頁面鎖,但也支持表級鎖;

?

二、InnoDB的鎖機制:

1、InnoDb行鎖的類型:

InnoDB實現(xiàn)了以下兩種類型的行鎖:

  • 共享鎖(S鎖、讀鎖):多個事務可以對同一數(shù)據(jù)行共享一把S鎖,但只能進行讀不能修改;
  • 排它鎖(X鎖、寫鎖):一個事務獲取排它鎖之后,可以對鎖定范圍內(nèi)的數(shù)據(jù)行執(zhí)行寫操作,在鎖定期間,其他事務不能再獲取這部分數(shù)據(jù)行的鎖(共享鎖、排它鎖),只允許獲取到排它鎖的事務進行更新數(shù)據(jù)。

對于update,delete,insert 操作,InnoDB會自動給涉及的數(shù)據(jù)行加排他鎖;對于普通SELECT語句,InnoDB不會加任何鎖。

2、InnoDB的表鎖:意向鎖

而且因為InnoDB引擎允許行鎖和表鎖共存,實現(xiàn)多粒度的鎖機制,但是表鎖和行鎖雖然鎖定范圍不同,但是會相互沖突。當你要加表鎖時,勢必要先遍歷該表的所有記錄,判斷是否有排他鎖。這種遍歷檢查的方式顯然是一種低效的方式,MySQL引入了意向鎖,來檢測表鎖和行鎖的沖突。

意向鎖也是表級鎖,分為讀意向鎖(IS鎖)和寫意向鎖(IX鎖)。當事務要在記錄上加上行鎖時,則先在表上加上對應的意向鎖。之后事務如果想進行鎖表,只要先判斷是否有意向鎖存在,存在時則可快速返回該表不能啟用表鎖,否則就需要等待,提高效率

意向鎖是InnoDB自動加的,不需要用戶干預。

其中,四種鎖的兼容性如下:

鎖模式XIXSIS
X沖突沖突沖突沖突
IX沖突兼容沖突兼容
S沖突沖突兼容兼容
IS沖突兼容兼容兼容

如果一個事務請求的鎖模式與當前的鎖兼容,InnoDB就請求的鎖授予該事務;反之,如果兩者鎖不兼容,該事務就要等待鎖釋放。

3、InnoDB的加鎖方法:

上面說過,對于普通的select語句,InnoDB不會加任何鎖,但是事務可以通過以下語句顯示給記錄集添加共享鎖或排他鎖:

(1)select …… for update:排它鎖

select * from table for update 語句:目的是在執(zhí)行這個 select 查詢語句的時候,會將對應的索引訪問條目進行上排他鎖(X 鎖),并且查到后的數(shù)據(jù)只允許自己來修改。

使用場景:為了讓確保自己查找到的數(shù)據(jù)一定是最新數(shù)據(jù),并且查找到后的數(shù)據(jù)值允許自己來修改,此時就需要用到select for update語句;

性能分析:select for update語句相當于一個update語句。在業(yè)務繁忙的情況下,如果事務沒有及時地commit或者rollback可能會造成事務長時間的等待,從而影響數(shù)據(jù)庫的并發(fā)使用效率。

(2)select …… lock in share mode:共享鎖:

select *?from table?lock in share mode 語句:給查找的數(shù)據(jù)加一個共享鎖(S 鎖)的功能,允許其他的事務也對該數(shù)據(jù)上 S鎖,但是不能夠允許對該數(shù)據(jù)進行修改。

使用場景:為了確保自己查詢的數(shù)據(jù)不會被其他事務正在修改,也就是確保自己查詢到的數(shù)據(jù)是最新的數(shù)據(jù),并且不允許其他事務來修改數(shù)據(jù)。與select for update不同的是,本事務在查找完之后不一定能去更新數(shù)據(jù),因為有可能其他事務也對同數(shù)據(jù)集使用了 in share mode 的方式加上了S鎖;

性能分析:select lock in share mode 語句是一個給查找的數(shù)據(jù)上一個共享鎖(S 鎖)的功能,它允許其他的事務也對該數(shù)據(jù)上S鎖,但是不能夠允許對該數(shù)據(jù)進行修改。如果不及時的commit 或者rollback 也可能會造成大量的事務等待。

4、InnoDB行鎖的實現(xiàn)與臨鍵鎖:

InnoDB的行鎖是通過給索引上的索引項加鎖來實現(xiàn)的。只有通過索引檢索數(shù)據(jù),才能使用行鎖,否則將使用表鎖。

在InnoDB中,為了解決幻讀的現(xiàn)象,引入了臨鍵鎖(next-key)根據(jù)索引,劃分為一個個左開右閉的區(qū)間。當進行范圍查詢的時候,若命中索引且能夠檢索到數(shù)據(jù),則鎖住記錄所在的區(qū)間和它的下一個區(qū)間。

其實臨鍵鎖(Next-Key)?=?記錄鎖(Record Locks)?+?間隙鎖(Gap Locks)

  • 間隙鎖:當使用范圍查詢而不是精準查詢進行檢索數(shù)據(jù),并請求共享或排它鎖時,InnoDB會給符合范圍條件的已有數(shù)據(jù)記錄的索引項加鎖;對于鍵值在條件范圍內(nèi)但并不存在的記錄,叫做間隙(GAP)。
  • 記錄鎖:當使用唯一索引,且記錄存在的精準查詢時,使用記錄鎖

具體的使用體現(xiàn)在哪里呢?如下圖所示:

(1)范圍查詢,記錄存在,使用臨鍵鎖

(2)當記錄不存在時(不論是等值查詢,還是范圍查詢),臨建鎖將退化成間隙鎖

(3)當條件是精準匹配(即為等值查詢時)且記錄存在時,并且是唯一索引,臨鍵鎖退化成記錄鎖:

(4)當條件是精準匹配(即為等值查詢時)且記錄存在,但不是唯一索引時,使用臨鍵鎖有精準值的數(shù)據(jù)會增加記錄鎖?和 精準值前后的區(qū)間的數(shù)據(jù)會增加間隙鎖

3、利用鎖機制解決并發(fā)問題:

通過對InnoDB不同鎖類型的特性分析,可以利用鎖解決臟讀、不可重復讀、幻讀:

  • X鎖解決臟讀

  • S鎖解決不可重復讀

  • 臨鍵鎖解決幻讀

4、分析數(shù)據(jù)庫中行鎖情況的命令:

mysql> show status like 'innodb_row_lock%';

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

| Variable_name | Value |

| Innodb_row_lock_current_waits | 0 |

| Innodb_row_lock_time | 76100 |

| Innodb_row_lock_time_avg | 10871 |

| Innodb_row_lock_time_max | 20552 |

| Innodb_row_lock_waits | 7 |

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

Innodb_row_lock_current_waits:當前等待鎖的數(shù)量

Innodb_row_lock_time:系統(tǒng)啟動到現(xiàn)在鎖定的總時間長度(重要)

Innodb_row_lock_time_avg:每次等待所花平均時間(重要)

Innodb_row_lock_time_max:系統(tǒng)啟動到現(xiàn)在 等待最長的一次所花的時間

Innodb_row_lock_waits:系統(tǒng)啟動到現(xiàn)在 總共等待的次數(shù)(重要)

當?shù)却螖?shù)很高,而且每次等待時長也不小的時候,我們就需要分析系統(tǒng)中為什么會有如此多的等待,然后根據(jù)分析結果著手指定優(yōu)化計劃

?

三、MyISAM的鎖機制:

MyISAM存儲引擎使用表級鎖,表級鎖兩種模式:表共享讀鎖、表獨占寫鎖。MyISAM在執(zhí)行查詢語句前,會自動給涉及的所有表加讀鎖,在執(zhí)行增刪改查操作前,會自動給涉及的表加寫鎖。讀鎖會阻塞寫鎖,但不會阻塞讀鎖,而寫鎖則會把寫鎖和讀鎖都阻塞。

1、MyISAM的鎖調(diào)度:

MyISAM默認情況下,認為寫請求一般比讀請求要重要,如果有讀寫請求同時進行的話,MyISAM將會優(yōu)先執(zhí)行寫操作,即使讀請求比寫請求先到達鎖等待隊列,寫鎖請求也會插到讀鎖請求之前!這也是MyISAM不適合做寫為主的引擎的原因。這樣MyISAM表在進行大量的更新操作時,會造成查詢操作很難獲得讀鎖,從而導致查詢阻塞。

我們可以通過一些設置來調(diào)節(jié)MyISAM的調(diào)度行為:

  • 通過指定啟動參數(shù)low-priority-updates,使MyISAM引擎默認給予讀請求以優(yōu)先的權利。
  • 通過執(zhí)行命令SET LOW_PRIORITY_UPDATES=1,使該連接發(fā)出的更新請求優(yōu)先級降低。
  • 通過指定INSERT、UPDATE、DELETE語句的LOW_PRIORITY屬性,降低該語句的優(yōu)先級。

上面3種方法都是要么更新優(yōu)先,要么查詢優(yōu)先的方法。這里要說明的就是,不要盲目的給mysql設置為讀優(yōu)先,因為一些需要長時間運行的查詢操作,也會使寫進程“餓死”。只有根據(jù)你的實際情況,來決定設置哪種操作優(yōu)先。但這些方法還是沒有從根本上同時解決查詢和更新的問題。

在一個有大數(shù)據(jù)量高并發(fā)的mysql里,我們還可采用另一種策略來進行優(yōu)化,那就是通過mysql讀寫分離來實現(xiàn)負載均衡,這樣可避免優(yōu)先哪一種操作從而可能導致另一種操作的堵塞。

2、并發(fā)插入:

一般情況下,當數(shù)據(jù)庫表有一個讀鎖時,其它進程無法對此表進行更新操作,但在一定條件下,MyISAM表也支持查詢和插入操作的并發(fā)進行。MyISAM存儲引擎有一個系統(tǒng)變量concurrent_insert,可以用來控制其并發(fā)插入的行為,其值分別可以為0、1或2。

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

當concurrent_insert設置為1時,如果MyISAM表中沒有空洞(即表的中間沒有被刪除的行),MyISAM允許在一個進程讀表的同時,另一個進程從表尾插入記錄。這也是MyISAM的默認設置。

當concurrent_insert設置為2時,無論MyISAM表中有沒有空洞,都允許在表尾并發(fā)插入記錄。

3、表級鎖情況分析命令:

【查看哪些表被加鎖了】mysql > show open tables;

【查詢表級鎖爭用情況分析】mysql> show status like 'tables%';

mysql> show open tables;

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

| DATABASE | TABLE | In_use | Name_locked |

| dbtest | book | 1 | 0 |

| dbtest | mylock| 1 | 0 |

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

參數(shù)說明:

(1)Database:含有該表的數(shù)據(jù)庫。

(2)Table:表名稱。

(3)In_use:表當前被查詢使用的次數(shù)。如果該數(shù)為零,則表是打開的,但是當前沒有被使用。

(4)Name_locked:表名稱是否被鎖定。名稱鎖定用于取消表或?qū)Ρ磉M行重命名等操作。

mysql> show status like 'tables%';

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

| Variable_name | TABLE |

| Table_locks_immediate | 105 |

| Table_locks_waited | 1 |

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

這里有兩個狀態(tài)變量記錄MySQL內(nèi)部表級鎖定的情況,兩個變量說明如下:

(1)Table_locks_immediate: 產(chǎn)生表級鎖定的次數(shù),表示可以立即獲取鎖的查詢次數(shù),每立即獲取鎖值加1

(2)Table_locks_waited: 出現(xiàn)表級鎖定爭用而發(fā)生等待的次數(shù)(不能立即獲取鎖的次數(shù),每等待一次鎖值加1),此值高則說明存在著較嚴重的表級鎖定爭用情況。

?

總結

以上是生活随笔為你收集整理的MySQL数据库:锁机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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