MySQL 鎖的監控及處理


故障模擬

# 添加兩項配置
vi /etc/my.cnf
[mysqld]
autocommit=0
innodb_lock_wait_timeout = 3600

systemctl restart mysqld

# 登錄數據庫
use klvchen;
UPDATE t1 SET k1='av' WHERE id=1;

# 新開一個窗口,再登錄數據庫
use klvchen;
UPDATE t1 SET k1='az' WHERE id=1;
# 此時頁面卡住

(一)看有沒有鎖等待

# 新開一個窗口,登錄數據庫
SHOW  STATUS LIKE 'innodb_row_lock%';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| Innodb_row_lock_current_waits | 1     |        # 當前正在等待鎖的數量;
| Innodb_row_lock_time          | 0     |        # 從系統啟動到現在鎖定總時間長度;
| Innodb_row_lock_time_avg      | 0     |        # 每次等待所花平均時間;
| Innodb_row_lock_time_max      | 0     |        # 從系統啟動到現在等待最長的一次所花的時間長度;
| Innodb_row_lock_waits         | 1     |        # 系統啟動到現在總共等待的次數;
+-------------------------------+-------+

(二)查看哪個事務在等待(被阻塞了)

USE information_schema;
SELECT * FROM information_schema.INNODB_TRX WHERE trx_state='LOCK WAIT'\G;
*************************** 1. row ***************************
                    trx_id: 14597                               # 事務ID號
                 trx_state: LOCK WAIT                           # 當前事務的狀態
               trx_started: 2019-12-21 09:20:25
     trx_requested_lock_id: 14597:32:3:2
          trx_wait_started: 2019-12-21 09:20:25
                trx_weight: 2
       trx_mysql_thread_id: 3                                   # 連接層的,連接線程ID(SHOW PROCESSLIST ===>Id或trx_id )
                 trx_query: UPDATE t1 SET k1='az' WHERE id=1    # 當前被阻塞的操作(一般是要丟給開發的)
       trx_operation_state: starting index read
         trx_tables_in_use: 1
         trx_tables_locked: 1
          trx_lock_structs: 2
     trx_lock_memory_bytes: 1136
           trx_rows_locked: 1
         trx_rows_modified: 0
   trx_concurrency_tickets: 0
       trx_isolation_level: REPEATABLE READ
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 0
          trx_is_read_only: 0
trx_autocommit_non_locking: 0

# 或者你可以簡單地進行查看
select trx_state,trx_started,trx_wait_started,trx_weight,trx_rows_locked,now() from information_schema.innodb_trx;

# 字段說明:
trx_state            事務狀態,有以下幾種狀態:RUNNING、LOCK WAIT、ROLLING BACK 和 COMMITTING
trx_started          事務開始時間
trx_wait_started     事務開始等待的時間
trx_weight           事務的權重
trx_rows_locked      事務鎖住的記錄數,包含標記為 DELETED,並且已經保存到磁盤但對事務不可見的行

(三)查看鎖源,誰鎖的我

SELECT * FROM sys.innodb_lock_waits\G;                          # 被鎖的和鎖定它的之間關系
*************************** 1. row ***************************
                wait_started: 2019-12-21 09:20:25
                    wait_age: 00:01:30
               wait_age_secs: 90
                locked_table: `klvchen`.`t1`                    # 哪張表出現的等待 
                locked_index: GEN_CLUST_INDEX
                 locked_type: RECORD
              waiting_trx_id: 14597                             # 等待的事務(與上個視圖trx_id 對應)
         waiting_trx_started: 2019-12-21 09:20:25
             waiting_trx_age: 00:01:30
     waiting_trx_rows_locked: 1
   waiting_trx_rows_modified: 0
                 waiting_pid: 3                                 # 等待的線程號(與上個視圖trx_mysql_thread_id)
               waiting_query: UPDATE t1 SET k1='az' WHERE id=1
             waiting_lock_id: 14597:32:3:2
           waiting_lock_mode: X
             blocking_trx_id: 14596                             # 鎖源的事務ID 
                blocking_pid: 2                                 # 鎖源的線程號
              blocking_query: NULL
            blocking_lock_id: 14596:32:3:2
          blocking_lock_mode: X
        blocking_trx_started: 2019-12-21 09:20:12
            blocking_trx_age: 00:01:43
    blocking_trx_rows_locked: 5
  blocking_trx_rows_modified: 0
     sql_kill_blocking_query: KILL QUERY 2
sql_kill_blocking_connection: KILL 2

(四)找到鎖源的 thread_id

SELECT * FROM performance_schema.threads WHERE processlist_id=2\G;
*************************** 1. row ***************************
          THREAD_ID: 27
               NAME: thread/sql/one_connection
               TYPE: FOREGROUND
     PROCESSLIST_ID: 2
   PROCESSLIST_USER: root
   PROCESSLIST_HOST: localhost
     PROCESSLIST_DB: klvchen
