Mysql中的行級鎖、表級鎖、頁級鎖
在計算機科學中,鎖是在執行多線程時用於強行限制資源訪問的同步機制,即用於在併發控制中保證對互斥要求的知足。sql
在數據庫的鎖機制中介紹過,在DBMS中,能夠按照鎖的粒度把數據庫鎖分爲行級鎖(INNODB引擎)、表級鎖(MYISAM引擎)和頁級鎖(BDB引擎 )。數據庫
行級鎖多線程
行級鎖是Mysql中鎖定粒度最細的一種鎖,表示只針對當前操做的行進行加鎖。行級鎖能大大減小數據庫操做的衝突。其加鎖粒度最小,但加鎖的開銷也最大。行級鎖分爲共享鎖 和 排他鎖。併發
特色ide
開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的機率最低,併發度也最高。性能
表級鎖spa
表級鎖是MySQL中鎖定粒度最大的一種鎖,表示對當前操做的整張表加鎖,它實現簡單,資源消耗較少,被大部分MySQL引擎支持。最常使用的MYISAM與INNODB都支持表級鎖定。表級鎖定分爲表共享讀鎖(共享鎖)與表獨佔寫鎖(排他鎖)。線程
特色索引
開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發出鎖衝突的機率最高,併發度最低。事務
頁級鎖
表級鎖是MySQL中鎖定粒度介於行級鎖和表級鎖中間的一種鎖.表級鎖速度快,但衝突多,行級衝突少,但速度慢。因此取了折衷的頁級,一次鎖定相鄰的一組記錄。BDB支持頁級鎖
特色
開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度通常
MySQL經常使用存儲引擎的鎖機制
MyISAM和MEMORY採用表級鎖(table-level locking)
BDB採用頁面鎖(page-level locking)或表級鎖,默認爲頁面鎖
InnoDB支持行級鎖(row-level locking)和表級鎖,默認爲行級鎖
Innodb中的行鎖與表鎖
前面提到過,在Innodb引擎中既支持行鎖也支持表鎖,那麼何時會鎖住整張表,何時或只鎖住一行呢?
InnoDB行鎖是經過給索引上的索引項加鎖來實現的,這一點MySQL與Oracle不一樣,後者是經過在數據塊中對相應數據行加鎖來實現的。InnoDB這種行鎖實現特色意味着:只有經過索引條件檢索數據,InnoDB才使用行級鎖,不然,InnoDB將使用表鎖!
在實際應用中,要特別注意InnoDB行鎖的這一特性,否則的話,可能致使大量的鎖衝突,從而影響併發性能。
行級鎖都是基於索引的,若是一條SQL語句用不到索引是不會使用行級鎖的,會使用表級鎖。行級鎖的缺點是:因爲須要請求大量的鎖資源,因此速度慢,內存消耗大。
行級鎖與死鎖
MyISAM中是不會產生死鎖的,由於MyISAM老是一次性得到所需的所有鎖,要麼所有知足,要麼所有等待。而在InnoDB中,鎖是逐步得到的,就形成了死鎖的可能。
在MySQL中,行級鎖並非直接鎖記錄,而是鎖索引。索引分爲主鍵索引和非主鍵索引兩種,若是一條sql語句操做了主鍵索引,MySQL就會鎖定這條主鍵索引;若是一條語句操做了非主鍵索引,MySQL會先鎖定該非主鍵索引,再鎖定相關的主鍵索引。 在UPDATE、DELETE操做時,MySQL不只鎖定WHERE條件掃描過的全部索引記錄,並且會鎖定相鄰的鍵值,即所謂的next-key locking。
當兩個事務同時執行,一個鎖住了逐漸索引在等待其餘相關索引,一個鎖定了非主鍵索引,在等待主鍵索引。這樣就會發生死鎖。
發生死鎖後,InnoDB通常均可以檢測到,並使一個事務釋放鎖回退,另外一個獲取鎖完成事務。
有多種方法能夠避免死鎖,這裏只介紹常見的三種
一、若是不一樣程序會併發存取多個表,儘可能約定以相同的順序訪問表,能夠大大下降死鎖機會。
二、在同一個事務中,儘量作到一次鎖定所須要的全部資源,減小死鎖產生機率;
三、對於很是容易產生死鎖的業務部分,能夠嘗試使用升級鎖定顆粒度,經過表級鎖定來減小死鎖產生的機率;