MySQL 8 複製效能的增強

abce發表於2024-11-15

新的複製時間戳

MySQL主從複製環境,最常見的任務是確保複製確實在進行,而且主從之間沒有發生錯誤。常用的命令是 show slave status,該命令提供了從庫執行緒的狀態資訊。因此,通常需要每個從庫上執行 show slave status並檢查輸出結果。

輸出內容中,有個引數指標 "Seconds_Behind_Master"。雖然該指標完全適用於簡單的主從設定,但對於更復雜的複製場景來說,該指標是不夠的。Seconds_Behind_Master 指標主要有四個缺點:

1.它只報告從庫與最上層主庫之間的延遲

例如,在鏈式複製設定中,Seconds_Behind_Master 報告的是相對於原始主庫的延遲,而不提供任何有關從庫與其最近(即直接)主庫之間延遲的資訊。

2.它是相對於最上層主庫的時區而言的

因此,伺服器跨時區複製會導致測得的延遲被兩臺伺服器之間的時區差抵消。

3.延遲是根據語句的執行開始時間按事件測量的

更具洞察力的測量方法是以每筆事務為單位,從事務在主庫上實際提交的時間算起。

4.用於測量複製延遲的時間戳只能精確到秒

MySQL 8引入了兩個新的時間戳,它們是對 “Seconds_Behind_Master ”的補充,可以避免上述問題。這些時間戳與寫入二進位制日誌的每個事務(而不是每個事件)的全域性事務識別符號(GTID)相關聯。GTID 是一個唯一識別符號,與在主庫上提交的每個事務相關聯。由於與事務相關聯,所有事務和所有 GTID 之間都有 1 對 1 的對映關係。

兩個新的時間戳是:

· original commit timestamp (OCT):即原始提交時間戳 (OCT),當事務被寫入原始主庫(original master)的二進位制日誌時,自紀元(即 POSIX 時間/UNIX 時間/1970 年 1 月 1 日/1970-01-01T00:00:00Z)起的微秒數

· immediate commit timestamp (ICT):即時提交時間戳 (ICT),事務寫入直接主庫(immediate master)的二進位制日誌時,自紀元起的微秒數。

mysqlbinlog 的輸出以兩種格式顯示新的時間戳:

1.微秒

2.以使用者時區顯示的 TIMESTAMP 格式(更易讀)

# at 708
#241113 19:24:24 server id 30  end_log_pos 787 CRC32 0x0950fa02         GTID    last_committed=2        sequence_number=3 rbr_only=yes    original_committed_timestamp=1731497064388667   immediate_commit_timestamp=1731497064388667       transaction_length=326
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
# original_commit_timestamp=1731497064388667 (2024-11-13 19:24:24.388667 CST)
# immediate_commit_timestamp=1731497064388667 (2024-11-13 19:24:24.388667 CST)
/*!80001 SET @@session.original_commit_timestamp=1731497064388667*//*!*/;
/*!80014 SET @@session.original_server_version=80036*//*!*/;
/*!80014 SET @@session.immediate_server_version=80036*//*!*/;
SET @@SESSION.GTID_NEXT= 'd59173d4-a168-11ef-bb5c-005056b04cdd:7'/*!*/;
# at 787
#241113 19:24:24 server id 30  end_log_pos 861 CRC32 0x2ce7b347         Query   thread_id=23    exec_time=0     error_code=0
SET TIMESTAMP=1731497064/*!*/;
BEGIN
/*!*/;
# at 861
#241113 19:24:24 server id 30  end_log_pos 912 CRC32 0xc13bf03f         Rows_query
# insert into a values(4),(3)
# at 912
#241113 19:24:24 server id 30  end_log_pos 958 CRC32 0xdf0e13db         Table_map: `abc`.`a` mapped to number 116
# has_generated_invisible_primary_key=0
# at 958
#241113 19:24:24 server id 30  end_log_pos 1003 CRC32 0x8e24a4c5        Write_rows: table id 116 flags: STMT_END_F

