目錄
正文
The Admin Schemas
ProxySQL管理界面是一個使用MySQL協議的界面,任何能夠通過這種界面發送命令的客戶端都很容易配置它。
ProxySQL解析通過此接口發送的查詢以查找特定於ProxySQL的任何命令,如果適當,則將它們發送到嵌入式SQLite3引擎以運行查詢。
請注意,SQLite3和MySQL使用的SQL語法不同,因此並非所有適用於MySQL的命令都適用於SQLite3。 例如,盡管管理界面接受USE命令,但它不會更改默認架構,因為SQLite3中不提供此功能。
連接到ProxySQL管理界面時,我們可以看到有一些數據庫可用。 ProxySQL將SHOW DATABASES命令轉換為SQLite3的等效命令。

這些數據庫的作用如下:
main:內存配置數據庫 。
使用此數據庫,可以輕松地以自動方式查詢和更新ProxySQL的配置。使用LOAD MYSQL USERS FROM MEMORY和類似命令,存儲在此處的配置可以在運行時傳播到ProxySQL使用的內存數據結構。
disk:基於磁盤的“main”鏡像。
在重新啟動時,“main”不會持久存在,並且可以從“磁盤”數據庫或配置文件中加載,具體取決於啟動標志和磁盤數據庫的存在。stats:包含從代理的內部功能收集的運行時指標。
示例度量標准包括每個查詢規則匹配的次數,當前運行的查詢等。monitor:包含與ProxySQL連接的后端服務器相關的監控指標。
示例度量標准包括連接到后端服務器或對其進行ping操作的最短和最長時間。myhgm:僅在調試版本中啟用
此外,使用這兩種類型的用戶使用這些默認憑據訪問管理數據庫:user:admin / password:admin - 具有對所有表的讀寫訪問權限
user:stats / password:stats - 具有對統計表的只讀訪問權限。 這用於從ProxySQL中提取指標,而不會暴露太多的數據庫
上述的訪問憑據,可通過變量admin-admin_credentials和admin-stats_credentials進行配置。
MAIN數據庫
主要包含了以下數據表:
核心配置表
1. mysql_server
字段定義
hostgroup_id
包含此mysqld實例的主機組。 請注意,同一實例可以是多個主機組的一部分
hostname,port
可以聯系mysqld實例的TCP端點
gtid_port
ProxySQL Binlog Reader偵聽GTID跟蹤的后端服務器端口
status
ONLINE - 后端服務器完全可以運行
SHUNNED - 后端服務器暫時停止使用,因為在時間太短或復制延遲超過允許閾值的情況下連接錯誤太多
OFFLINE_SOFT - 當服務器進入OFFLINE_SOFT模式時,不再接受新的傳入連接,而現有連接將保持不變,直到它們變為非活動狀態。 換句話說,連接一直在使用,直到當前事務完成。 這允許優雅地分離后端
OFFLINE_HARD - 當服務器進入OFFLINE_HARD模式時,現有連接被丟棄,而新的傳入連接也不被接受。 這相當於從主機組中刪除服務器,或暫時將其從主機組中取出以進行維護工作
weight
服務器相對於其他權重的權重越大,從主機組中選擇服務器的概率就越高
compression
如果該值大於0,則與該服務器的新連接將使用壓縮
max_connections
ProxySQL將向此后端服務器打開的最大連接數。 即使此服務器具有最高權重,但一旦達到此限制,就不會向其打開新連接。 請確保后端配置了正確的max_connections值,以避免ProxySQL嘗試超出該限制
max_replication_lag
如果更大且為0,ProxySQL將定期監視復制延遲,如果超出此閾值,它將暫時避開主機,直到復制趕上
use_ssl
如果設置為1,則與后端的連接將使用SSL
max_latency_ms
定期監視ping時間。 如果主機的ping時間大於max_latency_ms,則它將從連接池中排除(盡管服務器保持ONLINE狀態)
comment
可用於用戶定義的任何目的的文本字段。 可以是主機存儲內容的描述,添加或禁用主機的提醒,或某些檢查器腳本處理的JSON。
2. mysql_replication_hostgroups

