GreatSQL 的刷新鎖

来源:https://www.cnblogs.com/greatsql/p/18329441
-Advertisement-
Play Games

GreatSQL 的刷新鎖 前言 因為運維小伙伴執行dump備份命令,導致資料庫卡住,很多會話都在waiting for table flush,基於這一故障,我對GreatSQL的刷新鎖進行了研究。感興趣的小伙伴請隨我一探究竟吧。 刷新鎖的癥狀 刷新鎖問題的主要癥狀是資料庫會進入嘎然而止的狀態,所 ...


GreatSQL 的刷新鎖

file

前言

因為運維小伙伴執行dump備份命令,導致資料庫卡住,很多會話都在waiting for table flush,基於這一故障,我對GreatSQL的刷新鎖進行了研究。感興趣的小伙伴請隨我一探究竟吧。

刷新鎖的癥狀

刷新鎖問題的主要癥狀是資料庫會進入嘎然而止的狀態,所有需要使用部分或全部表的新查詢都停下來等待刷新鎖。要尋找的信號如下:

1.新查詢的查詢狀態為Waiting for table flush。這可能出現在所有新查詢中,也可能只出現在訪問特定表的新查詢中。

2.資料庫連接數增多,最終可能由於連接數用盡,新連接失敗。

3.至少有一個查詢的運行時間晚於最早的刷新鎖請求。

4.進程列表中可能有flush table語句,也可能flush table語句已經超時(超過lock_wait_timeout設置)或被取消(會話被Ctr +C 終止或被kill)。

刷新鎖構建

本實驗使用的GreatSQL版本: 8.0.32-25 GreatSQL (GPL)。

創建四個連接,第一個連接執行一個慢查詢,第二個連接用於執行flush tables語句,第三個連接執行第一個連接中慢查詢語句相關表的快速查詢。第四個連接執行其他表的查詢和插入:

Connection 1> select count(*) ,sleep(100) from t1;
Connection 2> flush tables;   (flush tables with read lock;)
Connection 3> select count(*) from t1;
Connection 4> select count(*) from t2;
​             insert into t2 values(5,'a');

刷新鎖爭用問題診斷及解決

1.flush tables 實驗

Connection 2 執行flush tables 時 ,Connection 3 受阻塞,Connection 4成功執行。

使用sys.session視圖來輸出各會話運行情況,也可以使用show processlist 來展示。預設輸出是按執行時間降序排列,這讓 查詢刷新鎖爭用之類的問題變得容易。

[root@GreatSQL][test]>select thd_id,conn_id,state,current_statement,statement_latency from sys.session where command='Query';
+--------+---------+-------------------------+-------------------------------------------------------------------+-------------------+
| thd_id | conn_id | state                   | current_statement                                                 | statement_latency |
+--------+---------+-------------------------+-------------------------------------------------------------------+-------------------+
|    116 |      61 | User sleep              | select count(*),sleep(100) from t1                                | 10.81 s           |
|    117 |      62 | Waiting for table flush | flush tables                                                      | 8.15 s            |
|    109 |      57 | Waiting for table flush | select count(*) from t1                                           | 3.91 s            |
|    118 |      63 | NULL                    | select thd_id,conn_id,state,cu ... .session where command='Query' | 71.49 ms          |
+--------+---------+-------------------------+-------------------------------------------------------------------+-------------------+
4 rows in set (0.07 sec)

從上面會話的查詢結果可以看出,flush tables會話的狀態是Waiting for table flush,在它之前有一個運行時間較長的查詢,這是阻塞flush tables完成的查詢。第三個查詢的狀態也是Waiting for table flush,說明flush tables語句又阻塞了其他查詢。

而Connection4 未受影響,說明flush tables不影響其他表的讀寫操作。

當等待刷新鎖成為問題時,這意味著有一條或多條查詢阻塞了flush tables 語句獲得刷新鎖。由於flush tables語句需要一個排他鎖,因此又會阻塞後續會話對相關表的共用鎖或排他鎖。

手動Ctr+C中斷flush tables 會話後,再次查詢各會話的運行情況。

[root@GreatSQL][test]>select thd_id,conn_id,state,current_statement,statement_latency from sys.session where command='Query';
+--------+---------+-------------------------+-------------------------------------------------------------------+-------------------+
| thd_id | conn_id | state                   | current_statement                                                 | statement_latency |
+--------+---------+-------------------------+-------------------------------------------------------------------+-------------------+
|    116 |      61 | User sleep              | select count(*),sleep(100) from t1                                | 20.10 s           |
|    109 |      57 | Waiting for table flush | select count(*) from t1                                           | 13.19 s           |
|    118 |      63 | NULL                    | select thd_id,conn_id,state,cu ... .session where command='Query' | 68.14 ms          |
+--------+---------+-------------------------+-------------------------------------------------------------------+-------------------+
3 rows in set (0.07 sec)

