亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解MySQL中如何定位阻塞語句

 更新時間:2023年07月17日 08:48:59   作者:ZhanLi  
MySQL?阻塞是指在并發(fā)訪問?MySQL?數(shù)據(jù)庫時,某個事務占用了資源并且長時間不釋放,導致其他事務無法執(zhí)行或執(zhí)行緩慢的情況,那如何排查和定位阻塞語句呢,下面來分析下吧

前言

MySQL 阻塞是指在并發(fā)訪問 MySQL 數(shù)據(jù)庫時,某個事務占用了資源并且長時間不釋放,導致其他事務無法執(zhí)行或執(zhí)行緩慢的情況。

MySQL 阻塞可能會導致數(shù)據(jù)庫性能下降,甚至出現(xiàn)死鎖等問題,需要馬上進行處理。

在 MySQL中,線程阻塞可能是由于以下原因導致:

1、鎖沖突:如果兩個或者多個線程同時請求同一個資源(栗如:同一行或者同一個表),其中一個將被阻塞,直到其他線程釋放鎖;

2、長事務:如果一個事務占用鎖的時間過長,可能會導致其它事務長時間等待甚至是超時;

3、死鎖:如果兩個線程或者更多的線程相互等待對方的資源,將會發(fā)生死鎖(Deadlock),進而導致語句的執(zhí)行阻塞。

如何排查和定位阻塞語句呢,下面來分析下?

MySQL

面對阻塞的語句如何查看呢?

首先我們來模擬2個阻塞的場景,然后使用命令來排查定位。

準備數(shù)據(jù)