字段定義
writer_hostgroup - 默認情況下將發送所有請求的主機組,MySQL中read_only = 0的節點將分配給該主機組。
reader_hostgroup - 應該發送讀取請求的主機組,應該定義查詢規則或單獨的只讀用戶將流量路由到此主機組,將read_only = 1的節點分配給該主機組。
check_type - 執行只讀檢查時檢查的MySQL變量,默認情況下為read_only(也可以使用super_read_only)。 對於AWS Aurora,應使用innodb_read_only。
comment - 可用於用戶定義的任何目的的文本字段。 可以是集群存儲內容的描述,添加或禁用主機組的提醒,或某些檢查器腳本處理的JSON。
3. mysql_group_replication_hostgroups(MGR)

字段定義
writer_hostgroup - 默認情況下將發送所有請求的主機組,MySQL中read_only = 0的節點將分配給該主機組。
backup_writer_hostgroup - 如果集群有多個節點,其read_only = 0和max_writers,則ProxySQL會將其他節點(超過max_writes的節點)放入backup_writer_hostgroup中。
reader_hostgroup - 應該發送讀請求的主機組,將read_only = 1的節點分配給該主機組。
offline_hostgroup - 當ProxySQL的監視確定節點為OFFLINE時,它將被放入offline_hostgroup。
active - 啟用時,ProxySQL監視主機組並在適當的主機組之間移動節點。
max_writers' - 此值確定writer_hostgroup中應允許的最大節點數,超過此值的節點將放入backup_writer_hostgroup中
writer_is_also_reader - 確定是否應將同一個節點添加到reader_hostgroup和writer_hostgroup中。
max_transactions_behind - 確定在屏蔽節點之前,ProxySQL應允許的寫入器后面的最大事務數,以防止讀取落后過多(這是通過查詢MySQL中sys.gr_member_routing_candidate_status表的transactions_behind字段來確定的)。
comment - 可用於用戶定義的任何目的的文本字段。 可以是集群存儲內容的描述,添加或禁用主機組的提醒,或某些檢查器腳本處理的JSON。
4. mysql_galera_hostgroups(PXC)

字段定義
writer_hostgroup - 默認情況下將發送所有流量的主機組,MySQL中read_only = 0的節點將分配給該主機組。
backup_writer_hostgroup - 如果集群有多個節點,其read_only = 0和max_writers,則ProxySQL會將其他節點(超過max_writes)放入backup_writer_hostgroup中。
reader_hostgroup - 應該發送讀取流量的主機組,應該定義查詢規則或單獨的只讀用戶將流量路由到此主機組,將read_only = 1的節點分配給該主機組。
offline_hostgroup - 當ProxySQL的監控確定主機處於OFFLINE時,它將被放入offline_hostgroup
active - 啟用時,ProxySQL監視主機組並在適當的主機組之間移動服務器。
max_writers - 此值確定writer_hostgroup中應允許的最大節點數,超過此值的節點將放入backup_writer_hostgroup中
writer_is_also_reader - 確定是否應將節點添加到reader_hostgroup以及在提升后的writer_hostgroup。
max_transactions_behind - 確定在避開節點之前ProxySQL應允許的集群后面的最大寫集數,以防止過時讀取(這是通過查詢wsrep_local_recv_queue Galera變量確定的)。
comment - 可用於用戶定義的任何目的的文本字段。 可以是集群存儲內容的描述,添加或禁用主機組的提醒,或某些檢查器腳本處理的JSON。
5. mysql_users

字段定義
username,password - 用於連接mysqld或ProxySQL實例的憑據。
active - 將在數據庫中跟蹤active = 0的用戶,但永遠不會在內存數據結構中加載
default_hostgroup - 如果此用戶發送的查詢沒有匹配規則,則生成的流量將發送到指定的主機組
default_schema - 默認情況下連接應更改的架構
schema_locked - 尚不支持(TODO:check)
transaction_persistent - 如果是一個事務內的多條SQL,只會路由到一個主機組中。
fast_forward - 如果設置,它繞過查詢處理層(重寫,緩存)並直接將查詢傳遞給后端服務器。
frontend - 如果設置為1,則此(用戶名,密碼)對用於對ProxySQL實例進行身份驗證
backend - 如果設置為1,則此(用戶名,密碼)對用於針對任何主機組對mysqld服務器進行身份驗證
max_connections - 定義特定用戶的最大允許前端連接數。
comment - 可用於用戶定義的任何目的的文本字段。 可以是集群存儲內容的描述,添加或禁用主機組的提醒,或某些檢查器腳本處理的JSON。
注意,目前所有用戶都需要將“frontend”和“后backend”都設置為1。
ProxySQL的未來版本將在前端和后端之間分離證書。
通過這種方式,前端永遠不會知道直接連接到后端的憑證,強制通過ProxySQL進行所有連接並提高系統的安全性。
fast_forward 注意事項:
1. 它不需要不同的端口:完整的功能代理邏輯和“快進”邏輯在同一代碼/模塊中實現
2. fast_forward是基於每個用戶實現的:取決於連接到ProxySQL的用戶,啟用或禁用fast_forward
3. 驗證后啟用fast_forward算法:客戶端仍然對ProxySQL進行身份驗證,當客戶端開始發送流量時,ProxySQL將創建連接。 這意味着在連接階段仍然會處理連接錯誤。
4. fast_forward不支持SSL
5. 如果使用壓縮,則必須在兩端啟用它
注意:mysql_users中的用戶也不應該與admin-admin_credentials和admin-stats_credentials里的配置相同
6. mysql_query_rules