BINLOG '
aIw0Zx0eAAAAMwAAAJADAACAABtpbnNlcnQgaW50byBhIHZhbHVlcyg0KSwoMyk/8DvB
aIw0ZxMeAAAALgAAAL4DAAAAAHQAAAAAAAEAA2FiYwABYQABAwABAQEA2xMO3w==
aIw0Zx4eAAAALQAAAOsDAAAAAHQAAAAAAAEAAgAB/wAEAAAAAAMAAADFpCSO
'/*!*/;
### INSERT INTO `abc`.`a`
### SET
###   @1=4 /* INT meta=0 nullable=1 is_null=0 */
### INSERT INTO `abc`.`a`
### SET
###   @1=3 /* INT meta=0 nullable=1 is_null=0 */
# at 1003
#241113 19:24:24 server id 30  end_log_pos 1034 CRC32 0x09af8ed0        Xid = 37
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

Performance Schema 新增的表

MySQL 8.0 對Performance Schema新增了一些更改,從而提高了效能並增加了更多指標:

1.可以檢測 server 錯誤

2.現在支援索引

3.為現有的Performance Schema複製狀態表新增了新欄位

檢測 server 錯誤

MySQL 8 引入了五個新的彙總表,以幫助檢測伺服器錯誤。它們包括

1.events_errors_summary_by_account_by_error

2.events_errors_summary_by_host_by_error

3.events_errors_summary_by_thread_by_error

4.events_errors_summary_by_user_by_error

5.events_errors_summary_global_by_error

在上述所有表中,錯誤統計資料都是按錯誤彙總的。此外,除 events_errors_summary_global_by_error 外,每個表都儲存與特定使用者、主機、賬戶或執行緒有關的錯誤;events_errors_summary_global_by_error 包含整個伺服器的錯誤。

表結構

每個表都包含以下欄位:

+-------------------+---------------------+------+-----+---------------------+
| Field             | Type                | Null | Key | Default             |
+-------------------+---------------------+------+-----+---------------------+
| error_number      | int(11)             | yes  |     | null                |
| error_name        | varchar(64)         | yes  |     | null                |
| sql_state         | varchar(5)          | yes  |     | null                |
| sum_error_raised  | bigint(20) unsigned | no   |     | null                |
| sum_error_handled | bigint(20) unsigned | no   |     | null                |
| first_seen        | timestamp           | yes  |     | 0000-00-00 00:00:00 |
| last_seen         | timestamp           | yes  |     | 0000-00-00 00:00:00 |
+-------------------+---------------------+------+-----+---------------------+

其中:

· first_seen/last_seen 列:表示出現特定錯誤的第一次和最後一次。

· sum_error_raised 列:丟擲特定錯誤的發生次數。

· sum_error_handled 列:列出特定錯誤被處理的次數。

在 sum_error_handled 下統計/彙總了所有在儲存程式中處理過的錯誤。同時,sum_error_raised 是所有其他已丟擲但未處理的錯誤的次數。因此,要檢視伺服器上遇到特定錯誤的次數,我們可以執行以下操作:

檢視不存在的表:
>select * from abc.abce;
ERROR 1146 (42S02): Table 'abc.abce' doesn't exist

檢視錯誤表中資訊:
>select * from performance_schema.events_errors_summary_global_by_error where error_name = 'er_no_such_table';
+--------------+------------------+-----------+------------------+-------------------+---------------------+---------------------+
| ERROR_NUMBER | ERROR_NAME       | SQL_STATE | SUM_ERROR_RAISED | SUM_ERROR_HANDLED | FIRST_SEEN          | LAST_SEEN           |
+--------------+------------------+-----------+------------------+-------------------+---------------------+---------------------+
|         1146 | ER_NO_SUCH_TABLE | 42S02     |                1 |                 0 | 2024-11-13 19:44:06 | 2024-11-13 19:44:06 |
+--------------+------------------+-----------+------------------+-------------------+---------------------+---------------------+
1 row in set (0.01 sec)

本示例查詢的是全域性表,但也可以從使用者/主機/賬戶/執行緒各自的表中按使用者/主機/賬戶/執行緒彙總檢索這些錯誤的統計資料,以獲得更精細的統計資料。

索引支援