從查詢結果可以看出,被flush table阻塞的查詢依然還被阻塞著,這時候解決問題的辦法就是結束第一個阻塞flush tables會話的慢查詢。

2.flush table with read lock實驗

Connection2 執行flush table with read lock 時,Connection 3 受阻塞,Connect 4的select成功,insert 被阻塞。

使用sys.session視圖來輸出各會話運行情況

[root@GreatSQL][test]>select thd_id,conn_id,state,current_statement,statement_latency from sys.session where command='Query';
+--------+---------+------------------------------+-------------------------------------------------------------------+-------------------+
| thd_id | conn_id | state                        | current_statement                                                 | statement_latency |
+--------+---------+------------------------------+-------------------------------------------------------------------+-------------------+
|    116 |      61 | User sleep                   | select count(*),sleep(100) from t1                                | 52.74 s           |
|    117 |      62 | Waiting for table flush      | flush table with read lock                                        | 26.36 s           |
|    109 |      57 | Waiting for table flush      | select count(*) from t1                                           | 22.00 s           |
|    124 |      69 | Waiting for global read lock | insert into t2 values(8,'b')                                      | 6.01 s            |
|    118 |      63 | NULL                         | select thd_id,conn_id,state,cu ... .session where command='Query' | 82.90 ms          |
+--------+---------+------------------------------+-------------------------------------------------------------------+-------------------+
5 rows in set (0.09 sec)

從上面結果看出, flush table with read lock 的會話狀態為Waiting for table flush,Connection3 狀態同樣為Waiting for table flush,而Connect4的狀態為Waiting for global read lock。

手動Ctr+C中斷flush tables 會話後,再次查詢各會話的運行情況。

[root@GreatSQL][test]>select thd_id,conn_id,state,current_statement,statement_latency from sys.session where command='Query';
+--------+---------+------------------------------+-------------------------------------------------------------------+-------------------+
| thd_id | conn_id | state                        | current_statement                                                 | statement_latency |
+--------+---------+------------------------------+-------------------------------------------------------------------+-------------------+
|    116 |      61 | User sleep                   | select count(*),sleep(100) from t1                                | 1.37 min          |
|    109 |      57 | Waiting for table flush      | select count(*) from t1                                           | 51.58 s           |
|    124 |      69 | Waiting for global read lock | insert into t2 values(8,'b')                                      | 35.57 s           |
|    118 |      63 | NULL                         | select thd_id,conn_id,state,cu ... .session where command='Query' | 65.26 ms          |
+--------+---------+------------------------------+-------------------------------------------------------------------+-------------------+
4 rows in set (0.06 sec)

發現Connection 3,Connection4 仍然受到阻塞。

Connection 1 查詢結束後查詢各會話運行情況

[root@GreatSQL][test]>select thd_id,conn_id,state,current_statement,statement_latency from sys.session where command='Query';
+--------+---------+------------------------------+-------------------------------------------------------------------+-------------------+
| thd_id | conn_id | state                        | current_statement                                                 | statement_latency |
+--------+---------+------------------------------+-------------------------------------------------------------------+-------------------+
|    124 |      69 | Waiting for global read lock | insert into t2 values(8,'b')                                      | 57.44 s           |
|    118 |      63 | executing                    | select thd_id,conn_id,state,cu ... .session where command='Query' | 2.06 ms           |
+--------+---------+------------------------------+-------------------------------------------------------------------+-------------------+
2 rows in set (0.06 sec)

Connection 3 成功執行,Connection 4的insert 仍然受到阻塞。

顯示執行unlock tables 命令後,Connection4的insert才執行完成。

實驗結論:

由上面兩個實驗得出,診斷刷新鎖爭用的問題時,只要有會話處於 Waiting for table flush狀態,說明曾發生過刷新表的操作,無論當前能否看到flush tables的相關會話,而通常處於Waiting for table flush狀態的會話之前發生的慢查詢都有可能是造成 後續阻塞的原因。

flush tables with read lock語句要獲取的全局讀鎖,在等待獲取鎖時,癥狀與flush tables語句差不多,不同的是:

1.flush tables with read lock等待獲取鎖及得到鎖之後,都會阻止所有表的寫入,而flush tables只是在執行過程中持有鎖,它不會阻止長查詢之外的其他表寫操作

2.flush tables with read lock需要通過unlock tables 顯示釋放鎖,而flush tables不需要。

為什麼flush table或者flush tables with read lock 會話都結束了,後續的查詢還是會被阻塞呢?