CREATE TABLE `t_user` (
  `id` int(11) NOT NULL,
  `name` varchar(16) NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t_user values(1,  "小明",12);
insert into t_user values(2, "小紅",20);
insert into t_user values(3, "小白",19);
insert into t_user values(4, "張三",24);
insert into t_user values(5, "李四",25);
insert into t_user values(6, "王五",26);

模擬長事務的場景

事務 1

SET autocommit = 0;
begin;
UPDATE t_user SET age=12  WHERE id=1;
select SLEEP(12000);
commit;

事務 2

SET autocommit = 0;
begin;
UPDATE t_user SET age=13  WHERE id=1;
commit;

兩個事務,第一個事務更新語句對 id=1 這一行加了行鎖,同時這個事務 sleep 了 120 秒。事務2同樣更新 id=1 這一行數(shù)據(jù),也會加一把行鎖,因為事務 1 的 sleep,導致事務 1 的行鎖沒有釋放,事務 2 就處于阻塞中了。

下面來看下如何排查

1、使用 show processlist 查詢正在運行的進程

show processlist 就是查看當前 mysql正 在執(zhí)行的進程,主要有兩個作用:

1、查看慢查詢的sql是哪個;

2、查看出現(xiàn)鎖的sql是哪個。

show processlist 顯示的信息都是來自 MySQL 系統(tǒng)庫 information_schema 中的 processlist 表。也可以直接查詢這個。

Select * from information_schema.processlist;   
$ show processlist;
+----+------+------------------+--------------------+---------+------+------------+--------------------------------------+
| Id | User | Host             | db                 | Command | Time | State      | Info                                 |
+----+------+------------------+--------------------+---------+------+------------+--------------------------------------+
|  7 | root | 172.21.0.1:56974 | test               | Query   |    3 | updating   | UPDATE t_user SET age=13  WHERE id=1 |
|  8 | root | 172.21.0.1:56976 | information_schema | Query   |    0 | starting   | show processlist                     |
|  9 | root | 172.21.0.1:56978 | test               | Query   | 2120 | User sleep | select SLEEP(12000)                  |
+----+------+------------------+--------------------+---------+------+------------+--------------------------------------+

來看下 show processlist 中幾個參數(shù)的含義:

  • Id:線程的標識,如果該線程幼有問題,可以直接通過 kill <Id>,殺死該線程;
  • User:啟動這個線程的用戶;
  • Host: 客戶端 IP 和端口號。結合 ss -n | grep :<port> 命令,可以定位到是哪個進程發(fā)送的請求;
  • db:當前執(zhí)行的命令是在哪個數(shù)據(jù)庫;
  • Command:顯示正在執(zhí)行的命令,常見的有休眠(sleep),查詢(query),連接(connect)等,更多的可參見官方文檔Thread Command Values;
  • Time:表示這個狀態(tài)持續(xù)的時間,單位是秒;
  • State:表示當前執(zhí)行 sql 語句的狀態(tài),例如 executing 表示開始執(zhí)行語句,Rolling back 表示線程正在回滾事務。更多的可參見官方文檔 General Thread States;
  • Info:顯示的是正在執(zhí)行的 sql 語句,不過這個只能顯示前100個字符,要看全部的執(zhí)行 sql,可使用 show full processlist 。

下面列舉幾個常用的查詢分析栗子

按客戶端 IP 分組,看哪個客戶端的鏈接數(shù)最多

select
  client_ip, count(client_ip) as client_num
from
	(select 
	substring_index(host, ':', 1) as client_ip
  from 
	information_schema.processlist) as connect_info
group by client_ip order by client_num desc;
+------------+------------+
| client_ip  | client_num |
+------------+------------+
| 172.21.0.1 |          1 |
+------------+------------+

查詢正在執(zhí)行的 sql,根據(jù)時間倒敘查詢,查詢執(zhí)行時間較長的 sql

select
   * 
from 
   information_schema.processlist 
where 
   Command != 'Sleep' 
	 order by Time desc;

2、使用 INNODB_TRX 查詢當前運行的事務

INNODB_TRX 表提供了當前在 InnoDB 內部執(zhí)行的所有事務信息,包含事務是否在等待鎖,事務何時開始以及事務正在執(zhí)行的 SQL 語句(如果有的話,sql語句阻塞就可以顯示)。

select * from information_schema.innodb_trx where trx_state="LOCK WAIT"\G;
*************************** 1. row ***************************
                    trx_id: 5800
                 trx_state: LOCK WAIT
               trx_started: 2023-07-14 01:34:06
     trx_requested_lock_id: 5800:630:3:8
          trx_wait_started: 2023-07-14 01:34:06
                trx_weight: 2
       trx_mysql_thread_id: 16
                 trx_query: UPDATE t_user SET age=13  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

看幾個主要的參數(shù),更詳細的信息可參見The INFORMATION_SCHEMA INNODB_TRX Table

  • trx_id:InnoDB 內部的唯一事務 ID,不會為只讀且非鎖定事務創(chuàng)建 ID;
  • trx_state:事務的執(zhí)行狀態(tài)。值為 RUNNING(運行), LOCK WAIT(等待鎖), ROLLING BACK(正在回滾), 和 COMMITTING(正在提交);
  • trx_query:事務正在執(zhí)行的 sql;
  • trx_isolation_level:事務的隔離級別;
  • trx_autocommit_non_locking:無鎖自動提交標識。值1表示該事務是一個 SELECT 語句,不使用 FOR UPDATE 或 LOCK IN SHARED MODE 子句,并且在啟用自動提交的情況下執(zhí)行,因此該事務只包含這一條語句。當這一列和 TRX_IS_READ_ONLY 都為 1 時,InnoDB會優(yōu)化事務,以減少與更改表數(shù)據(jù)的事務相關的開銷。

3、使用 INNODB_LOCKS 來查詢當前出現(xiàn)的鎖

SELECT * FROM information_schema.INNODB_LOCKS; 
+--------------+-------------+-----------+-----------+-----------------+------------+------------+-----------+----------+-----------+
| lock_id      | lock_trx_id | lock_mode | lock_type | lock_table      | lock_index | lock_space | lock_page | lock_rec | lock_data |
+--------------+-------------+-----------+-----------+-----------------+------------+------------+-----------+----------+-----------+
| 5812:630:3:8 | 5812        | X         | RECORD    | `test`.`t_user` | PRIMARY    |        630 |         3 |        8 | 1         |
| 5811:630:3:8 | 5811        | X         | RECORD    | `test`.`t_user` | PRIMARY    |        630 |         3 |        8 | 1         |
+--------------+-------------+-----------+-----------+-----------------+------------+------------+-----------+----------+-----------+

來看下每個字段的含義,更詳細的可參加The data_locks Table

  • lock_id:鎖 id;
  • lock_trx_id:擁有鎖的事務id, 可以和 INNODB_TRX 表 JOIN 得到事務的詳細信息;
  • lock_mode:鎖的模式,如下鎖的類型,行級鎖包括:S、X、IS、IX,分別代表:共享鎖、排它鎖、意向共享鎖、意向排它鎖。表級鎖包括:S_GAP、X_GAP、IS_GAP、IX_GAP 和 AUTO_INC,分別代表共享間隙鎖、排它間隙鎖、意向共享間隙鎖、意向排它間隙鎖和自動遞增鎖;
  • lock_type:鎖的類型,RECORD 代表行級鎖,TABLE 代表表級鎖;
  • lock_table:被鎖定的或者包含鎖記錄的表名稱;
  • lock_index:當 LOCK_TYPE=’RECORD’ 時,表示索引的名稱;否則為 NULL;
  • lock_space:當 LOCK_TYPE=’RECORD’ 時,表示鎖定行的表空間 ID;否則為 NULL。
  • lock_page:當 LOCK_TYPE=’RECORD’ 時,表示鎖定行的頁號;否則為 NULL。
  • lock_rec:當 LOCK_TYPE=’RECORD’ 時,表示一堆頁面中鎖定行的數(shù)量,亦即被鎖定的記錄號;否則為 NULL。
  • lock_data:當 LOCK_TYPE=’RECORD’ 時,表示鎖定行的主鍵;否則為NULL。

4、使用 INNODB_LOCK_WAITS 來查詢當前鎖等待的關系

SELECT * FROM information_schema.INNODB_LOCK_WAITS;
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 5812              | 5812:630:3:8      | 5811            | 5811:630:3:8     |
+-------------------+-------------------+-----------------+------------------+

來看下每個字段的含義,跟詳細的參數(shù)可參見The data_lock_waits Table

  • requesting_trx_id:請求事務的 ID ;
  • requested_lock_id:事務所等待的鎖定的 ID??梢院?INNODB_LOCKS 表 JOIN;
  • blocking_trx_id:阻塞事務的 ID;
  • blocking_lock_id:某一事務的鎖的 ID,該事務阻塞了另一事務的運行??梢院?INNODB_LOCKS 表 JOIN。

總結

如果發(fā)現(xiàn)數(shù)據(jù)庫響應變慢,排查阻塞語句,通過 show processlist 命令或者 performance_schema 表來查看當前正在執(zhí)行的 SQL 語句,就能簡單的分析出執(zhí)行較長的 sql 語句,以及正在等待的鎖和事務信息,找到阻塞的原因;

不過需要看更加詳細的信息,就需要借助于下面的信息來分析定位。

1、使用 INNODB_TRX 查詢當前運行的事務;

2、使用 INNODB_LOCKS 來查詢當前出現(xiàn)的鎖;

3、使用 INNODB_LOCK_WAITS 來查詢當前鎖等待的關系;

如果某個事務已經(jīng)卡住了,可以使用 MySQL的 kill 命令來強制結束該事務,以釋放資源。

當前要徹底結局問題還是要分析原因,優(yōu)化查詢語句或者業(yè)務中對 sql 的使用。

到此這篇關于詳解MySQL中如何定位阻塞語句的文章就介紹到這了,更多相關MySQL定位阻塞語句內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論