自從在 MySQL 5.5 中加入 Performance Schema 後,該模式已增加到 93 個表,其中一些表儲存了大量資料。新增的索引支援功能大大提高了 Performance Schema 的效率,從而顯著提升了許多監控查詢的速度。

在許多 sys Schema 查詢中,都能很容易地看到索引帶來的效能提升。例如,在有 1000 個空閒執行緒的情況下,查詢 "SELECT * FROM sys.session" 從 34.70 秒下降到 1.01 秒,提高了 30 倍!

Performance Schema 中總共新增了 115 個索引。與 Information Schema 不同,Performance Schema 將資料作為儲存引擎而不是臨時表公開。

臨時表無法公開最佳化器可能會使用的索引,而儲存引擎卻可以。對 Performance Schema 的資料訪問也使用與常規表相同的(SQL)介面,因此它能受益於未來對查詢最佳化器的改進。

現有 Performance Schema 複製狀態表新增的欄位

除了新的錯誤表,現有的 Performance Schema 表也增加了一些欄位,以幫助檢測和診斷多個點的延遲情況。複製流中的每個潛在延遲點都對映到自己的表中:

延遲點

Performance Schema 複製狀態表

連線執行緒檢索主庫來的事務,並以丟列的方式將其加入relay log

replication_connection_status:與主庫連線的當前狀態

協調執行緒讀取來自relay log的事務,並排程到worker執行緒(如果開啟了多執行緒複製)

replication_applier_status_by_coordinator:協調器執行緒的當前狀態,僅在啟用 MTS 時顯示資訊

worker執行緒應用日誌

replication_applier_status_by_worker: 應用從主伺服器接收的事務的執行緒的當前狀態

檢視示例:

root@localhost (none)>select * from performance_schema.replication_connection_status\g
*************************** 1. row ***************************
                                      channel_name: 
                                        group_name: 
                                       source_uuid: 3dc957a8-4b53-13ee-81be-055056a0cda9
                                         thread_id: 290
                                     service_state: on
                         count_received_heartbeats: 12104
                          last_heartbeat_timestamp: 2024-11-13 20:03:49.797661
                          received_transaction_set: 3dc957a8-4b53-13ee-81be-055056a0cda9:90536365-92544861
                                 last_error_number: 0
                                last_error_message: 
                              last_error_timestamp: 0000-00-00 00:00:00.000000
                           last_queued_transaction: 3dc957a8-4b53-13ee-81be-055056a0cda9:92544861
 last_queued_transaction_original_commit_timestamp: 2024-11-13 20:00:49.794755
last_queued_transaction_immediate_commit_timestamp: 2024-11-13 20:00:49.794755
     last_queued_transaction_start_queue_timestamp: 2024-11-13 20:00:49.795718
       last_queued_transaction_end_queue_timestamp: 2024-11-13 20:00:49.804412
                              queueing_transaction: 
    queueing_transaction_original_commit_timestamp: 0000-00-00 00:00:00.000000
   queueing_transaction_immediate_commit_timestamp: 0000-00-00 00:00:00.000000
        queueing_transaction_start_queue_timestamp: 0000-00-00 00:00:00.000000
1 row in set (0.00 sec)

root@localhost (none)>select * from performance_schema.replication_applier_status_by_coordinator\g
*************************** 1. row ***************************
                                         channel_name: 
                                            thread_id: 291
                                        service_state: on
                                    last_error_number: 0
                                   last_error_message: 
                                 last_error_timestamp: 0000-00-00 00:00:00.000000
                           last_processed_transaction: 3dc957a8-4b53-13ee-81be-055056a0cda9:92544861
 last_processed_transaction_original_commit_timestamp: 2024-11-13 20:00:49.794755
last_processed_transaction_immediate_commit_timestamp: 2024-11-13 20:00:49.794755
    last_processed_transaction_start_buffer_timestamp: 2024-11-13 20:00:49.795788
      last_processed_transaction_end_buffer_timestamp: 2024-11-13 20:00:49.830551
                               processing_transaction: 
     processing_transaction_original_commit_timestamp: 0000-00-00 00:00:00.000000
    processing_transaction_immediate_commit_timestamp: 0000-00-00 00:00:00.000000
        processing_transaction_start_buffer_timestamp: 0000-00-00 00:00:00.000000