這是低版本表定義緩存(TDC)的原因,這兩條命令都會close all open tables,將表版本推高(refresh_version +1), 但因為長查詢線程的存在,導致舊表無法被close,在訪問舊表時都會認為是舊版本,等待 TABLE cache flush,而refresh_version 的推高是不可逆的結果,也就是說即使發出flush table或flush tables with read lock 的會話中斷了 ,但是實際產生的 TABLE flush 的效果還是存在的。

另外這個癥狀與隔離級別關係不大,筆者測試了READ COMMITTED, REPEATABLE READ兩種隔離級別,癥狀都相同。

通常除了手動發出這兩個命令,使用mysqldump工具進行備份時也會發出這兩個命令。

mysqldump備份加哪種選項會觸發命令flush tables

打開general log, 進行多次dump測試實驗,發現有以下幾種情況會觸發flush tables命令

1.--flush-logs,--single-transaction 一起使用時,觸發flush tables,flush tables with read lock

2.--source-data 不和--single-transaction搭配使用時,觸發FLUSH /*!40101 LOCAL */ TABLES, FLUSH TABLES WITH READ LOCK

3.--flush-logs,--single-transaction,--source-data 這三個選項同時使用時,會觸發FLUSH /*!40101 LOCAL */ TABLES, FLUSH TABLES WITH READ LOCK

DBA小伙伴要熟悉備份工具各個選項或者選項組合使用時帶來效果,儘量避免在業務高峰進行備份操作。

結語

Flush table 的功能是關閉所有已經打開的表,強制關閉所有正在使用的表,然而,正在使用的表對象是不能關閉的,所以Flush Tables操作會被正在運行的SQL請求阻塞,而在Flush table 之後的SQL請求又會被Flush table會話阻塞,即使Flush table會話被取消了,這些發生在Flush table之後的SQL請求也還是會被阻塞。所以當會話出現大量waiting for table flush時,無論當前是否還存在flush table 命令,查詢耗時比這些waiting會話更久的慢查詢,將其kill掉才能解決問題。


Enjoy GreatSQL

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • SPI是嵌入式中使用比較廣泛的協議之一,本文從該協議的原理入手對其進行了詳細介紹,並結合STM32F103ZET主控晶元對其進行了說明,最後給出了兩個實例代碼demo供大家做參考。 ...
  • 本節內容 因為risc-v存在硬體特權級機制,我們又要實現一個可以使得應用程式工作在用戶級,使得操作系統工作在特權級.原因是要保證用戶態的應用程式不能隨意使用內核態的指令,要使用內核態的指令就必須通過操作系統來執行,這樣有了操作系統的控制和檢查,程式不會因為應用程式的問題導致整個操作系統都運行錯誤. ...
  • 本章將和大家分享Linux中的許可權控制。廢話不多說,下麵我們直接進入主題。 一、基礎知識 Linux作為一種多用戶的操作系統(伺服器系統),允許多個用戶同時登陸到系統上,並響應每個用戶的請求。 任何需要使用操作系統的用戶,都需要一個系統賬號,賬號分為:管理員賬號與普通用戶賬號。 在Linux中,操作 ...
  • 在現代軟體開發和部署中,Docker容器已成為一種流行的技術。然而,隨著容器的廣泛使用,數據保護和遷移也變得至關重要。本文將詳細介紹如何備份和遷移Docker容器,確保你的應用和數據在任何時候都是安全的。 一、為什麼需要備份和遷移Docker容器? 在某些情況下,你可能需要備份和遷移Docker容器 ...
  • 書接上文,在一個正常的事務複製環境中,如果發生了資料庫還原,事務複製會不會出問題,出問題之後又如何恢復,如果在不刪除訂閱發佈重建的情況下,如何在現有基礎上修複事務複製的異常,這個問題可以分為兩部分看: 1,如果publisher資料庫發生了還原操作,事務複製會出現什麼異常,該如何恢復? 2,如果是s ...
  • Vue 的 Keep-Alive 組件是用於緩存組件的高階組件,可以有效地提高應用性能。它能夠使組件在切換時仍能保留原有的狀態信息,並且有專門的生命周期方便去做額外的處理。該組件在很多場景非常有用,比如: · tabs 緩存頁面 · 分步表單 · 路由緩存 在 Vue 中,通過 KeepAlive ...
  • 上次向大家分享了論文圖譜項目Awesome-Graphs的介紹文章,這次我們就拿圖計算系統的奠基文章Pregel開篇,沿著論文圖譜的主線,對圖計算系統的論文內容進行解讀。 ...
  • 1. 事物的四大特性 事務是邏輯上的一組操作,要麼都執行,要麼都不執行 原子性(Atomicity):事務是最小的執行單位,不允許分割。事務的原子性確保動作要麼全部完成,要麼完全不起作用; 一致性(Consistency):執行事務前後,數據保持一致,例如轉賬業務中,無論事務是否成功,轉賬者和收款人 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...