作者:Arunjith Aravindan
翻譯:管長龍
本文來源:https://www.percona.com/blog/2020/10/27/using-MySQL-8-persisted-system-variables/
MySQL 8 之前,使用的動態變量不是永久性的,并且在重啟后會重置。可在運行時使用 SET 語句更改這些變量,以影響當前實例的操作,但是我們必須手動更新 my.cnf 配置文件以使其持久化。
在許多情況下,從服務端更新 my.cnf 并不是一個方便的選擇,并且使變量僅被更新才能在后續重新啟動時動態還原,而沒有任何歷史記錄。
持久化系統變量是 MySQL 8 中引入的功能之一。新功能可幫助 DBA 動態更新變量并注冊它們,而無需從服務器端訪問配置文件。
如何持久化全局系統變量?
與 SET GLOBAL 一樣,SET PERSIST 是可用于在運行時更新系統變量并使它們在重新啟動后保持不變的命令。當我們使用 PERSIST 關鍵字時,變量更改將更新到數據目錄中的 mysqld-auto.cnf 選項文件。mysqld-auto.cnf 是僅在第一次執行 PERSIST 或 PERSIST_ONLY 語句時創建的 JSON 格式文件。
讓我們以更新最大連接數為例,看看此功能的工作原理。
mysql> SET PERSIST max_connections = 1000;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@max_connectionsG
*************************** 1. row ***************************
@@max_connections: 1000
1 row in set (0.00 sec)
生成的 mysqld-auto.cnf 如下所示:
cat /var/lib/mysql/mysqld-auto.cnf
{ "Version" : 1 , "mysql_server" : {
"max_connections" : {
"Value" : "1000" , "Metadata" : {
"Timestamp" : 1602543199335909 , "User" : "root" , "Host" : "localhost" } } } }
如何保留只讀的系統變量?
當需要更改只讀變量時,我們需要使用 PERSIST_ONLY 關鍵字。該子句更新 mysqld-auto.cnf 文件中的更改,但不適用于 MySQL,在下一次 MySQL 重新啟動時繼續存在。這使得 PERSIST_ONLY 適合配置只能在服務器啟動時設置的只讀系統變量。
mysql> SET PERSIST innodb_log_file_size=50331648*2;
ERROR 1238 (HY000): Variable 'innodb_log_file_size' is a read-only variable
mysql> set persist_only innodb_log_file_size=50331648*2;
Query OK, 0 rows affected (0.01 sec)
如何清除永久系統變量設置?
我們可以使用 RESET PERSIST 命令從 mysqld-auto.cnf 中刪除持久設置。運行不帶特定變量名的命令時要小心,因為它將從配置文件中刪除所有設置。實際上,它從 mysqld-auto.cnf 中刪除了持久設置,但沒有從 MySQL中 刪除。
看幾個例子:
mysql> RESET PERSIST;
Query OK, 0 rows affected (0.00 sec)
cat /var/lib/mysql/mysqld-auto.cnf
{ "Version" : 1 , "mysql_server" : { } }
mysql> select @@max_connections;
+-------------------+
| @@max_connections |
+-------------------+
| 1000 |
+-------------------+
1 row in set (0.01 sec)
如果想清除特定變量而不是清除配置文件中的所有設置,則以下示例向我們展示了如何執行此操作。如果我們嘗試刪除 mysqld-auto.cnf 中不存在的變量,則會導致錯誤,如下所示,我們可以使用 IF EXISTS 子句來抑制該錯誤。
mysql> RESET PERSIST max_connections;
Query OK, 0 rows affected (0.00 sec)
mysql> RESET PERSIST innodb_max_dirty_pages_pct;
ERROR 3615 (HY000): Variable innodb_max_dirty_pages_pct does not exist in persisted config file
mysql>
mysql> RESET PERSIST IF EXISTS innodb_max_dirty_pages_pct;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show warnings;
| Warning | 3615 | Variable innodb_max_dirty_pages_pct does not exist in persisted config file |
有沒有辦法禁用持久性?
是的,persisted_globals_load 參數用于啟用或禁用持久化的系統變量。禁用后,服務器啟動順序將忽略 mysqld-auto.cnf 文件。手動更改為 mysqld-auto.cnf 文件可能會在服務器啟動時導致解析錯誤。在這種情況下,服務器報告錯誤并退出。如果發生此問題,則必須在禁用 persisted_globals_load 系統變量或使用以下示例中提供的 --no-defaults 選項的情況下啟動服務器。
mysql> select @@persisted_globals_load ;
+-------------------------------------+
| @@persisted_globals_load |
+-------------------------------------+
| 1 |
+-------------------------------------+
1 row in set (0.00 sec)
grep -i persisted_globals_load /etc/my.cnf
persisted_globals_load=0
mysql> restart;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@persisted_globals_load ;
+-----------------------------------+
| @@persisted_globals_load |
+-----------------------------------+
| 0 |
+----------------------------------+
1 row in set (0.00 sec)
mysql> select @@max_connections;
+-------------------+
| @@max_connections |
+-------------------+
| 500 |
+-------------------+
1 row in set (0.00 sec)
需要什么授權?
考慮到安全性,正確用戶的正確權限絕對是最佳實踐。SYSTEM_VARIABLES_ADMIN 和 PERSIST_RO_VARIABLES_ADMIN 是用戶使用 SET PERSIST_ONLY 將全局系統變量持久保存到 mysqld-auto.cnf 的必需特權。
用戶還需要具有 SHUTDOWN 特權才能使用 RESTART 命令。它提供了一種從客戶端會話重新啟動 MySQL 的方法,而無需在服務器主機上進行命令行訪問。
mysql> CREATE USER 'admin_persist'@'localhost' IDENTIFIED BY '*********';
Query OK, 0 rows affected (0.02 sec)
mysql> GRANT SYSTEM_VARIABLES_ADMIN, PERSIST_RO_VARIABLES_ADMIN, SHUTDOWN on *.* to 'admin_persist'@'localhost';
Query OK, 0 rows affected (0.03 sec)
如何監視變量?
要列出使用 PERSIST 選項更新的變量,我們可以查詢 performance_schema.persisted_variables 表以及其他幾個表,如下所示。這是一個如何從 MySQL 端監視變量的簡單示例,您可以根據需要修改查詢。
mysql> select v.VARIABLE_NAME,g.VARIABLE_VALUE current_value,p.VARIABLE_VALUE as persist_value,SET_TIME,SET_USER,VARIABLE_SOURCE,VARIABLE_PATH from performance_schema.variables_info v JOIN performance_schema.persisted_variables p USING(VARIABLE_NAME) JOIN performance_schema.global_variables g USING(VARIABLE_NAME)G
*************************** 1. row ***************************
VARIABLE_NAME: innodb_log_file_size
current_value: 50331648
persist_value: 100663296
SET_TIME: 2020-10-12 18:54:35.725177
SET_USER: arun
VARIABLE_SOURCE: COMPILED
VARIABLE_PATH:
*************************** 2. row ***************************
VARIABLE_NAME: max_connections
current_value: 1000
persist_value: 1000
SET_TIME: 2020-10-12 18:53:19.336115
SET_USER: root
VARIABLE_SOURCE: DYNAMIC
VARIABLE_PATH:
2 rows in set (0.06 sec)
mysql> restart;
Query OK, 0 rows affected (0.01 sec)
select v.VARIABLE_NAME,g.VARIABLE_VALUE current_value,p.VARIABLE_VALUE as persist_value,SET_TIME,SET_USER,VARIABLE_SOURCE,VARIABLE_PATH from performance_schema.variables_info v JOIN performance_schema.persisted_variables p USING(VARIABLE_NAME) JOIN performance_schema.global_variables g USING(VARIABLE_NAME)G
*************************** 1. row ***************************
VARIABLE_NAME: innodb_log_file_size
current_value: 100663296
persist_value: 100663296
SET_TIME: 2020-10-12 18:54:35.725177
SET_USER: arun
VARIABLE_SOURCE: PERSISTED
VARIABLE_PATH: /var/lib/mysql/mysqld-auto.cnf
*************************** 2. row ***************************
VARIABLE_NAME: max_connections
current_value: 1000
persist_value: 1000
SET_TIME: 2020-10-12 18:53:19.335909
SET_USER: root
VARIABLE_SOURCE: PERSISTED
VARIABLE_PATH: /var/lib/mysql/mysqld-auto.cnf
2 rows in set (0.16 sec)