1. 程式人生 > >mysql加鎖分析

mysql加鎖分析

  1. 分析場景
    1.1 工具:mysql5.5.53,在windows開啟兩個mysql命令列,m1、m2、m3,m1執行更新、刪除操作,m2查詢,m3查詢事務
    1.2 表結構:兩個欄位,一個id,一個price
    1.3 刪除SQL:delete from t1 where id=x limit 1
    1.4 隔離級別
    # 設定m1、m2隔離級別為RC
    set session tx_isolation='read-committed';
    # 檢視m1、m2隔離級別是否設定成功
    select @@session.tx_isolation;
    
  2. 分析開始
    2.1
    # 建立t1表,id是主鍵,price是唯一鍵,使用innodb引擎
    create table t1(id int(20) not null auto_increment,price int(10) not null,primary key(id),unique key(price))engine=innodb default charset=utf8mb4 collate=utf8mb4_general_ci;
    # m1插入1條資料
    insert into t1(id,price) values(8,88888);
    # m1、m2查詢結果
    select * from t1;
    +----+-------+
    | id | price |
    +----+-------+
    |  8 | 88888 |
    +----+-------+
    # m1開啟事務,執行刪除
    begin;
    delete from t1 where id=8 limit 1;
    # m3查詢事務
    ① select * from information_schema.innodb_trx\G;
    ② show engine innodb status\G;
    ------------
    TRANSACTIONS
    ------------
    Trx id counter 258C35
    Purge done for trx's n:o < 258C33 undo n:o < 0
    History list length 766
    LIST OF TRANSACTIONS FOR EACH SESSION:
    ---TRANSACTION 0, not started # m3事務未開啟
    MySQL thread id 3, OS thread handle 0x9ec0, query id 637 localhost 127.0.0.1 root
    show engine innodb status
    ---TRANSACTION 258C31, not started # m2事務未開啟
    MySQL thread id 2, OS thread handle 0x9f84, query id 631 localhost 127.0.0.1 root
    ---TRANSACTION 258C34, ACTIVE 29 sec # m1事務開啟,已持續29秒
    2 lock struct(s), heap size 320, 1 row lock(s), undo log entries 1 # 2個鎖結構體,堆區佔用320KB,1個X鎖,1個回滾記錄
    MySQL thread id 1, OS thread handle 0xa2d0, query id 636 localhost 127.0.0.1 root
    --------
    # m1查詢(當前讀)
    select * from t1;
    empty set;
    # m2查詢有資料,m1提交後,m2就查詢不到資料(幻讀)
    select * from t1;
    +----+-------+
    | id | price |
    +----+-------+
    |  8 | 88888 |
    +----+-------+
    
    2.2
    # 建立t2表,id是唯一鍵,price是主鍵,使用innodb引擎
    create table t2(id int(20) not null ,price int(10) not null,primary key(price),unique key(id))engine=innodb default charset=utf8mb4 collate=utf8mb4_general_ci;
    # m1插入1條資料
    insert into t2(id,price) values(1,10);
    # m1開啟事務,執行刪除
    begin;
    delete from t2 where id=1;
    # m3查詢事務
    ① select * from information_schema.innodb_trx\G;
    *************************** 1. row ***************************
                    trx_id: 258C49
                 trx_state: RUNNING
               trx_started: 2018-10-10 16:49:46
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 4
       trx_mysql_thread_id: 2
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 0
          trx_lock_structs: 3
     trx_lock_memory_bytes: 320
           trx_rows_locked: 2 # 兩個行鎖,一個二級索引的X鎖,一個主鍵的X鎖
    trx_rows_modified: 1
    trx_concurrency_tickets: 0
    trx_isolation_level: READ COMMITTED
    trx_unique_checks: 1
    trx_foreign_key_checks: 1
    trx_last_foreign_key_error: NULL
    trx_adaptive_hash_latched: 0
    trx_adaptive_hash_timeout: 10000
    1 rows in set (0.00 sec)
    
    2.3
    # 建立t3表,id是普通索引,price是主鍵,使用innodb引擎
    create table t3(id int(20) not null ,price int(10) not null,primary key(price),key(id))engine=innodb default charset=utf8mb4 collate=utf8mb4_general_ci;
    # m1插入4條資料
    insert into t3(id,price) values(1,10),(1,20),(1,30),(1,40);
    # m1開啟事務,執行刪除
    begin;
    delete from t3 where id=1;
    # m3查詢事務
    ① select * from information_schema.innodb_trx\G;
    *************************** 1. row ***************************
                    trx_id: 258C59
                 trx_state: RUNNING
               trx_started: 2018-10-10 17:11:31
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 6
       trx_mysql_thread_id: 2
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 0
          trx_lock_structs: 2
     trx_lock_memory_bytes: 320
           trx_rows_locked: 4 # 4行被鎖定,實際應該有8個,4個普通索引X鎖,4個主鍵X鎖
         trx_rows_modified: 4
    trx_concurrency_tickets: 0
       trx_isolation_level: READ COMMITTED
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
    trx_last_foreign_key_error: NULL
    trx_adaptive_hash_latched: 0
    trx_adaptive_hash_timeout: 10000
    1 row in set (0.00 sec)
    
    2.4
    # 建立t4表,id無索引,price是主鍵,使用innodb引擎
    create table t4(id int(20) not null ,price int(10) not null,primary key(price))engine=innodb default charset=utf8mb4 collate=utf8mb4_general_ci;
    # m1插入5條資料
    insert into t4(id,price) values(1,10),(1,20),(1,30),(1,40),(2,50);
    # m1開啟事務,執行刪除
    begin;
    delete from t4 where id=1;
    # m3查詢事務
    ① select * from information_schema.innodb_trx\G;
    ② 查詢事務id:SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX  WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();
    *************************** 1. row ***************************
                    trx_id: 258C61
                 trx_state: RUNNING
               trx_started: 2018-10-10 17:21:22
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 6
       trx_mysql_thread_id: 2
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 0
          trx_lock_structs: 2
     trx_lock_memory_bytes: 320
           trx_rows_locked: 4 # 4個行鎖,實際上是5個行鎖,mysql資料引擎層會對所有行加X鎖,mysql服務層會對不符合條件的解鎖(使用了semi-consistent read)
         trx_rows_modified: 4
    trx_concurrency_tickets: 0
       trx_isolation_level: READ COMMITTED
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
    trx_last_foreign_key_error: NULL
    trx_adaptive_hash_latched: 0
    trx_adaptive_hash_timeout: 10000
    1 row in set (0.00 sec)
    
    2.5 在RR隔離級別下,2.1、2.2加鎖情況相同,2.3、2.4會加上間隙鎖,鎖預設不會提前釋放
    2.6 死鎖
    執行sql順序(id為主鍵):
    m1:delete from t1 where id=14;
    m2:delete from t1 where id=13;
    m1:delete from t1 where id=13;
    m2:delete from t1 where id=14;
    ------------------------
    LATEST DETECTED DEADLOCK
    ------------------------
    181011 10:21:21
    *** (1) TRANSACTION:
    TRANSACTION 258CB6, ACTIVE 68 sec starting index read
    mysql tables in use 1, locked 1
    LOCK WAIT 3 lock struct(s), heap size 320, 2 row lock(s), undo log entries 1
    MySQL thread id 2, OS thread handle 0xa2d0, query id 985 localhost 127.0.0.1 root updating
    delete from t1 where id=13
    *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 0 page no 163855 n bits 72 index `PRIMARY` of table `trx`.`t1` trx id 258CB6 lock_mode X 		locks rec but not gap waiting
    Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
    0: len 4; hex 8000000d; asc     ;;
    1: len 6; hex 000000258cb4; asc    %  ;;
    2: len 7; hex 1b000380022cea; asc      , ;;
    3: len 4; hex 80000309; asc     ;;
    
    *** (2) TRANSACTION:
    TRANSACTION 258CB4, ACTIVE 154 sec starting index read, thread declared inside InnoDB 500
    mysql tables in use 1, locked 1
    3 lock struct(s), heap size 320, 2 row lock(s), undo log entries 1
    MySQL thread id 3, OS thread handle 0x9f84, query id 986 localhost 127.0.0.1 root updating
    delete from t1 where id=14
    *** (2) HOLDS THE LOCK(S):
    RECORD LOCKS space id 0 page no 163855 n bits 72 index `PRIMARY` of table `trx`.`t1` trx id 258CB4 lock_mode X 		locks rec but not gap
    Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
    0: len 4; hex 8000000d; asc     ;;
    1: len 6; hex 000000258cb4; asc    %  ;;
    2: len 7; hex 1b000380022cea; asc      , ;;
    3: len 4; hex 80000309; asc     ;;
    
    *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 0 page no 163855 n bits 72 index `PRIMARY` of table `trx`.`t1` trx id 258CB4 lock_mode X 	locks rec but not gap waiting
    Record lock, heap no 4 PHYSICAL RECORD: n_fields 4; compact format; info bits 32
    0: len 4; hex 8000000e; asc     ;;
    1: len 6; hex 000000258cb6; asc    %  ;;
    2: len 7; hex 1c000380132b35; asc      +5;;
    3: len 4; hex 8000029a; asc     ;;
    
    *** WE ROLL BACK TRANSACTION (2)