PROCESSLIST_COMMAND: Sleep
   PROCESSLIST_TIME: 261
  PROCESSLIST_STATE: NULL
   PROCESSLIST_INFO: UPDATE t1 SET k1='av' WHERE id=1
   PARENT_THREAD_ID: 1
               ROLE: NULL
       INSTRUMENTED: YES
            HISTORY: YES
    CONNECTION_TYPE: Socket
       THREAD_OS_ID: 2557

(五)找到鎖源的SQL語句

-- 當前在執行的語句
SELECT * FROM performance_schema.`events_statements_current` WHERE thread_id=27\G;
*************************** 1. row ***************************
              THREAD_ID: 27
               EVENT_ID: 8
           END_EVENT_ID: 8
             EVENT_NAME: statement/sql/update
                 SOURCE: 
            TIMER_START: 16785505578000
              TIMER_END: 16785741560000
             TIMER_WAIT: 235982000
              LOCK_TIME: 126000000
               SQL_TEXT: UPDATE t1 SET k1='av' WHERE id=1
                 DIGEST: c75120019b1993cf2423bd9add827987
            DIGEST_TEXT: UPDATE `t1` SET `k1` = ? WHERE `id` = ? 
         CURRENT_SCHEMA: klvchen
            OBJECT_TYPE: NULL
          OBJECT_SCHEMA: NULL
            OBJECT_NAME: NULL
  OBJECT_INSTANCE_BEGIN: NULL
            MYSQL_ERRNO: 0
      RETURNED_SQLSTATE: 00000
           MESSAGE_TEXT: Rows matched: 1  Changed: 0  Warnings: 0
                 ERRORS: 0
               WARNINGS: 0
          ROWS_AFFECTED: 0
              ROWS_SENT: 0
          ROWS_EXAMINED: 4
CREATED_TMP_DISK_TABLES: 0
     CREATED_TMP_TABLES: 0
       SELECT_FULL_JOIN: 0
 SELECT_FULL_RANGE_JOIN: 0
           SELECT_RANGE: 0
     SELECT_RANGE_CHECK: 0
            SELECT_SCAN: 0
      SORT_MERGE_PASSES: 0
             SORT_RANGE: 0
              SORT_ROWS: 0
              SORT_SCAN: 0
          NO_INDEX_USED: 0
     NO_GOOD_INDEX_USED: 0
       NESTING_EVENT_ID: NULL
     NESTING_EVENT_TYPE: NULL
    NESTING_EVENT_LEVEL: 0

-- 執行語句的歷史
SELECT * FROM performance_schema.`events_statements_history` WHERE thread_id=27\G;

得出結果,丟給開發
表信息
被阻塞的
鎖源SQL

快速方法

方法 一

# 查看有沒有鎖表
SHOW  STATUS LIKE 'innodb_row_lock%';

# 獲取正在等待的語句,kill 鎖源語句,鎖源ID,鎖源線程ID
select a.waiting_query  as '被鎖住的SQL語句', a.sql_kill_blocking_connection, a.blocking_pid, b.THREAD_ID AS '鎖源線程ID'
from
(SELECT waiting_query, sql_kill_blocking_connection, blocking_pid FROM sys.innodb_lock_waits) a, 
(SELECT THREAD_ID, PROCESSLIST_ID FROM performance_schema.threads WHERE processlist_id IN (SELECT blocking_pid FROM sys.innodb_lock_waits)) b 
where a.blocking_pid = b.PROCESSLIST_ID order by b.THREAD_ID;

# 查出鎖源 SQL 語句
SELECT THREAD_ID, SQL_TEXT AS '鎖源當前執行的SQL語句' ,CURRENT_SCHEMA AS '數據庫' FROM performance_schema.`events_statements_current` WHERE thread_id IN (SELECT THREAD_ID FROM performance_schema.threads pt WHERE processlist_id IN (SELECT blocking_pid FROM sys.innodb_lock_waits));

方法 二

# 查看有沒有鎖表
SHOW  STATUS LIKE 'innodb_row_lock%';

# 獲取正在等待的語句,kill 鎖源語句,鎖源ID
SELECT waiting_query as '被鎖住的SQL語句',sql_kill_blocking_connection,blocking_pid FROM sys.innodb_lock_waits;

# 查找對應關系
SELECT THREAD_ID AS '鎖源線程ID', PROCESSLIST_ID FROM performance_schema.threads WHERE processlist_id IN (SELECT blocking_pid FROM sys.innodb_lock_waits);

# 查出鎖源 SQL 語句
SELECT THREAD_ID, SQL_TEXT AS '鎖源當前執行的SQL語句' ,CURRENT_SCHEMA AS '數據庫' FROM performance_schema.`events_statements_current` WHERE thread_id IN (SELECT THREAD_ID FROM performance_schema.threads pt WHERE processlist_id IN (SELECT blocking_pid FROM sys.innodb_lock_waits));


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM