Mysql之Innodb鎖場景

mysql鎖分類

  基於鎖的屬性分類:共享鎖(讀鎖)、排他鎖(寫鎖)

  基於鎖的粒度分類:行級鎖(innodb)、表鎖(innodb、myisam)、頁級鎖(innodb引擎)、記錄鎖、間隙鎖、臨建鎖。

  mysql中的絕大部分鎖都是悲觀鎖,按照粒度可以分爲行鎖和表鎖:

  行鎖:

    共享鎖:當讀取一行記錄的時候,爲了防止別人修改,則需要添加S鎖

    排它鎖:當修改一行記錄的時候,爲了防止別人同時進行修改,則需要添加X鎖    

 

X

S

X

不兼容

不兼容

S

不兼容

兼容

    記錄鎖:添加在行索引上的鎖

    間隙鎖:鎖定範圍是索引記錄之間的間隙,針對可重複讀以上隔離級別

    臨鍵鎖:記錄鎖+間隙鎖

  表鎖:

    意向鎖:在獲取某行的鎖之前,必須要獲取表的鎖,分爲意向共享鎖,意向排它鎖

    自增鎖:對自增字段所採用的特殊表級鎖。

  鎖模式的含義:

    IX:意向排它鎖

    X:鎖定記錄本身和記錄之前的間隙(重點用)

    S:鎖定記錄本身和記錄之前的間隙

    X,REC_NOT_GAP:只鎖定記錄本身(重點用)

    S,REC_NOT_GAP:只鎖定記錄本身

    X,GAP:間隙鎖,不鎖定記錄本身(重點用)

    S,GAP:間隙鎖,不鎖定記錄本身

    X,GAP,INSERT_INTENTION:插入意向鎖

  監控鎖:     

show engine innodb status\G  //顯示鎖

  加鎖場景:

       

  分情況來說主要是RR和RC的區別:

  先介紹RR下的查詢鎖場景

    查詢格式:

    1. select * from table for update
    2. select * from table where id ='10' for update
    3. select * from table where name ='10' for update 
  1. RR+表無顯式主鍵沒有索引 

    初始化sql: 

      create table t1(id int default null, name char(20) default null); 

      insert into t1 values ( 10, '10' ),(20,'20' ),(30, '30’) ;

    結論: 

      查詢1和查詢2(id不是索引列)加鎖一致: 

      加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞), 所以鎖的是表,插入新數據超時,爲了組織幻讀問題。

  2.RR+表有顯式主鍵沒有索引 

    初始化sql: 

      create table t2(id int primary key not null, name char(20) default null); 

      insert into t2 values ( 10, '10' ),(20,'20' ),(30, '30’) ;

    結論: 

      查詢1:加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞), 

      查詢2:加的是:id=10的行鎖,保證10的主鍵不能再插入了

  3.RR+表無顯式主鍵有索引 

    初始化sql: 

      create table t3(id int default  null, name char(20) default null); 

      create index idx_id on  t3 (id); 

      insert into t3 values ( 10, '10' ),(20,'20' ),(30, '30’) ;

    結論: 

      查詢1(鎖的row_id):加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞), 

      查詢2:加的是:1.臨鍵鎖:(-∞,10],2.索引:10 ,3.間隙鎖:(10,20),減少幻讀的可能,插入小於20不允許。

  4.RR+表無顯式主鍵有唯一索引 

    初始化sql: 

      create table t4(id int default  null, name char(20) default null); 

      create unique idx_id on  tt (id); 

      insert into t4 values ( 10, '10' ),(20,'20' ),(30, '30’) ;

    結果: 

      查詢1(鎖的row_id):加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞), 

      查詢2:加的是: 行鎖:10被鎖定

   5.RR+表有顯式主鍵有索引 

    初始化sql: 

      create table t5(id int not null, name char(20) default null,primary key(id),key idx_name(name)); 

      create unique idx_id on  tt (id); 

      insert into t5 values ( 10, '10' ),(20,'20' ),(30, '30’) ;

    結果: 

      查詢1(鎖的row_id):加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞);以及10 20 30 的行鎖 

      查詢2:加的是: 行鎖 

      查詢3:加的是: 

          臨鍵鎖:(-∞,10], 

          索引:10 

          間隙鎖:(10,20), 

     6.RR+表有顯式主鍵有唯一索引 

      初始化sql:

        create table t6(id int not null,name char(20) default null,primary key(id) , nique key idx_name(name); 

        insert into t6 values ( 10, '10' ),(20,'20' ),(30, '30’) ;

      結果: 

        查詢1(鎖的row_id):加的是:加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞);以及10 20 30 的行鎖 

        查詢2:加的是: 行鎖  

  RC情況下查詢1和2---都是行鎖(因爲臨建鎖和間隙鎖都是解決幻讀問題) 

    1.RC+表無顯式主鍵沒有索引 

    2.RC+表有顯式主鍵沒有索引 

    3.RC+表無顯式主鍵有索引 

    4.RC+表無顯式主鍵有唯一索引 

    5.RC+表有顯式主鍵有索引 

    6.RC+表有顯式主鍵有唯一索引

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章