1. 程式人生 > >13.MySQL鎖機制

13.MySQL鎖機制

其他 插入 mysql ble tran 對數 等待 才會 字符型

鎖的分類

  從對數據的類型 (讀\寫)分:

    1.讀鎖(共享鎖):針對同一份數據,多個讀操作可以同時進行而不會互相影響

    2.寫鎖(排它鎖):當前寫操作沒有完成前,它會阻斷其他寫鎖和讀鎖

  從對數據操作的粒度分:

    1.表鎖

    2.行鎖

表鎖(偏讀)

  1.偏向MyISAM存儲引擎,開銷小,加鎖快;無死鎖;鎖的粒度大,發生鎖沖突的概率最高,並發度最低

  2.MyISAM 在執行查詢(SELECT)語句前,會自動給涉及的所有表加讀鎖,在執行更新操作(UPDATE/DELETE/INSERT等)前,

  會自動給涉及的表加寫鎖,這個過程並不需要用戶參與,我們試驗中使用 lock table 是為了模擬並發環境

  加讀鎖   

    1.會話一中A表加讀鎖(lock table tablename read),會話二不鎖任何表

    2.會話一中 可以查詢A表,也只能查詢A表,對A表的寫操作會報錯,對其他的表的讀寫操作也報錯

    3.會話二中,可以讀A表,也可以對其他表進行讀寫,但只對A表的寫操作會阻塞,必須等會話一釋放 A表的讀鎖(unlock tables),會話二才能完成寫操作

  加寫鎖 

    1.連接一,給一張表加 寫鎖,這個連接可以對這張表進行 讀和寫,但是不能訪問其他表

    2.連接二 可以訪問其他未加鎖的表,但是對加了寫鎖的表 的讀 和 寫 會阻塞(即排他),等待連接一中鎖的釋放

簡而言之,就是讀鎖會阻塞寫,但是不會阻塞讀,而寫鎖則會把 讀和寫 都阻塞(對於其他連接而言)

表鎖分析 show status like ‘table%’

行鎖(偏寫)(行鎖出現的前提是在事務中)

  1.偏向 Innodb 存儲引擎,開銷大,加鎖慢;會出現死鎖;鎖的粒度最小,發生鎖沖突的概率最低,並發度也最高

  2.Innodb 和 Myisam最大不同的有兩點:一是只是事務(TRANSACTION);二是采用了行級鎖

  

  3.由於行鎖支持事務,我們復習一下關於事務的知識

    1.事務及其ACID屬性

    2.並發事務 帶來的問題

      1.更新丟失(Lost Update)

      2.臟讀(Dirty Reads)

      3.不可重復讀(Non-Repeatable Reads)

      在事務A的執行過程中,事務B進行了開啟,修改和提交,導致事務A在事務B執行前讀取的數據和事務B執行後讀取的數據不一致

      4.幻讀(Phantom Reads)

      和 不可重復讀 類似,不過不可重復讀針對的列的修改,而幻讀針對的是列的增加

    3.事務隔離級別

  

  4.行鎖定基本演示:事務中對數據的更新才會觸發行鎖,

    如:連接一開啟了事務,在事務中,對表的某一行數據進行更新(此時就把這一行鎖定了)(查詢不會鎖定),

    在該事務提交之前, 連接二發出了update語句,想對被鎖的這一行數據進行更新,此時 連接二的語句就會發生阻塞,

    需要到等待連接一中 事提交,行鎖釋放,才能繼續執行

    但是因為是行鎖,所以連接二對其他行的數據更新是不會受影響的

  5.無索引行鎖升級為表鎖(索引失效)

    當出現行鎖時,如果行鎖鎖定的這一行上面 有字段(如name)建立了索引,如果這個索引失效了(比如字符型不加‘’ where name = 1234),

    那麽行鎖 會自動升級為表鎖,其他行數據的 更新 也會被鎖定,其他連接無法對這個表進行更新

  6.間隙鎖(寧可錯殺,不可錯放)

    當我們使用範圍條件而不是相等相等條件檢索數據時,它會鎖定整個範圍內所有的索引鍵值,即使這個鍵值並不存在

    如:有這樣一段數據,id = 1,id = 3,id = 4...中間少了一個 id = 2,如果此時連接一 開啟一個事務,更新數據當 1<id <4,

    此時Mysql本著寧可錯殺,不可錯放的原則,即使id=2 不存在也會被無情的鎖定,

    連接二想要插入 一條id=2的數據是不行的,會阻塞,等待連接一事務提交,行鎖釋放

  7.如何鎖定一行

    for update可以鎖定某一行,也可以鎖定整張表

    主要是看 select語句後面是否有where,where限定的範圍 即鎖的範圍, select xxx... for update

    如果沒有 where,則鎖定整張表,鎖定之後,其他連接 就無法對鎖定的範圍進行 更新操作

  8.行鎖分析:show status like ‘innodb_row_lock%‘

為什麽說行鎖偏寫,表鎖偏讀,即Myisam偏寫,Innodb偏讀

  Myisam 讀的性能高

  Myisam 的讀寫鎖調用 是寫優先,這也是myisam不適合做寫為主表的引擎。因為寫鎖後,其他線程不能做任何操作,大量的更新會使查詢很難得到鎖,從而造成永久阻塞

  Innodb行鎖是單比查詢比不過,但是innodb支持高並發,支持事務

  在寫多讀少的應用中還是Innodb插入性能更穩定,在並發情況下也能基本保證性能

可以根據系統的讀寫情況 來選擇合適的 Mysql存儲引擎

優化建議

  1.盡可能讓所有數據檢索都通過索引來完成,避免無索引行鎖升級為表鎖

  2.合理設計索引,盡量縮小鎖的範圍

  3.盡可能較少檢索條件,避免間隙鎖

  4.盡量控制事務大小,減少鎖定資源量和時間長度

  5.盡可能低級別事務隔離

頁鎖(了解一下即可)

  1.開銷和加鎖時間介於表鎖和行鎖之間

  2.會出現死鎖

  3.鎖定粒度介於表鎖和行鎖之間,並發度一般

    

  

13.MySQL鎖機制