mysql鎖知識小了解

1、概述

mysql的鎖分爲表鎖和行鎖兩種,其中myisam引擎用的是表鎖, innoDB默認的使用是行鎖, 其餘狀況是表鎖。
兩種鎖的優缺點:
 表級鎖:加鎖速度快,開銷小。不會出現死鎖的狀況,粒度大,發生鎖衝突的機率最高,併發度最低。
 行級鎖:加鎖速度慢,開銷大。 會出現死鎖的狀況,粒度小, 發生鎖衝突的機率最小,併發度最高
  頁面鎖:介於以上二者之間

 沒法肯定哪一種鎖更合適:
表級鎖更適合查詢爲主,只有少許按索引更新數據的應用,如web應用。
行級鎖適合有大量索引併發更新少許不一樣的數據,同時有併發查詢的應用,如一些在線的事物系統。

2、MyIsam存儲引擎
只支持表鎖。
查詢表級鎖的爭用狀況:
table_locks_waited table_locks_immediate 

1.  mysql> show status like 'table%'; mysql

2.  +-----------------------+-------+ web

3.  | Variable_name         | Value | sql

4.  +-----------------------+-------+ 數據庫

5.  | Table_locks_immediate | 2979  | 數據結構

6.  | Table_locks_waited    | 0     | 併發


2.一、表級鎖的鎖模式
兩種模式:表共享讀鎖,表獨佔寫鎖
分析:
讀鎖不會阻塞其餘用戶對同一張表的讀請求,但會阻塞對同表的寫請求;
對錶的寫請求,會阻塞對同表的讀操做和寫操做
myisam的讀操做和寫操做之間,以及寫操做之間是互相串行的。

2.二、如何加表鎖
myisam引擎在執行查詢語句以前會自動的給涉及到的表加上讀鎖,執行更新操做的語句以前會自動加上寫鎖,這個過程不須要用戶干預。
加鎖代碼以下

1.  Lock tables orders read local, order_detail read local; 性能

2.  Select sum(total) from orders; spa

3.  Select sum(subtotal) from order_detail; 線程

4.  Unlock tables; 設計


2.三、併發插入

 Myisam也支持查詢和插入同時進行的併發操做:存儲引擎有一個系統變量concurrent_insert, 專門控制併發插入的行爲。值爲 0 1 2

concurrent_insert == 0 :不容許併發的插入

concurrent_insert == 1 :(默認值1)若是該表沒有空洞(表的中間沒有被刪除的行),容許邊讀邊插入。

concurrent_insert == 2 :不管有沒有空洞都運行在表的末尾插入數據


2.四、鎖調度

Myisam的讀寫操做是互斥的,讀寫操做是串行的。

若是一個進程請求表的讀鎖,同時另外一個線程請求表的寫鎖,那麼寫的進程會先得到鎖,就算是讀的進程先到鎖的等待隊列,若是有寫進程

那麼也是寫進程得到鎖,由於mysql默認認爲寫進程比讀的進程更加劇要。 能夠經過一些設置來調節這些級別:

SET LOW_PRIORITY_UPDATES = 1 :更新請求的優先級下降

還能夠經過調節系統參數來調節讀寫的衝突:max_write_lock_count, 當讀鎖的阻塞數量達到這個值的時候,就會把寫請求的優先級下降,給讀的進程得到鎖的機會

3、InnoDB存儲引擎

InnoDB和Myisam最大的不一樣就是

一、事物支持

二、行級鎖

3.一、事物以及其的屬性

  • 原子性:對數據的修改要麼執行,要麼所有不執行
  • 一致性:事物開始和完成時,數據都應該保持一致的狀態,數據結構的完整性都是一致的。
  • 隔離性:數據庫系統提供必定的隔離機制,保證事物在不收外部併發操做影響的獨立環境進行,意味着事物處理過程當中是不對外可見的。
  • 持久性:事物完成後,對於數據的修改是永久性的,即時出現系統故障會保持