1 row in set (0.00 sec)

root@localhost (none)>select * from performance_schema.replication_applier_status_by_worker\g
*************************** 1. row ***************************
                                           channel_name: 
                                              worker_id: 1
                                              thread_id: 292
                                          service_state: on
                                      last_error_number: 0
                                     last_error_message: 
                                   last_error_timestamp: 0000-00-00 00:00:00.000000
                               last_applied_transaction: 3dc957a8-4b53-13ee-81be-055056a0cda9:92544861
     last_applied_transaction_original_commit_timestamp: 2024-11-13 20:00:49.794755
    last_applied_transaction_immediate_commit_timestamp: 2024-11-13 20:00:49.794755
         last_applied_transaction_start_apply_timestamp: 2024-11-13 20:00:49.796949
           last_applied_transaction_end_apply_timestamp: 2024-11-13 20:00:49.852644
                                   applying_transaction: 
         applying_transaction_original_commit_timestamp: 0000-00-00 00:00:00.000000
        applying_transaction_immediate_commit_timestamp: 0000-00-00 00:00:00.000000
             applying_transaction_start_apply_timestamp: 0000-00-00 00:00:00.000000
                 last_applied_transaction_retries_count: 0
   last_applied_transaction_last_transient_error_number: 0
  last_applied_transaction_last_transient_error_message: 
last_applied_transaction_last_transient_error_timestamp: 0000-00-00 00:00:00.000000
                     applying_transaction_retries_count: 0
       applying_transaction_last_transient_error_number: 0
      applying_transaction_last_transient_error_message: 
    applying_transaction_last_transient_error_timestamp: 0000-00-00 00:00:00.000000
*************************** 2. row ***************************
                                           channel_name: 
                                              worker_id: 2
                                              thread_id: 295
                                          service_state: on
                                      last_error_number: 0
                                     last_error_message: 
                                   last_error_timestamp: 0000-00-00 00:00:00.000000
                               last_applied_transaction: 3dc957a8-4b53-13ee-81be-055056a0cda9:92543553
     last_applied_transaction_original_commit_timestamp: 2024-11-13 19:55:11.074457
    last_applied_transaction_immediate_commit_timestamp: 2024-11-13 19:55:11.074457
         last_applied_transaction_start_apply_timestamp: 2024-11-13 19:55:12.013437
           last_applied_transaction_end_apply_timestamp: 2024-11-13 19:55:12.015771
                                   applying_transaction: 
         applying_transaction_original_commit_timestamp: 0000-00-00 00:00:00.000000
        applying_transaction_immediate_commit_timestamp: 0000-00-00 00:00:00.000000
             applying_transaction_start_apply_timestamp: 0000-00-00 00:00:00.000000
                 last_applied_transaction_retries_count: 0
   last_applied_transaction_last_transient_error_number: 0
  last_applied_transaction_last_transient_error_message: 
last_applied_transaction_last_transient_error_timestamp: 0000-00-00 00:00:00.000000
                     applying_transaction_retries_count: 0
       applying_transaction_last_transient_error_number: 0
      applying_transaction_last_transient_error_message: 
    applying_transaction_last_transient_error_timestamp: 0000-00-00 00:00:00.000000
*************************** 3. row ***************************
                                           channel_name: 
                                              worker_id: 3
                                              thread_id: 296
                                          service_state: on
                                      last_error_number: 0
                                     last_error_message: 
                                   last_error_timestamp: 0000-00-00 00:00:00.000000
                               last_applied_transaction: 3dc957a8-4b53-13ee-81be-055056a0cda9:92543080
     last_applied_transaction_original_commit_timestamp: 2024-11-13 19:54:48.822867
    last_applied_transaction_immediate_commit_timestamp: 2024-11-13 19:54:48.822867
         last_applied_transaction_start_apply_timestamp: 2024-11-13 19:54:51.491876
           last_applied_transaction_end_apply_timestamp: 2024-11-13 19:54:54.896176
                                   applying_transaction: 
         applying_transaction_original_commit_timestamp: 0000-00-00 00:00:00.000000
        applying_transaction_immediate_commit_timestamp: 0000-00-00 00:00:00.000000
             applying_transaction_start_apply_timestamp: 0000-00-00 00:00:00.000000
                 last_applied_transaction_retries_count: 0
   last_applied_transaction_last_transient_error_number: 0
  last_applied_transaction_last_transient_error_message: 