字段定義
rule_id - 規則的唯一ID。 規則以rule_id順序處理
active - 查詢處理模塊將僅考慮active = 1的規則,並且只將活動規則加載到運行時。
username - 匹配用戶名的過濾條件。 如果為非NULL,則僅當使用正確的用戶名建立連接時,查詢才會匹配
schemaname - 匹配schemaname的過濾條件。 如果為非NULL,則僅當連接使用schemaname作為默認模式時,查詢才會匹配(在mariadb / mysql schemaname中等效於databasename)
flagIN,flagOUT,apply -
這些允許我們創建一個接一個地應用的“規則鏈”。
輸入標志值設置為0,並且在開始時僅考慮flagIN = 0的規則。
當為特定查詢找到匹配規則時,將評估flagOUT,如果為NOT NULL,則將使用flagOUT中的指定標志標記查詢。
如果flagOUT與flagIN不同,則查詢將退出當前鏈並輸入一個新的規則鏈,其中flagIN作為新的輸入標志。
如果flagOUT與flagIN匹配,則將針對具有所述flagIN的第一個規則再次重新評估查詢。
這種情況會發生,直到沒有更多匹配規則,或者apply設置為1(這意味着這是要應用的最后一條規則)
client_addr - 匹配來自特定源的流量
proxy_addr - 匹配特定本地IP上的傳入流量
proxy_port - 匹配特定本地端口上的傳入流量
使用stats_mysql_query_digest.digest返回的特定摘要匹配查詢
match_digest - 與查詢摘要匹配的正則表達式。 另請參見https://github.com/sysown/proxysql/wiki/Global-variables#mysql-query_processor_regex
match_pattern - 與查詢文本匹配的正則表達式。 另請參見https://github.com/sysown/proxysql/wiki/Global-variables#mysql-query_processor_regex
negate_match_pattern - 如果將其設置為1,則只有與查詢文本不匹配的查詢才會被視為匹配項。 這在與match_pattern或match_digest匹配的正則表達式前面充當NOT運算符
re_modifiers -
用逗號分隔的選項列表,用於修改RE引擎的行為。 使用CASELESS,匹配不區分大小寫。
使用GLOBAL,替換是全局的(替換所有匹配而不僅僅是第一個匹配)。
為了向后兼容,默認情況下僅啟用CASELESS。 有關更多詳細信息,另請參見https://github.com/sysown/proxysql/wiki/Global-variables#mysql-query_processor_regex。
replace_pattern -
這是用於替換匹配模式的模式。
它是使用RE2 :: Replace完成的,因此值得一看有關的在線文檔:https://github.com/google/re2/blob/master/re2/re2.h#L378。
請注意,這是可選的,當缺少此選項時,查詢處理器將僅緩存,路由或設置其他參數而不重寫。
destination_hostgroup -
將匹配的查詢路由到此主機組。
除非存在已啟動的事務且登錄用戶將transaction_persistent標志設置為1(請參閱mysql_users表),否則會發生這種情況。
cache_ttl - 緩存查詢結果的毫秒數。 注意:在ProxySQL 1.1中,cache_ttl只需幾秒鍾
cache_empty_result -
控制是否緩存沒有行的結果集
重新連接 - 未使用的功能
timeout -
應執行匹配或重寫查詢的最大超時(以毫秒為單位)。
如果查詢運行的時間超過特定閾值,則會自動終止查詢。 如果未指定timeout,則應用全局變量mysql-default_query_timeout
retries - 在執行查詢期間檢測到失敗時需要重新執行查詢的最大次數。 如果未指定重試,則應用全局變量mysql-query_retries_on_failure
delay -
延遲執行查詢的毫秒數。
這本質上是一種限制機制和QoS,允許優先考慮某些查詢而不是其他查詢。
此值將添加到適用於所有查詢的mysql-default_query_delay全局變量中。 未來版本的ProxySQL將提供更高級的限制機制。
mirror_flagOUT和mirror_hostgroup - 與鏡像相關的設置 https://github.com/sysown/proxysql/wiki/Mirroring。
error_msg - 將阻止查詢,並將指定的error_msg返回給客戶端
OK_msg - 將為使用已定義規則的查詢返回指定的消息
sticky_conn - 尚未實現
multiplex -
如果為0,則禁用Multiplex。
如果為1,如果沒有任何其他條件阻止此操作(如用戶變量或事務),則可以重新啟用Multiplex。
如果為2,則不會僅針對當前查詢禁用多路復用。 請參閱wiki默認為NULL,因此不會修改多路復用策略
gtid_from_hostgroup - 定義哪個主機組應該用作GTID一致性讀取的領導者(通常是復制主機組對中定義的WRITER主機組)
log- 將記錄查詢
apply - 當設置為1時,在匹配和處理此規則后,將不再評估進一步的查詢(注意:之后不會評估mysql_query_rules_fast_routing規則)
comment- 自由格式文本字段,可用於查詢規則的描述性注釋
7. mysql_query_rules_fast_routing