相對於串行處理來講,併發事物處理能力能大大的加強數據庫資源的利用率,提升數據庫系統的吞吐量,能夠支持更多的用戶量,可是也帶來必定的問題:
一、更新丟失:兩個事物選擇同一行,而後都是基於最後選定的值更新,每一個事物都不知道其餘事物的存在。最後的事物就會覆蓋前面的事物更新的數據。
二、髒讀:一個事物正在對一條記錄作修改,在這個事物完成並提交以前,此時這條數據就是不一致的狀態;有一條事物同時來讀取這條記錄,並進行下一步的處理,就會產生未提交的數據依賴關係。叫作髒讀。
三、不可重複讀:一個事物在讀取某個數據後的某個時間,再次讀取之前讀過的數據,卻發現讀出的數據發生了變換,或者刪除了某些記錄,這種現象叫作「不可重複讀」。
四、幻讀:一條事物按照必定的條件檢索出之前讀取的數據,卻發現檢索出了其餘事物插入的符合條件的數據。這種現象稱爲 幻讀。

3.二、事物隔離級別
事物處理帶來的問題中,「更新丟失」 應該是能夠徹底避免的。防止數據更新丟失 不能所有靠數據庫的事物機制來控制,須要應用程序對更新的數據加上必要的鎖來控制。 其他的「髒讀, 幻讀, 不可重複讀」 都是數據庫的讀一致性的問題,那麼必須由數據庫提供必定的事物隔離機制來解決。解決方式基本分爲兩種:
  • 讀取數據前,對其加上鎖。
  • 不加任何鎖機制,經過必定的機制生成數據請求時間點的一致性數據快照,並用這個快照提供必定級別的(語句, 事物)的一致性讀取,從用戶的角度來看,好像是數據庫能夠提供一份數據的多個版本,所以能夠叫作數據庫的多版本控制(多版本數據庫)。

數據庫的隔離機制越高,併發反作用越小, 可是付出的性能代價也是越高,由於事物隔離實質上就是對事物進行串行進行。

爲了解決併發和隔離的矛盾,提供了4個隔離級別, 每一個級別的隔離程度不一樣,容許出現的反作用也不一樣,根據業務要求來決定。

隔離級別
讀數據一致性
髒讀
不可重複讀
幻讀
未提交讀
最低級別
已提交讀
語句級
可重複讀
事物級
可序列化
最高級別(事物級)

3.三、InnoDB鎖
共享鎖:容許一個事物去讀一行,阻止其餘事物得到相同數據集的排他鎖
排他鎖:容許獲的排他鎖的事物更新數據,阻止其餘事物取得相同數據集的共享讀鎖和排他寫鎖。

InnoDB爲了行鎖和表鎖共存,實現多粒度的鎖機制,還有兩種內部使用的意向鎖,這兩種意向鎖都是表鎖
意向共享鎖:事物打算給數據行加上行共享鎖,事物在給一個數據行加共享鎖前必須得到該表的意向共享鎖
意向排他鎖:事物打算給數據行加上行排他鎖,事物在給一個數據行加排他鎖前必須得到該表的意向排他鎖

InnoDB的實現方式
行鎖是經過索引上的索引項上加鎖來實現的:只有經過索引條件檢索數據才使用行級鎖,不然,InnoDB將使用表搜

3.四、InnoDB死鎖
死鎖的例子:
步驟1:
用戶1:select * from table1 where id = 1;
用戶2:select * from table2 where id = 1;
步驟2:
用戶1:select * from table2 where id = 1; (此時在步驟1中的用戶2中已經取得了排他鎖,故等待。。。)
用戶2:select * from table1 where id = 1;  (死鎖)

發生死鎖後,InnoDB 通常都能自動檢測到,並使一個事物釋放鎖並回退,另外一個事物得到鎖,繼續完成事物。可是在涉及到外部鎖,或涉及到表鎖的狀況下,InnoDB並不能自動檢測到死鎖,須要經過設置鎖等待超時參數 innodb_lock_wait_timeout 來解決,須要說明的是, 這個參數並非只用來解決死鎖的問題,在併發訪問比較高的狀況下,若是大量事物因沒法當即得到所需的鎖而掛起,會佔用大量的計算機資源,形成嚴重的性能問題,甚至拖垮數據庫,咱們經過設置合適的鎖等待超時值,能夠避免這種狀況的發生。



此文是經過了解mysql的鎖的基本工做原理:
一、讓咱們在業務數據處理的流程上作出好的設計,能夠大部分避免沒法解開死鎖致使應用掛掉。
舉個例子:不一樣的程序會併發存取某個表,儘可能約定好程序以相同的順序來訪問表來下降死鎖概率。
二、同時瞭解一下經常使用的檢測參數值,追蹤mysql的鎖狀態。
相關文章
相關標籤/搜索