返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.html
1.配置后端節點前的說明
為了讓ProxySQL能夠找到后端的MySQL節點,需要將后端的MySQL Server加入到ProxySQL中。ProxySQL的一切配置行為都是在修改main庫中的對應的表,所以添加節點到ProxySQL中實際上也是通過修改相關表來實現的。
管理后端節點有幾個過程:
- 將后端MySQL Server的主從復制結構配置好。
- 將后端MySQL Server節點加入到ProxySQL中。相關的表為
mysql_servers
。 - 監控后端節點。相關的表是全局變量表
global_vairbles
,相關的變量為mysql-monitor_
開頭的變量。 - 配置讀、寫組。相關的表為
mysql_replication_hostgroups
。 - 配置MySQL用戶,用於發送SQL語句。相關的表為
mysql_users
。
幾個注意點:
-
(1).ProxySQL是通過監控后端節點的
read_only
值來自動調整節點所屬組的,例如read_only=1
的節點會移動到讀組,read_only=0
的節點會移動到寫組。所以,在配置讀、寫組之前,需要先監控后端節點。ProxySQL也支持手動管理后端節點,這種模式不會根據read_only的值自動調整,在后面的文章中會介紹這種模式。 -
(2).對於傳統的主從復制,默認的
read_only=0
,所以在第一步中,各slave節點的配置文件中需要加上read_only=1
。對於組復制、Galera,因為會自動強制設置非寫節點的read_only=1
,所以無需額外配置該屬性。 -
(3).ProxySQL支持傳統主從復制結構(即異步、半同步、gtid復制)的后端,讀、寫組相關的表是
mysql_replication_hostgroups
。還支持MySQL組復制結構的后端,相關的表是mysql_group_replication_hostgroups
,還支持Galera(如percona XtraDB cluster)結構的后端,不過ProxySQL是通過scheduler調度proxysql_galera_checker.sh
腳本來支持Galera的,而且目前還沒有mysql_galera_hostgroups
(ProxySQL 2.0才新增該表)。
本文暫時只解釋mysql_servers
和mysql_replication_hostgroups
,組復制相關的表在在后面介紹"ProxySQL+組復制"的文章中再介紹。
完成了上面的過程后,節點就一切正常了,然后就可以去配置ProxySQL的路由規則、查詢緩存、SQL語句重寫等功能。這些在后面的文章會詳細介紹。
在開始本文下面的配置之前,請確保已經明白如何使用Admin管理接口,以及ProxySQL的多層配置系統。
2.添加新節點:mysql_servers表
假如后端有3個節點,使用的是傳統的異步復制(1 master, 2 slave)。這3個節點的IP地址為:
192.168.100.22
192.168.100.23
192.168.100.24
要加入3個后端MySQL節點,只需向mysql_servers表插入3行對應的記錄即可。以下是使用了一大堆默認值的insert語句:
insert into mysql_servers(hostgroup_id,hostname,port)
values(10,'192.168.100.22',3306);
insert into mysql_servers(hostgroup_id,hostname,port)
values(10,'192.168.100.23',3306);
insert into mysql_servers(hostgroup_id,hostname,port)
values(10,'192.168.100.24',3306);
load mysql servers to runtime;
save mysql servers to disk;
上面的insert語句表示將后端MySQL節點192.168.100.xx:3306
加入到hostgroup_id=10
的組中。
其實mysql_servers表有很多字段,很多字段都有默認值,正如上面的insert語句,除了3個字段,其它使用的全是字段的默認值。
以下是mysql_servers表的字段屬性。
| 字段 | 數據類型 | 允許null | 默認值 |
|---------------------|----------|-----------|--------|
| hostgroup_id (pk) | int | not null | 0 |
| hostname (pk) | varchar | not null | 無 |
| port (pk) | int | not null | 3306 |
| status | varchar | not null | online |
| weight | int | not null | 1 |
| compression | int | not null | 0 |
| max_connections | int | not null | 1000 |
| max_replication_lag | int | not null | 0 |
| use_ssl | int | not null | 0 |
| max_latency_ms | int | not null | 0 |
| comment | varchar | not null | '' |
可見,新添加一個節點時,唯一必須指定的字段就是hostname值。如果不指定hostgroup_id
,那么節點將自動加入到hostgroup_id=0
的組中。
各字段的意義如下:
- hostgroup_id:該后端MySQL實例所在的主機組。注意,同一MySQL節點可屬於多個主機組。
- hostname,port:后端MySQL監聽的地址和端口。就是默認3306端口的意義
- status:
- ONLINE:該后端MySQL節點完全正常。
- SHUNNED:該后端MySQL節點將暫時被ProxySQL自動避開(忽略),原因可能是一個較短時間內發生了大量連接錯誤,也可能是該slave與master的數據延遲太大(replication lag)。
- OFFLINE_SOFT:當某后端MySQL被設置為 OFFLINE_SOFT 時,ProxySQL將不會向它發送新的請求,但該節點正在執行的事務會繼續執行,直到所有事務執行完畢后會進入非激活狀態。也就是說,和該后端的連接會保持到事務執行完畢。這可以實現后端節點的graceful停止、重啟。
- OFFLINE_HARD:當某后端MySQL被設置為 OFFLINE_HARD 時,ProxySQL將不會向它發送新的請求,該節點正在執行的事務也會立即中斷。也就是直接將該后端殺掉。等價於刪除該節點,或臨時將其移除出組(例如出於維護的目的)。
- weight:節點在組中的權重值越高,ProxySQL會發送越多請求給它們。
- compression:如果該字段的值設置為大於0,ProxySQL和該后端新建的連接中,ProxySQL將會先壓縮數據再傳輸。
- max_connections:和該后端允許建立的最大連接數。當達到最大數量時,即使該后端的權重很大,也不會和它新建連接。默認值為1000,表示每個后端最多能同時接受1000個連接。請確保該后端的
max_connections
值是合理的,以避免MySQL超負荷時ProxySQL繼續向其發送請求。 - max_replication_lag:如果值大於0,ProxySQL的Monitor模塊將會定期檢查該slave的復制是否延后於master,如果延遲的值大於該字段的值,ProxySQL將會暫時避開該節點,直到該slave趕上master。
- use_ssl:如果設置為1,則和該后端MySQL建立SSL連接。
- max_latency_ms:Monitory模塊定期向該后端發起ping檢查,如果該節點的ping時間大於該字段的值,則將其排除在連接池之外(盡管該節點仍處於ONLINE狀態)。
- comment:該表的說明信息,可隨便定義。
關於該表各字段的用法,請參見官方手冊(我已翻譯)。
以下是上面插入數據成功后的結果:
admin> select * from mysql_servers\G
*************************** 1. row ***************************
hostgroup_id: 10
hostname: 192.168.100.22
port: 3306
status: ONLINE
weight: 1
compression: 0
max_connections: 1000
max_replication_lag: 0
use_ssl: 0
max_latency_ms: 0
comment:
*************************** 2. row ***************************
hostgroup_id: 10
hostname: 192.168.100.23
port: 3306
status: ONLINE
weight: 1
compression: 0
max_connections: 1000
max_replication_lag: 0
use_ssl: 0
max_latency_ms: 0
comment:
*************************** 3. row ***************************
hostgroup_id: 10
hostname: 192.168.100.24
port: 3306
status: ONLINE
weight: 1
compression: 0
max_connections: 1000
max_replication_lag: 0
use_ssl: 0
max_latency_ms: 0
comment:
需要注意的是,同一個節點是可以同時存在於多個組中的。最典型的情形是master既充當寫節點,也充當讀節點,這時它就同時存在於寫組和讀組。
3.監控后端節點
ProxySQL通過Monitor模塊監控后端MySQL Server的read_only
值來自動調整節點所屬的組。所以,在配置讀、寫組之前,必須先配置好監控。
本文只簡單介紹該模塊的監控類型,以及如何配置監控。對於Monitor模塊理論的詳細介紹,請參見以下兩篇文章:
- Monitor模塊官方手冊翻譯:關於Monitor模塊和相關變量。
- Monitor模塊使用的線程池、連接池
3.1 Monitor模塊可以監控什么東西
首先看下Monitor庫中的表:
admin> show tables from monitor;
+------------------------------------+
| tables |
+------------------------------------+
| mysql_server_connect_log |
| mysql_server_group_replication_log |
| mysql_server_ping_log |
| mysql_server_read_only_log |
| mysql_server_replication_lag_log |
+------------------------------------+
Monitor監控4種指標:connect、ping、read_only和replication lag。下面稍作介紹。
1.connect監控
ProxySQL連接到各后端是否成功,成功/失敗的連接將記錄到表mysql_server_connect_log
中。
2.ping監控
這是一種心跳檢測。Monitor模塊向所有后端MySQL節點發起ping檢查,ping成功/失敗的情況將記錄到表mysql_server_ping_log
中。當ping某后端的失敗次數達到了mysql-monitor_ping_max_failures
時表示失去心跳,將發送一個信號給MySQL的主機組管理器來殺掉和該后端節點的所有連接。
請和connect監控區分開,connect監控是通過建立連接來檢測和后端節點連接的連通性。ping監控是心跳檢測,ProxySQL通過MySQL的一個ping API發送給后端MySQL服務上,然后等待ping回復,雖然是ping檢測,但也是需要建立連接的。
所以,有兩個確定連接不可用公式:
- mysql-monitor_ping_max_failures * mysql-monitor_connect_timeout
- mysql-monitor_ping_max_failures * mysql-monitor_ping_timeout
3.read_only監控
檢查mysql_replication_hostgroups
表中所有節點的read_only
值,並記錄到mysql_server_read_only_log
。如果read_only=1
,表示只讀,是一個slave,這樣的節點將會自動移入reader_hostgroup
中,如果read_only=0
,表示可寫,可能是master,這樣的節點將會自動移入writer_hostgroup
中。
4.replication lag監控
對mysql_servers
表中所有配置了max_replication_lag
的后端slave節點都檢查復制延遲,通過show slave status
返回結果中的Seconds_Behind_Master
字段,判斷slave和master之間的延遲程度,並記錄到mysql_server_replication_lag_log
表中。
如果Seconds_Behind_Master > max_replication_lag,表示該slave延遲很嚴重,ProxySQL會自動避開這種slave節點,直到Seconds_Behind_Master < max_replication_lag。
Monitor監控上述指標時,會使用MySQL節點上的用戶連接到后端節點,所以,需要先在后端節點上創建負責監控的用戶。監控connect、ping和read_only這3項指標時,該用戶只需具有USAGE
權限,如果要監控replication lag指標,則需要replication client
權限。
3.2 配置connect和ping監控
首先,在后端節點上創建用於監控的用戶,順便為其授予replication client
權限。只需在一個寫節點(例如master)上創建即可,它會復制到其它節點上。
create user monitor@'192.168.100.%' identified by 'P@ssword1!';
grant replication client on *.* to monitor@'192.168.100.%';
然后,在ProxySQL上配置這個監控用戶,配置方式是修改全局變量。
set mysql-monitor_username='monitor';
set mysql-monitor_password='P@ssword1!';
由於ProxySQL上所有的配置修改都是在修改main庫中對應的表,上面的變量在main.global_variables
中,所以上面兩個set語句和下面兩個update語句是等價的。
update global_variables set variable_value='monitor'
where variable_name='mysql-monitor_username';
update global_variables set variable_value='P@ssword1!'
where variable_name='mysql-monitor_password';
在將配置load到runtime之前,可以先查看下connect和ping對應的log表。
admin> select * from mysql_server_connect_log;
+----------------+------+------------------+-------------------------+---------------+
| hostname | port | time_start_us | connect_success_time_us | connect_error |
+----------------+------+------------------+-------------------------+---------------+
| 192.168.100.22 | 3306 | 1530968712977867 | 4174 | NULL |
| 192.168.100.23 | 3306 | 1530968712988986 | 4908 | NULL |
| 192.168.100.24 | 3306 | 1530968713000074 | 3044 | NULL |
| 192.168.100.22 | 3306 | 1530968772978982 | 3407 | NULL |
| 192.168.100.23 | 3306 | 1530968772989627 | 3404 | NULL |
| 192.168.100.24 | 3306 | 1530968773000778 | 3444 | NULL |
+----------------+------+------------------+-------------------------+---------------+
admin> select * from mysql_server_ping_log;
+----------------+------+------------------+----------------------+-------------+
| hostname | port | time_start_us | ping_success_time_us | ping_error |
+----------------+------+------------------+----------------------+-------------+
| 192.168.100.22 | 3306 | 1530968712666540 | 452 | NULL |
| 192.168.100.23 | 3306 | 1530968712668779 | 458 | NULL |
| 192.168.100.24 | 3306 | 1530968712671541 | 324 | NULL |
| 192.168.100.22 | 3306 | 1530968722667071 | 1190 | NULL |
| 192.168.100.23 | 3306 | 1530968722669574 | 1162 | NULL |
| 192.168.100.24 | 3306 | 1530968722673162 | 1380 | NULL |
+----------------+------+------------------+----------------------+-------------+
不難發現,監控操作在load到runtime之前就已經生效了。這是有意為之的:通過這種方式,可以在節點添加到生產環境之前執行一些基本的健康檢查。
監控的節點一切正常后(error=NULL),將配置load到runtime。
load mysql variables to runtime;
save mysql variables to disk;
3.3 配置read_only監控和讀/寫組
目前read_only和replication_lag的監控日志還是空。
admin> select * from mysql_server_read_only_log;
Empty set (0.00 sec)
admin> select * from mysql_server_replication_lag_log;
Empty set (0.00 sec)
這是因為還沒有對ProxySQL中的節點分組:writer_hostgroup、reader_hostgroup。
設置分組信息,需要修改的是main庫中的mysql_replication_hostgroups
表(組復制則是mysql_group_replication_hostgroups
),該表只有3個字段:第一個字段名為writer_hostgroup,第二個字段為reader_hostgroup,第三個字段為注釋字段,可隨意寫。
例如,指定寫組的id為10,讀組的id為20。
insert into mysql_replication_hostgroups values(10,20);
admin> select * from mysql_replication_hostgroups;
+------------------+------------------+----------+
| writer_hostgroup | reader_hostgroup | comment |
+------------------+------------------+----------+
| 10 | 20 | cluster1 |
+------------------+------------------+----------+
在該配置加載到RUNTIME生效之前,先查看下各mysql server所在的組。
admin> select hostgroup_id,hostname,port,status,weight from mysql_servers;
+--------------+----------------+------+--------+--------+
| hostgroup_id | hostname | port | status | weight |
+--------------+----------------+------+--------+--------+
| 10 | 192.168.100.22 | 3306 | ONLINE | 1 |
| 10 | 192.168.100.23 | 3306 | ONLINE | 1 |
| 10 | 192.168.100.24 | 3306 | ONLINE | 1 |
+--------------+----------------+------+--------+--------+
3個節點都在hostgroup_id=10
的組中。
現在,將剛才mysql_replication_hostgroups
表的修改加載到RUNTIME生效。
load mysql servers to runtime;
save mysql servers to disk;
一加載,Monitor模塊就會開始監控后端的read_only值,當監控到read_only值后,就會按照read_only的值將某些節點自動移動到讀/寫組。
例如,此處所有節點都在id=10
的寫組,slave1和slave2都是slave,它們的read_only=1
,這兩個節點將會移動到id=20
的組。如果一開始這3節點都在id=20
的讀組,那么移動的將是Master節點,會移動到id=10
的寫組。
看結果:
admin> select hostgroup_id,hostname,port,status,weight from mysql_servers;
+--------------+----------------+------+--------+--------+
| hostgroup_id | hostname | port | status | weight |
+--------------+----------------+------+--------+--------+
| 10 | 192.168.100.22 | 3306 | ONLINE | 1 |
| 20 | 192.168.100.23 | 3306 | ONLINE | 1 |
| 20 | 192.168.100.24 | 3306 | ONLINE | 1 |
+--------------+----------------+------+--------+--------+
配置好read_only的監控后,Monitor模塊會每隔一段時間監控一次read_only值。
admin> select * from mysql_server_read_only_log;
+----------------+------+------------------+-----------------+-----------+--------+
| hostname | port | time_start_us | success_time_us | read_only | error |
+----------------+------+------------------+-----------------+-----------+--------+
| 192.168.100.22 | 3306 | 1530970372197917 | 8487 | 0 | NULL |
| 192.168.100.23 | 3306 | 1530970372198992 | 7907 | 1 | NULL |
| 192.168.100.24 | 3306 | 1530970372199835 | 8064 | 1 | NULL |
| 192.168.100.22 | 3306 | 1530970373698824 | 10078 | 0 | NULL |
| 192.168.100.23 | 3306 | 1530970373699825 | 9845 | 1 | NULL |
| 192.168.100.24 | 3306 | 1530970373700786 | 10745 | 1 | NULL |
+----------------+------+------------------+-----------------+-----------+--------+
3.4 配置replication lag監控
Monitor模塊會監控后端主機組中各slave的數據是否延遲於master,這個延遲行為稱為replication lag
,俗稱拖后腿。
如果某個slave節點上的數據比master落后很多(臨界值見下文),表示這個slave節點處理速度慢,數據較舊。ProxySQL采用一種稱為自動避開(automatic shunned)的方式,臨時避開這個落后的節點。當ProxySQL避開某節點后,ProxySQL不會把SQL語句路由給這個節點。
ProxySQL有幾種情況可能會觸發自動避開節點的行為:
- 和后端的連接斷開。
- slave落后於master過多。
- 和后端建立連接時,錯誤次數過多。
- second_behind_master=null時,即slave的SQL線程未運行,或者slave未連接到master。(不過這種自動避開的情況是可控的,見全局變量mysql-monitor_slave_lag_when_null
本文介紹關於replication lag的內容。
Monitor模塊會每隔一段時間(mysql-monitor_replication_lag_interval
)去檢查一次拖后腿情況,檢測的方式是獲取show slave status
中的Seconds_Behind_Master
字段值,然后和mysql_servers
表中max_replication_lag
字段的值比較:
- Seconds_Behind_Master < max_replication_lag:表示落后程度尚在允許范圍內。
- Seconds_Behind_Master > max_replication_lag:表示落后太多,這樣的節點應該避開。
只有傳統復制結構的slave節點才需要設置max_replication_lag
字段,master無需設置,組復制和galera也無需設置,因為這兩種復制結構中show slave status
的結果為空。例如,將讀組中的所有節點都設置最多落后於master 10秒鍾。
update mysql_servers set max_replication_lag=10 where hostgroup_id=20;
load mysql servers to runtime;
save mysql servers to disk;
需要注意的是,Seconds_Behind_Master的值並不總是可靠的,見 https://dev.mysql.com/doc/refman/5.7/en/show-slave-status.html 。
4.關於主機組和read_only
前面為了將主機組分為讀組和寫組,特地開啟了monitor模塊的read_only監控功能,根據read_only的值以及mysql_replication_hostgroup表中定義的讀、寫組自動調整節點。
在簡單的環境下,這沒什么問題。但是想要實現復雜一點的讀、寫分離,比如寫操作路由到hostgroup_id=10的組,讀操作分多種情況路由,select1語句路由到hostgroup_id=20的讀組,select2語句路由到hostgroup_id=30的組,...。這種情況,想通過monitor模塊和mysql_replication_hostgroup表來實現是不可能的,因為mysql_replication_hostgroup表的writer_hostgroup字段是主鍵,reader_hostgroup字段具有唯一性,它們都是int類型,且不可重復。
admin> show create table main.mysql_replication_hostgroups\G
*************************** 1. row ***************************
table: mysql_replication_hostgroups
Create Table: CREATE TABLE mysql_replication_hostgroups (
writer_hostgroup INT CHECK (writer_hostgroup>=0) NOT NULL PRIMARY KEY,
reader_hostgroup INT NOT NULL CHECK (reader_hostgroup<>writer_hostgroup AND reader_hostgroup>0),
comment VARCHAR NOT NULL DEFAULT '', UNIQUE (reader_hostgroup))
1 row in set (0.00 sec)
換句話說,每一個寫組只能且必須對應單個讀組(經測試,reader_hostgroup字段可以為空),無法實現hg_id=10是寫組,而hg_id=20、hg_id=30同時作為讀組。
顯然ProxySQL不可能限制的這么死。實際上,完全可以不用定義mysql_replication_hostgroup表,也不用定義monitor模塊的read_only監控(如果沒有定義mysql_replication_hostgroup,read_only監控會自動停止),這時只能人為控制不要把寫操作路由到后端的slave上。
例如:
delete from mysql_replication_hostgroup;
delete from mysql_servers;
insert into mysql_servers(hostgroup_id,hostname,port)
values(10,'192.168.100.22',3306),
(20,'192.168.100.23',3306),
(30,'192.168.100.24',3306);
load mysql servers to runtime;
save mysql servers to disk;
事實上,在實現ProxySQL復雜、高級的路由功能時,都不會通過monitor模塊去自動控制讀、寫組。
5.向ProxySQL添加MySQL用戶:mysql_users表
配置好后端MySQL節點、監控、分組后,接下來要配置的是MySQL的用戶。
需要注意,ProxySQL中有3套用戶:
- 連接Admin管理接口(默認6032端口)使用一套用戶名/密碼。
- 分為管理員和普通用戶,管理員用戶具有寫權限,能配置ProxySQL,普通用戶只有幾個庫的讀權限。
- 管理員用戶/密碼通過變量
admin-admin_credentials
設置,普通用戶/密碼通過變量admin-stats_credentials
設置。 - 這部分用戶名不能出現在mysql_users表中。
- Monitor模塊監控后端時,需要使用一個MySQL用戶連接后端進行監控。
- 需要先在后端MySQL組中創建好這個用戶監控的用戶。
- 監控connect、ping和read_only時,只需
USAGE
權限,監控replication lag時需要replication client
權限。 - 通過變量
mysql-monitor_username
和mysql-monitor_password
將監控用戶加入到ProxySQL中。
- 前端連接ProxySQL(默認6033端口)、ProxySQL連接后端MySQL時使用一套用戶名/密碼。
- 當前端app發送SQL請求時,需要使用這套用戶。然后ProxySQL將SQL語句路由給某后端節點,需要使用同一個用戶和后端建立連接並將SQL語句發送出去。
- 需要現在后端MySQL組中創建好這套用戶,因為ProxySQL需要連接后端,所以一般授權所有權限,例如root。
- 通過mysql_users表將這些用戶加入到ProxySQL中,每一行對應一個用戶。
5.1 添加MySQL users到ProxySQL
例如,使用root用戶來處理SQL請求。先在后端的寫節點(如master節點)上授權root,該操作會復制給其它節點。
grant all on *.* to root@'192.168.100.%' identified by 'P@ssword1!';
然后,向ProxySQL的mysql_users
插入這個用戶即可。這個表的字段很多,大多數字段都有默認值,以下是大部分使用默認值的插入語句:
insert into mysql_users(username,password,default_hostgroup)
values ('root','P@ssword1!',10);
load mysql users to runtime;
save mysql users to disk;
上面指定了root用戶的用戶名、密碼以及該用戶默認的路由目標組。
ProxySQL有多種粒度的路由規則,每個用戶都有默認的路由目標組,當使用該用戶發送的SQL語句沒有能夠匹配的語句級路由規則,則會將該SQL語句路由給該用戶默認的路由目標組。
例如,navicat工具使用root用戶連接到了ProxySQL,發送了一個select語句,如果沒有配置select語句的路由規則,那么這個select語句將默認路由給root用戶的默認組。
下面先介紹一下mysql_users
表中的密碼相關內容,然后再詳細介紹mysql_users
表。
5.2 mysql_users表中用戶的密碼管理
ProxySQL向mysql_users
表添加用戶時,支持明文密碼和hash加密密碼。這個hash密碼和mysql的password()
的算法是一樣的。
但是,ProxySQL內部使用的是SQLite3引擎,不支持password()
。所以,想要向ProxySQL中使用hash加密密碼,可以先通過mysql的password()
函數創建一個hash密碼,然后copy到mysql_users表中。
例如:
[root@s4 ~]# mysql -uroot -pP@ssword1! -e 'select password("P@ssword1!");'
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------------------------------------+
| password("P@ssword1!") |
+-------------------------------------------+
| *50572A5FABC7DA9CEE5EB5977EDDE59E38967422 |
+-------------------------------------------+
然后插入到ProxySQL的mysql_users表:
insert into mysql_users(username,password,default_hostgroup)
values ('root','*50572A5FABC7DA9CEE5EB5977EDDE59E38967422',10);
ProxySQL和MySQL對密碼的處理方式都是:以"*"開頭的密碼,表示是hash加密密碼。
在MySQL和ProxySQL中,使用SHA1(SHA1('clear_password'))
對clear_password進行加密。無法根據加密的hash密碼推導回原始的明文密碼。
當客戶端連接到ProxySQL時,ProxySQL將使用該加密的密碼對用戶進行認證。如果該客戶端是第一次認證,則ProxySQL會推導出一部分的hash密碼SHA1('clear_password')
。推導出的信息會存儲到runtime的內部數據結構中,以便ProxySQL連接后端MySQL時使用。
從1.2.3版本開始,引入了一個布爾類型的全局變量admin-hash_passwords
,默認為true。該變量表示,內存數據庫的mysql_users
表中的明文密碼,在load mysql users to runtime
時,對明文密碼進行hash加密,並保存到runtime數據結構中。有了這個特性,可以以另一種方式保存加密密碼:只需將其刷回內存數據庫即可。
例如:
Admin> SELECT username,password FROM mysql_users;
+----------+-----------+
| username | password |
+----------+-----------+
| user1 | password1 | # 明文密碼
| user2 | password2 |
+----------+-----------+
Admin> LOAD MYSQL USERS TO RUNTIME; # 加載到runtime數據結構
Admin> SELECT username,password FROM mysql_users;
+----------+-----------+
| username | password |
+----------+-----------+
| user1 | password1 | # 還是明文密碼
| user2 | password2 |
+----------+-----------+
這個時候,runtime數據結構中的密碼是加密密碼,而內存數據庫中的密碼是明文密碼。
將runtime數據結構數據刷回內存數據庫,即可將加密密碼保存到內存數據庫中,然后還可以將加密的密碼持久化到disk。
Admin> save mysql users to memory;
Admin> SELECT username,password FROM mysql_users;
+----------+-------------------------------------------+
| username | password |
+----------+-------------------------------------------+
| user1 | *668425423DB5193AF921380129F465A6425216D0 |
| user2 | *DC52755F3C09F5923046BD42AFA76BD1D80DF2E9 |
+----------+-------------------------------------------+
Admin> save mysql users to disk;
唯一需要注意的是,admin-hash-passwords
變量是admin-
變量而非mysql-
變量,這意味着修改了這個變量后(雖然基本不會去修改),load/save操作的目標是"admin variables",而非"mysql variables"。
load admin variables to runtime;
save admin variables to disk;
5.3 mysql_users表詳細解釋
以下是mysql_users
表的屬性。
| 字段名 | 數據類型 | 可為空? | 默認值 |
|-----------------------|---------|----------|-------|
|username (pk,uk) | VARCHAR | NOT NULL | |
|password | VARCHAR | NULL | |
|active | INT | NOT NULL | 1 |
|use_ssl | INT | NOT NULL | 0 |
|default_hostgroup | INT | NOT NULL | 0 |
|default_schema | VARCHAR | NULL | |
|schema_locked | INT | NOT NULL | 0 |
|transaction_persistent | INT | NOT NULL | 1 |
|fast_forward | INT | NOT NULL | 0 |
|backend (pk) | INT | NOT NULL | 1 |
|frontend (uk) | INT | NOT NULL | 1 |
|max_connections | INT | NOT NULL | 10000 |
各字段的意義:
- username, password:前端連接到ProxySQL以及ProxySQL連接到后端時使用的用戶憑據。
- active:
active=0
的用戶會保留在庫中,但不會加載到runtime數據結構中,只有active=1
用戶才是有效用戶。該字段默認值為1。 - default_hostgroup:如果該用戶發送的查詢語句無法匹配任何規則,則該查詢會路由到該字段指定的默認組中。
- default_schema:建立連接時默認將切換到該schema。
- schema_locked:目前還不支持該功能。
- transaction_persistent:如果正在和ProxySQL建立連接的客戶端使用的用戶設置了該字段,那么當該用戶開啟一個事務后,該客戶端后續的請求都將路由到同一主機組中(無視查詢規則),使得事務在這個組中是持久的,避免同一事務分散到其它組,直到事務結束才可能會路由到其它主機組。注意,有些老版本中,這個字段默認值為0,強烈建議修改為1。
- fast_forward:如果設置了該字段,ProxySQL將繞過查詢處理層(重寫語句、緩存),直接將原請求語句轉發給后端節點。
- frontend:如果設置為1,前端將可以使用該用戶(username,password)連接到ProxySQL。
- backend:如果設置為1,ProxySQL將可以使用該用戶(username,password)連接到后端節點。
- max_connections:使用該用戶"建立到ProxySQL的連接"的最大數量。默認值為10000,所以每個用戶最多和ProxySQL建立10000個連接。注意,這是前端到ProxySQL的連接限制,ProxySQL和某個后端節點的最大連接數量是通過
mysql_servers
中的max_connections
字段控制的。
注意,當前版本的ProxySQL要求所有的用戶均設置frontend和backend為1(即所有用戶都可以進行frontend --> ProxySQL
以及ProxySQL --> backend
的連接認證)。將來版本中,ProxySQL將分離這兩部分連接的用戶憑據。這樣前端將永遠不知道后端的用戶憑據,它們只能通過中間的ProxySQL發送請求,無法直接和后端節點建立連接,從而提高安全性。
關於快速轉發fast_forward:
- 不要求用一個不同的端口:正常的ProxySQL邏輯和"fast forward"的邏輯使用的是完全相同的代碼/模塊。
- fast forward是基於每用戶的:根據連接到ProxySQL用戶的設置,決定該用戶是否啟用、禁用fast forward功能。
- fast forward算法的啟用是在用戶認證之后:ProxySQL仍然需要先對客戶端使用的用戶進行認證,盡管客戶端的請求會直接原樣轉發給后端,但ProxySQL仍然會和前端先建立好連接。這意味着,如果前端和ProxySQL的連接發生錯誤,也會被處理。
- fast forward不支持SSL連接。
- 如果使用壓縮功能,必須在兩端都啟用壓縮。
5.4 事務持久化:transaction_persistent
mysql_users表中的transaction_persistent
字段,當它的值為1時,表示事務持久化:當某連接使用該用戶開啟了一個事務后,那么在事務提交/回滾之前,所有的語句都路由到同一個組中,避免語句分散到不同組。在以前的版本中,默認值為0,不知道從哪個版本開始,它的默認值為1。我們期望的值為1,所以強烈建議插入用戶后先檢查下這個字段的值是否為1,如果為0,則執行下面的語句修改為1。
update mysql_users set transaction_persistent=1 where username='root';
update mysql_users set transaction_persistent=1 where username='sqlsender';
load mysql users to runtime;
save mysql users to disk;
6.總結
添加后端節點、監控后端節點、添加MySQL用戶是使用ProxySQL所必須完成的步驟。這3個步驟雖然需要操作的過程不多,但是涉及的內容還是比較多的。
強烈建議將mysql_servers、mysql_users、mysql_replication_hostgroups這3個表的所有字段都了解一遍。不僅如此,要熟練使用ProxySQL,還應該對main庫中的表的各個字段都比較熟悉,至少要知道它們什么意思。
下面,將添加后端節點、監控后端節點、添加MySQL用戶的操作過程抽取出來,算是個步驟總結:
######### 1.添加后端節點
#
#
insert into mysql_servers(hostgroup_id,hostname,port) values
(10,'192.168.100.22',3306),
(10,'192.168.100.23',3306),
(10,'192.168.100.24',3306);
load mysql servers to runtime;
save mysql servers to disk;
# 查看下各節點是否都是 ONLINE
select * from mysql_servers\G
######### 2.在后端MySQL上創建監控用戶和處理SQL語句的用戶
#
# 在后端master節點上執行以下語句
#
create user monitor@'192.168.100.%' identified by 'P@ssword1!';
grant replication client on *.* to monitor@'192.168.100.%';
grant all on *.* to root@'192.168.100.%' identified by 'P@ssword1!';
######### 3.在ProxySQL中配置監控用戶
#
#
set mysql-monitor_username='monitor';
set mysql-monitor_password='P@ssword1!';
# 以上兩個set語句等價於下面兩個update:
update global_variables set variable_value='monitor'
where variable_name='mysql-monitor_username';
update global_variables set variable_value='P@ssword1!'
where variable_name='mysql-monitor_password';
load mysql variables to runtime;
save mysql variables to disk;
# 查看下connect和ping的監控是否正常
select * from mysql_server_connect_log order by time_start_us desc limit 6;
select * from mysql_server_ping_log order by time_start_us desc limit 6;
######### 4.配置讀、寫組
#
#
insert into mysql_replication_hostgroups values(10,20);
load mysql servers to runtime;
save mysql servers to disk;
######### 5.在ProxySQL中配置MySQL用戶
#
#
insert into mysql_users(username,password,default_hostgroup)
values ('root','P@ssword1!',10);
load mysql users to runtime;
save mysql users to memory;
save mysql users to disk;
update mysql_users set transaction_persistent=1 where username='root';
load mysql users to runtime;
save mysql users to disk;
在后面的文章中,我會介紹以下percona版本的ProxySQL,percona ProxySQL提供了一個管理工具,它能通過額外的配置文件自動化配置上面一大堆的操作,大大簡化了初始搭建使用ProxySQL的過程。