字段定義
username - 與用戶名匹配的過濾條件,只有在使用正確的用戶名建立連接時,查詢才會匹配
schemaname - 匹配schemaname的過濾條件,只有當連接使用schemaname作為默認模式時,查詢才會匹配(在mariadb / mysql schemaname中,這相當於databasename)
flagIN - 與mysql_query_rules中flagin相同,並與mysql_query_rules表中指定的flagout / apply相關聯
destination_hostgroup - 將匹配的查詢路由到此主機組。
comment- 自由格式文本字段,可用於查詢規則的描述性注釋
8. global_variables\mysql_collations\scheduler 暫不介紹了,后面會逐步投在功能介紹里提及
Runtime層對應表
- runtime_global_variables : runtime version of global_variables
- runtime_mysql_replication_hostgroups : runtime version of mysql_replication_hostsgroups
- runtime_mysql_galera_hostgroups : runtime version of mysql_replication_hostsgroups
- runtime_mysql_group_replication_hostgroups : runtime version of mysql_replication_hostsgroups
- runtime_mysql_query_rules : runtime version of mysql_query_rules
- runtime_mysql_query_rules_fast_routing : runtime version of mysql_query_rules_fast_routing
- runtime_mysql_servers : runtime version of mysql_servers
- runtime_mysql_users : runtime version of mysql_users
- runtime_proxysql_servers : runtime version of proxysql_servers
- runtime_scheduler : runtime version of scheduler
Disk層對應表
監控MGR,需要在MySQL實例中配置一些監控腳本(MySQL 5.7 和 MySQL 8.0略有不同)
先看看執行效果
select * from sys.gr_member_routing_candidate_status; +------------------+-----------+---------------------+----------------------+ | viable_candidate | read_only | transactions_behind | transactions_to_cert | +------------------+-----------+---------------------+----------------------+ | YES | NO | 0 | 0 | +------------------+-----------+---------------------+----------------------+ viable_candidate:MGR當前節點是否正常 read_only:當前節點是否開啟了只讀 transactions_behind:MGR應用relay log的隊列中,積壓事務數 transactions_to_cert:MGR當前節點的驗證隊列,積壓事務數
MySQL5.7,配置腳本為:
USE sys; DELIMITER $$ CREATE FUNCTION IFZERO(a INT, b INT) RETURNS INT DETERMINISTIC RETURN IF(a = 0, b, a)$$ CREATE FUNCTION LOCATE2(needle TEXT(10000), haystack TEXT(10000), offset INT) RETURNS INT DETERMINISTIC RETURN IFZERO(LOCATE(needle, haystack, offset), LENGTH(haystack) + 1)$$ CREATE FUNCTION GTID_NORMALIZE(g TEXT(10000)) RETURNS TEXT(10000) DETERMINISTIC RETURN GTID_SUBTRACT(g, '')$$ CREATE FUNCTION GTID_COUNT(gtid_set TEXT(10000)) RETURNS INT DETERMINISTIC BEGIN DECLARE result BIGINT DEFAULT 0; DECLARE colon_pos INT; DECLARE next_dash_pos INT; DECLARE next_colon_pos INT; DECLARE next_comma_pos INT; SET gtid_set = GTID_NORMALIZE(gtid_set); SET colon_pos = LOCATE2(':', gtid_set, 1); WHILE colon_pos != LENGTH(gtid_set) + 1 DO SET next_dash_pos = LOCATE2('-', gtid_set, colon_pos + 1); SET next_colon_pos = LOCATE2(':', gtid_set, colon_pos + 1); SET next_comma_pos = LOCATE2(',', gtid_set, colon_pos + 1); IF next_dash_pos < next_colon_pos AND next_dash_pos < next_comma_pos THEN SET result = result + SUBSTR(gtid_set, next_dash_pos + 1, LEAST(next_colon_pos, next_comma_pos) - (next_dash_pos + 1)) - SUBSTR(gtid_set, colon_pos + 1, next_dash_pos - (colon_pos + 1)) + 1; ELSE SET result = result + 1; END IF; SET colon_pos = next_colon_pos; END WHILE; RETURN result; END$$ CREATE FUNCTION gr_applier_queue_length() RETURNS INT DETERMINISTIC BEGIN RETURN (SELECT sys.gtid_count( GTID_SUBTRACT( (SELECT Received_transaction_set FROM performance_schema.replication_connection_status WHERE Channel_name = 'group_replication_applier' ), (SELECT @@global.GTID_EXECUTED) ))); END$$ CREATE FUNCTION gr_member_in_primary_partition() RETURNS VARCHAR(3) DETERMINISTIC BEGIN RETURN (SELECT IF( MEMBER_STATE='ONLINE' AND (( SELECT COUNT() FROM performance_schema.replication_group_members WHERE MEMBER_STATE != 'ONLINE') >= (( SELECT COUNT() FROM performance_schema.replication_group_members)/2) = 0), 'YES', 'NO' ) FROM performance_schema.replication_group_members JOIN performance_schema.replication_group_member_stats USING(member_id)); END$$ CREATE VIEW gr_member_routing_candidate_status AS SELECT sys.gr_member_in_primary_partition() AS viable_candidate, IF((SELECT (SELECT GROUP_CONCAT(variable_value) FROM performance_schema.global_variables WHERE variable_name IN ('read_only' , 'super_read_only')) != 'OFF,OFF' ), 'YES', 'NO') AS read_only, sys.gr_applier_queue_length() AS transactions_behind, Count_Transactions_in_queue AS 'transactions_to_cert' FROM performance_schema.replication_group_member_stats$$ DELIMITER ;
MySQL8.0,配置腳本為:
USE sys; DELIMITER $$ CREATE FUNCTION IFZERO(a INT, b INT) RETURNS INT DETERMINISTIC RETURN IF(a = 0, b, a)$$ CREATE FUNCTION LOCATE2(needle TEXT(10000), haystack TEXT(10000), offset INT) RETURNS INT DETERMINISTIC RETURN IFZERO(LOCATE(needle, haystack, offset), LENGTH(haystack) + 1)$$ CREATE FUNCTION GTID_NORMALIZE(g TEXT(10000)) RETURNS TEXT(10000) DETERMINISTIC RETURN GTID_SUBTRACT(g, '')$$ CREATE FUNCTION GTID_COUNT(gtid_set TEXT(10000)) RETURNS INT DETERMINISTIC BEGIN DECLARE result BIGINT DEFAULT 0; DECLARE colon_pos INT; DECLARE next_dash_pos INT; DECLARE next_colon_pos INT; DECLARE next_comma_pos INT; SET gtid_set = GTID_NORMALIZE(gtid_set); SET colon_pos = LOCATE2(':', gtid_set, 1); WHILE colon_pos != LENGTH(gtid_set) + 1 DO SET next_dash_pos = LOCATE2('-', gtid_set, colon_pos + 1); SET next_colon_pos = LOCATE2(':', gtid_set, colon_pos + 1); SET next_comma_pos = LOCATE2(',', gtid_set, colon_pos + 1); IF next_dash_pos < next_colon_pos AND next_dash_pos < next_comma_pos THEN SET result = result + SUBSTR(gtid_set, next_dash_pos + 1, LEAST(next_colon_pos, next_comma_pos) - (next_dash_pos + 1)) - SUBSTR(gtid_set, colon_pos + 1, next_dash_pos - (colon_pos + 1)) + 1; ELSE SET result = result + 1; END IF; SET colon_pos = next_colon_pos; END WHILE; RETURN result; END$$ CREATE FUNCTION gr_applier_queue_length() RETURNS INT DETERMINISTIC BEGIN RETURN (SELECT sys.gtid_count( GTID_SUBTRACT( (SELECT Received_transaction_set FROM performance_schema.replication_connection_status WHERE Channel_name = 'group_replication_applier' ), (SELECT @@global.GTID_EXECUTED) ))); END$$ CREATE FUNCTION gr_member_in_primary_partition() RETURNS VARCHAR(3) DETERMINISTIC BEGIN RETURN (SELECT IF( MEMBER_STATE='ONLINE' AND ((SELECT COUNT(*) FROM performance_schema.replication_group_members WHERE MEMBER_STATE != 'ONLINE') >= ((SELECT COUNT(*) FROM performance_schema.replication_group_members)/2) = 0), 'YES', 'NO' ) FROM performance_schema.replication_group_members JOIN performance_schema.replication_group_member_stats USING(member_id) where performance_schema.replication_group_members.member_host=@@hostname); END$$ CREATE VIEW gr_member_routing_candidate_status AS SELECT sys.gr_member_in_primary_partition() AS viable_candidate, IF((SELECT (SELECT GROUP_CONCAT(variable_value) FROM performance_schema.global_variables WHERE variable_name IN ('read_only' , 'super_read_only')) != 'OFF,OFF' ), 'YES', 'NO') AS read_only, sys.gr_applier_queue_length() AS transactions_behind, Count_Transactions_in_queue AS 'transactions_to_cert' FROM performance_schema.replication_group_member_stats a JOIN performance_schema.replication_group_members b ON a.member_id = b.member_id WHERE b.member_host IN (SELECT variable_value FROM performance_schema.global_variables WHERE variable_name = 'hostname')$$ DELIMITER ;