last_applied_transaction_last_transient_error_timestamp: 0000-00-00 00:00:00.000000
                     applying_transaction_retries_count: 0
       applying_transaction_last_transient_error_number: 0
      applying_transaction_last_transient_error_message: 
    applying_transaction_last_transient_error_timestamp: 0000-00-00 00:00:00.000000
*************************** 4. row ***************************
                                           channel_name: 
                                              worker_id: 4
                                              thread_id: 297
                                          service_state: on
                                      last_error_number: 0
                                     last_error_message: 
                                   last_error_timestamp: 0000-00-00 00:00:00.000000
                               last_applied_transaction: 3dc957a8-4b53-13ee-81be-055056a0cda9:92540369
     last_applied_transaction_original_commit_timestamp: 2024-11-13 19:43:11.017099
    last_applied_transaction_immediate_commit_timestamp: 2024-11-13 19:43:11.017099
         last_applied_transaction_start_apply_timestamp: 2024-11-13 19:43:11.088638
           last_applied_transaction_end_apply_timestamp: 2024-11-13 19:43:11.091951
                                   applying_transaction: 
         applying_transaction_original_commit_timestamp: 0000-00-00 00:00:00.000000
        applying_transaction_immediate_commit_timestamp: 0000-00-00 00:00:00.000000
             applying_transaction_start_apply_timestamp: 0000-00-00 00:00:00.000000
                 last_applied_transaction_retries_count: 0
   last_applied_transaction_last_transient_error_number: 0
  last_applied_transaction_last_transient_error_message: 
last_applied_transaction_last_transient_error_timestamp: 0000-00-00 00:00:00.000000
                     applying_transaction_retries_count: 0
       applying_transaction_last_transient_error_number: 0
      applying_transaction_last_transient_error_message: 
    applying_transaction_last_transient_error_timestamp: 0000-00-00 00:00:00.000000
4 rows in set (0.00 sec)

root@localhost (none)>

每個表中增加了九個欄位,用於儲存上一個事務、相應處理的執行緒以及該執行緒當前正在處理的事務的資訊。這些資訊包括:

· 事務的 GTID

· OCT 和 ICT(從庫的中繼日誌中獲取)

· 執行緒開始處理的時間

· 如果是最後處理的事務,執行緒完成處理的時間

複製執行緒之間的關係更高效

從 MySQL 8.0.1 開始,由於複製執行緒之間關係的改進,從庫的改進將使其比以前的 MySQL 版本更高效。

MySQL 從庫側的複製核心由兩個執行緒(有時更多)組成:

  1. connection :處理與主庫的連線,檢索事件並按佇列寫入 relay log。
  2. applier:從 relay log 中讀取排隊的事件,並將其應用到副本中。

舊的仲裁執行緒模型

由於"仲裁"的原因,當 connection 和 applier 處理同一個 relay log 時,connection 和 applier 之間的關係就會出現問題。relay log 一次只能由一個執行緒訪問,導致複製執行緒相互排斥。因此,當 connection 寫入 relay log 時,applier 無法讀取要應用的內容,只能等待。同樣,當 applier 從 relay log 中讀取內容時,connection 也無法向其中寫入新內容,從而進入空閒狀態。

仲裁是為了防止 applier 程式將只部分寫入 relay log 的事件傳送給 worker 執行緒。雖然這種仲裁有時對資源有限的從庫有益,但也限制了多執行緒 (MTS)複製的可擴充套件性。

新執行緒模型

從 MySQL 8.0.1 開始,applier 幾乎不再阻塞 connection ,但中繼日誌超過其大小限制時例外。

同樣,對於已經完全寫入佇列的事務,connection 也不會阻塞 applier。

為使這一解決方案奏效,connection 執行緒會不斷更新上次完全假如佇列的事件在 relay log 中的位置資訊。applier 現在從日誌中讀取直到該位置,並等待 connection 執行緒的通知。

相關文章