導讀:html
在以前,咱們搭建了MySQL組複製集羣環境,MySQL組複製集羣環境解決了MySQL集羣內部的自動故障轉移,可是,組複製並無解決外部業務的故障轉移。舉個例子,在A、B、C 3臺機器上搭建了組複製環境,且運行在單主模式下,這裏假設A爲主節點,應用程序鏈接A寫數據,若是A節點發生宕機,主節點切換到B機器上,此時,應用程序是不會自動鏈接到B服務器上的,須要人工進行切換。node
在這篇文章中,咱們要介紹的ProxySQL就可以解決上面的問題,ProxySQL可以實現業務層面故障轉移、讀寫分離功能,固然ProxySQL不只僅只有這兩項功能,還有更多的其它功能。其架構以下:mysql
咱們不妨來了解一下。git
ProxySQL是一款MySQL代理軟件,其核心特色爲讀寫分離、故障轉移,詳細其功能以下:github
這裏,咱們使用ProxySQL來對MySQL組複製環境實現讀寫分離以及故障轉移。個人環境以下:sql
IP地址 | 主機名 | 用途 |
192.168.10.11 | mgr-node1 | MySQL組複製成員 |
192.168.10.12 | mgr-node2 | MySQL組複製成員 |
192.168.10.13 | mgr-node3 | MySQL組複製成員 |
192.168.10.10 | proxysql | ProxySQL代理服務器 |
MySQL採用多主模式,搭建過程見文檔:《MySQL組複製MGR(二)-- 組複製搭建》,本文把重點放在ProxySQL的搭建與配置上。shell
(二)安裝ProxySQL數據庫
安裝ProxySQL,有2種方法,若是有網絡,能夠直接使用yum安裝,若是沒有網絡,能夠下載ProxySQL發行包安裝,下載地址爲:https://github.com/sysown/proxysql/releases。這裏爲了方便,直接使用yum在線安裝。
添加yum源,使用Linux root用戶執行以下配置:後端
cat <<EOF | tee /etc/yum.repos.d/proxysql.repo [proxysql_repo] name= ProxySQL YUM repository baseurl=https://repo.proxysql.com/ProxySQL/proxysql-2.0.x/centos/\$releasever gpgcheck=1 gpgkey=https://repo.proxysql.com/ProxySQL/repo_pub_key EOF
安裝proxysql:centos
yum install -y proxysql OR yum install proxysql-version
若是要查看安裝的文件在哪,可使用以下命令:
[root@proxysql yum.repos.d]# rpm -ql proxysql /etc/logrotate.d/proxysql /etc/proxysql.cnf /etc/systemd/system/proxysql-initial.service /etc/systemd/system/proxysql.service /usr/bin/proxysql /usr/share/proxysql/tools/proxysql_galera_checker.sh /usr/share/proxysql/tools/proxysql_galera_writer.pl
查看ProxySQL進程:
[root@proxysql yum.repos.d]# ps -ef|grep proxy avahi 740 1 0 15:52 ? 00:00:00 avahi-daemon: registering [proxysql-65.local] root 761 1 0 15:52 ? 00:00:00 /usr/sbin/gssproxy -D proxysql 2058 1 0 16:09 ? 00:00:00 /usr/bin/proxysql --idle-threads -c /etc/proxysql.cnf proxysql 2059 2058 1 16:09 ? 00:00:00 /usr/bin/proxysql --idle-threads -c /etc/proxysql.cnf root 2087 1589 0 16:09 pts/0 00:00:00 grep --color=auto proxy
查看端口,6032是proxysql的管理端口,6033是對外服務端口
[root@proxysql yum.repos.d]# netstat -anlp | grep proxysql tcp 0 0 0.0.0.0:6032 0.0.0.0:* LISTEN 2059/proxysql tcp 0 0 0.0.0.0:6033 0.0.0.0:* LISTEN 2059/proxysql
(三)啓動關閉ProxySQL
啓動ProxySQL
service proxysql start
關閉ProxySQL
service proxysql stop
重啓ProxySQL
service proxysql restart
查看ProxySQL的狀態
service proxysql status
(四)ProxySQL基礎知識瞭解
ProxySQL的配置,相對而言仍是比較複雜的。所以,在配置ProxySQL以前,咱們須要對其架構有一些瞭解,這樣在配置的時候,纔不會一臉懵逼。
(4.1)ProxySQL多層配置系統
前面咱們說到ProxySQL具備「零停機時間變動」功能,它是經過3層配置來實現的,3層配置包括:Runtime、Memory、Disk & Configuration File。
3個層面的信息有什麼區別呢?我我的的理解是:3個層面保存的都是ProxySQL的配置信息,若是管理員未做修改,那麼3個層面的配置信息是相同的。若是管理員要修改配置信息,首先須要修改Memory層,要讓修改的信息馬上生效,則須要把Memory層的變動信息推到Runtime層;要讓修改的配置信息在ProxySQL重啓後還能保存下來,則須要把Memory層的信息推到Disk層。Runtime層是ProxySQL正在使用的配置信息,Memory層是用戶能夠編輯的信息,Disk層能夠把配置信息永久保存在磁盤上。
各層之間數據如何同步呢?咱們能夠看上圖的箭頭部分,經過load/save命令來實現同步。具體命令以下:
[1] LOAD <item> FROM MEMORY/LOAD <item> TO RUNTIME 將配置項從內存數據庫加載到運行時數據結構 [2] SAVE <item> TO MEMORY/SAVE <item> FROM RUNTIME 將配置項從運行時保存到內存數據庫中 [3] LOAD <item> TO MEMORY/LOAD <item> FROM DISK 將持久性配置項目從磁盤數據庫加載到內存數據庫 [4] SAVE <item> FROM MEMORY/SAVE <item> TO DISK 將配置項從內存數據庫保存到磁盤數據庫 [5] LOAD <item> FROM CONFIG 將配置項從配置文件加載到內存數據庫中
經常使用的配置有:
# 激活用戶配置到RUNTIME LOAD MYSQL USERS TO RUNTIME; # 保存用戶信息到磁盤上 SAVE MYSQL USERS TO DISK; --------------------------------- # 激活MySQL服務器信息到RUNTIME LOAD MYSQL SERVERS TO RUNTIME; # 保存MySQL服務器信息到磁盤 SAVE MYSQL SERVERS TO DISK; --------------------------------- # 激活查詢路由規則到RUNTIME LOAD MYSQL QUERY RULES TO RUNTIME; # 保存查詢路由規則到磁盤 SAVE MYSQL QUERY RULES TO DISK; ---------------------------------- # 激活MySQL變量到RUNTIME LOAD MYSQL VARIABLES TO RUNTIME; # 保存MySQL變量到磁盤 SAVE MYSQL VARIABLES TO DISK; ---------------------------------- # 激活proxySQL admin變量到RUNTIME LOAD ADMIN VARIABLES TO RUNTIME; # 保存proxySQL admin變量到磁盤 SAVE ADMIN VARIABLES TO DISK;
(4.2)ProxySQL的配置管理接口
ProxySQL有2種配置方式:
一般使用第一種方法進行配置,這裏咱們只瞭解第1種方法。
ProxySQL管理界面使用的是MySQL協議的界面,經過使用mysql客戶端鏈接到SQLite3進行配置的查詢、管理。可使用默認的admin用戶鏈接到proxySQL數據庫。
[root@proxysql ~]# mysql -uadmin -padmin -h127.0.0.1 -P6032 mysql> show databases; +-----+---------------+-------------------------------------+ | seq | name | file | +-----+---------------+-------------------------------------+ | 0 | main | | | 2 | disk | /var/lib/proxysql/proxysql.db | | 3 | stats | | | 4 | monitor | | | 5 | stats_history | /var/lib/proxysql/proxysql_stats.db | +-----+---------------+-------------------------------------+
這些數據庫做用以下:
ProxySQL設定了2個用戶來管理配置數據庫:
(五)一步一步配置ProxySQL--基礎配置
(5.1)檢查配置信息
查看相關配置表是否存在信息,由於還沒開始配置,因此是不存在信息的,若是已經配置過了,能夠先刪除信息。
mysql> select * from mysql_servers; Empty set (0.00 sec) mysql> select * from mysql_users; Empty set (0.01 sec) mysql> select * from mysql_query_rules; Empty set (0.00 sec) mysql> select * from mysql_group_replication_hostgroups; Empty set (0.00 sec)
(5.2)組的配置
所謂組的配置,即定義讀組、寫組等,可使用以下兩個表來定義讀寫組:
由於咱們這裏是使用proxySQL來實現MGR集羣業務層面的實現故障轉移以及讀寫分離的,因此配置mysql_group_replication_hostgroups表便可,該表定義以下:
show create table mysql_group_replication_hostgroups; ------------------------------------------------------------ CREATE TABLE mysql_group_replication_hostgroups ( writer_hostgroup INT CHECK (writer_hostgroup>=0) NOT NULL PRIMARY KEY, backup_writer_hostgroup INT CHECK (backup_writer_hostgroup>=0 AND backup_writer_hostgroup<>writer_hostgroup) NOT NULL, reader_hostgroup INT NOT NULL CHECK (reader_hostgroup<>writer_hostgroup AND backup_writer_hostgroup<>reader_hostgroup AND reader_hostgroup>0), offline_hostgroup INT NOT NULL CHECK (offline_hostgroup<>writer_hostgroup AND offline_hostgroup<>reader_hostgroup AND backup_writer_hostgroup<>offline_hostgroup AND offline_hostgroup>=0), active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1, max_writers INT NOT NULL CHECK (max_writers >= 0) DEFAULT 1, writer_is_also_reader INT CHECK (writer_is_also_reader IN (0,1,2)) NOT NULL DEFAULT 0, max_transactions_behind INT CHECK (max_transactions_behind>=0) NOT NULL DEFAULT 0, comment VARCHAR, UNIQUE (reader_hostgroup), UNIQUE (offline_hostgroup), UNIQUE (backup_writer_hostgroup))
這些字段含義以下:
咱們對該表進行以下配置:
mysql> select * from mysql_group_replication_hostgroups; +------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------+ | writer_hostgroup | backup_writer_hostgroup | reader_hostgroup | offline_hostgroup | active | max_writers | writer_is_also_reader | max_transactions_behind | comment | +------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------+ | 1 | 2 | 3 | 4 | 1 | 1 | 0 | 100 | NULL | +------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------+
(5.3)視圖添加
若是ProxySQL是與組複製MGR一塊兒使用的,那麼還須要在MGR集羣添加以下視圖:
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 ;
而後受權給監控用戶,這裏須要特別注意,個人監控用戶在5.5.1步才建立,所以這一步須要放到5.5.1後執行:
grant select on sys.* to monitoring_user;
(5.4)MySQL服務器添加
mysql_server表是用來存儲ProxySQL路由轉換的MySQL節點的信息。
mysql> insert into mysql_servers (hostgroup_id, hostname, port) values(1,'192.168.10.11',3306); mysql> insert into mysql_servers (hostgroup_id, hostname, port) values(1,'192.168.10.12',3306); mysql> insert into mysql_servers (hostgroup_id, hostname, port) values(1,'192.168.10.13',3306); mysql> select * from mysql_servers; +--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ | hostgroup_id | hostname | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment | +--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ | 1 | 192.168.10.11 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 1 | 192.168.10.12 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 1 | 192.168.10.13 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | +--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
而後執行下面的命令生效:
LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;
(5.5)監控配置及檢查
這裏配置監控信息,用來監控ProxySQL與後端的MySQL通訊是否正常。
(5.5.1)監控用戶配置
在ProxySQL的變量表裏面設定監控用戶密碼,用於ProxySQL監控後端MySQL服務器的用戶信息
mysql> UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_username'; Query OK, 1 row affected (0.00 sec) mysql> UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_password'; Query OK, 1 row affected (0.00 sec) mysql> select variable_name,variable_value from global_variables where variable_name in ('mysql-monitor_username','mysql-monitor_password'); +------------------------+----------------+ | variable_name | variable_value | +------------------------+----------------+ | mysql-monitor_password | monitor | | mysql-monitor_username | monitor | +------------------------+----------------+
須要注意,既然使用該用戶監控後臺MySQL數據庫,那麼後臺MySQL數據庫也須要建立該用戶並受權,monitor用戶須要有usage權限去鏈接、ping和檢查read_only信息,若是要檢測複製延遲,還須要具備replication client權限。特別注意,不能使用mysql_users裏面的用戶來作監控用戶。
-- 在MySQL服務器上建立監控用戶 -- 須要注意,這裏MySQL使用的是MGR,因此只須要在一臺節點建立用戶便可,其它節點會自動同步用戶信息 create user monitor@'%' identified by 'monitor'; grant usage,replication client on *.* to monitor@'%'; flush privileges;
注意:由於ProxySQL+組複製添加了新的視圖,見」5.3 視圖添加」,所以還需受權:
grant select on sys.* to monitor;
(5.5.2)配置監控間隔
這裏把鏈接、ping、read_only監控間隔改成2s,也能夠根據須要改爲其它,也能夠不作修改
mysql> update global_variables set variable_value='2000' -> where variable_name in('mysql-monitor_connect_interval','mysql-monitor_ping_interval','mysql-monitor_read_only_interval'); Query OK, 3 rows affected (0.00 sec) mysql> select * from global_variables where variable_name like 'mysql-monitor%'; +--------------------------------------------------------------+----------------+ | variable_name | variable_value | +--------------------------------------------------------------+----------------+ | mysql-monitor_enabled | true | | mysql-monitor_connect_timeout | 600 | | mysql-monitor_ping_max_failures | 3 | | mysql-monitor_ping_timeout | 1000 | | mysql-monitor_read_only_max_timeout_count | 3 | | mysql-monitor_replication_lag_interval | 10000 | | mysql-monitor_replication_lag_timeout | 1000 | | mysql-monitor_groupreplication_healthcheck_interval | 5000 | | mysql-monitor_groupreplication_healthcheck_timeout | 800 | | mysql-monitor_groupreplication_healthcheck_max_timeout_count | 3 | | mysql-monitor_groupreplication_max_transactions_behind_count | 3 | | mysql-monitor_galera_healthcheck_interval | 5000 | | mysql-monitor_galera_healthcheck_timeout | 800 | | mysql-monitor_galera_healthcheck_max_timeout_count | 3 | | mysql-monitor_replication_lag_use_percona_heartbeat | | | mysql-monitor_query_interval | 60000 | | mysql-monitor_query_timeout | 100 | | mysql-monitor_slave_lag_when_null | 60 | | mysql-monitor_threads_min | 8 | | mysql-monitor_threads_max | 128 | | mysql-monitor_threads_queue_maxsize | 128 | | mysql-monitor_wait_timeout | true | | mysql-monitor_writer_is_also_reader | true | | mysql-monitor_username | monitor | | mysql-monitor_password | monitor | | mysql-monitor_history | 600000 | | mysql-monitor_connect_interval | 2000 | | mysql-monitor_ping_interval | 2000 | | mysql-monitor_read_only_interval | 2000 | | mysql-monitor_read_only_timeout | 500 | +--------------------------------------------------------------+----------------+ 30 rows in set (0.01 sec)
在修改完變量以後,必定要加載到內存中生效以及永久保存到磁盤中:
LOAD MYSQL VARIABLES TO RUNTIME; SAVE MYSQL VARIABLES TO DISK;
(5.5.3)檢查監控信息是否存在異常
監控配置完成後,咱們須要檢查ProxySQL與後端MySQL通訊是否有異常,monitor數據庫中的表用於存儲監視信息,須要注意的是,這些表並不是都已經被使用。
mysql> show tables from monitor; +--------------------------------------+ | tables | +--------------------------------------+ | mysql_server_aws_aurora_check_status | | mysql_server_aws_aurora_failovers | | mysql_server_aws_aurora_log | | mysql_server_connect_log | | mysql_server_galera_log | | mysql_server_group_replication_log | | mysql_server_ping_log | | mysql_server_read_only_log | | mysql_server_replication_lag_log | +--------------------------------------+
查看ProxySQL與後臺服務器鏈接是否正常:
mysql> select * from monitor.mysql_server_connect_log order by time_start_us desc limit 10; +---------------+------+------------------+-------------------------+---------------+ | hostname | port | time_start_us | connect_success_time_us | connect_error | +---------------+------+------------------+-------------------------+---------------+ | 192.168.10.13 | 3306 | 1596263409501584 | 2191 | NULL | | 192.168.10.11 | 3306 | 1596263409480641 | 1911 | NULL | | 192.168.10.12 | 3306 | 1596263409459524 | 3671 | NULL | | 192.168.10.13 | 3306 | 1596263407504677 | 1451 | NULL | | 192.168.10.11 | 3306 | 1596263407481776 | 1398 | NULL | | 192.168.10.12 | 3306 | 1596263407458859 | 1378 | NULL | | 192.168.10.12 | 3306 | 1596263405490389 | 3480 | NULL | | 192.168.10.13 | 3306 | 1596263405474367 | 2804 | NULL | | 192.168.10.11 | 3306 | 1596263405458569 | 1612 | NULL | | 192.168.10.13 | 3306 | 1596263403497485 | 2132 | NULL | +---------------+------+------------------+-------------------------+---------------+ 10 rows in set (0.00 sec)
查看組複製是否正常,檢查節點是否只讀和交易滯後時間:
mysql> select * from mysql_server_group_replication_log order by time_start_us desc limit 10; +---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+ | hostname | port | time_start_us | success_time_us | viable_candidate | read_only | transactions_behind | error | +---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+ | 192.168.10.13 | 3306 | 1596263494597039 | 5671 | YES | NO | 0 | NULL | | 192.168.10.12 | 3306 | 1596263494596052 | 3231 | YES | NO | 0 | NULL | | 192.168.10.11 | 3306 | 1596263494595139 | 3245 | YES | NO | 0 | NULL | | 192.168.10.13 | 3306 | 1596263489596357 | 3027 | YES | NO | 0 | NULL | | 192.168.10.12 | 3306 | 1596263489595491 | 3306 | YES | NO | 0 | NULL | | 192.168.10.11 | 3306 | 1596263489594645 | 3110 | YES | NO | 0 | NULL | | 192.168.10.13 | 3306 | 1596263484595710 | 3680 | YES | NO | 0 | NULL | | 192.168.10.12 | 3306 | 1596263484594839 | 3618 | YES | NO | 0 | NULL | | 192.168.10.11 | 3306 | 1596263484594114 | 3214 | YES | NO | 0 | NULL | | 192.168.10.13 | 3306 | 1596263479595072 | 1887 | YES | NO | 0 | NULL | +---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+ 10 rows in set (0.01 sec)
查看ProxySQL ping後端MySQL服務器是否正常:
mysql> select * from mysql_server_ping_log order by time_start_us desc limit 10; +---------------+------+------------------+----------------------+------------+ | hostname | port | time_start_us | ping_success_time_us | ping_error | +---------------+------+------------------+----------------------+------------+ | 192.168.10.12 | 3306 | 1596263541810631 | 496 | NULL | | 192.168.10.11 | 3306 | 1596263541786903 | 612 | NULL | | 192.168.10.13 | 3306 | 1596263541762973 | 749 | NULL | | 192.168.10.12 | 3306 | 1596263539796079 | 565 | NULL | | 192.168.10.13 | 3306 | 1596263539779040 | 403 | NULL | | 192.168.10.11 | 3306 | 1596263539762769 | 1141 | NULL | | 192.168.10.12 | 3306 | 1596263537797512 | 848 | NULL | | 192.168.10.11 | 3306 | 1596263537779520 | 845 | NULL | | 192.168.10.13 | 3306 | 1596263537761840 | 742 | NULL | | 192.168.10.12 | 3306 | 1596263535814945 | 843 | NULL | +---------------+------+------------------+----------------------+------------+ 10 rows in set (0.00 sec)
經過監控信息,咱們能夠得出結論,全部配置都是健康的,繼續下一步。
(5.6)用戶配置
(5.6.1)ProxySQL的雙層用戶認證機制
若是使用了ProxySQL來作中間路由,那麼與咱們平時登陸數據庫有一些區別:平時咱們直接使用數據庫的用戶密碼,便可訪問到數據庫,若是使用了ProxySQL,則要先使用帳號密碼訪問到ProxySQL的數據庫,而後再由ProxySQL進行用戶請求的轉發,那麼,ProxySQL中的用戶與數據庫層的用戶有什麼關聯呢?很奇怪,這部分ProxySQL竟然沒在文檔裏面給出來。
只能本身測試了,通過我的測試,發現:當中間件用戶與數據庫用戶以及密碼一致時,才能正常訪問數據庫。測試結果以下:
MySQL數據庫用戶(mysql.user表) | ProxySQL用戶(main.mysql_users表) | 使用ProxySQL的6033端口訪問數據庫 |
usera | usera | 正常訪問 |
userb | 沒法登入proxysql | |
userc | 能夠登入proxysql,可是沒法讀寫 |
這裏是個人測試過程:
在MySQL數據庫上建立用戶:usera和userb
create user `usera`@`%` identified by '123456'; grant all privileges on *.* to `usera`@`%`; create user `userb`@`%` identified by '123456'; grant all privileges on *.* to `userb`@`%`; flush privileges;
在ProxySQL上建立用戶:usera和userc
insert into mysql_users(username,password,default_hostgroup) values('usera','123456',1); insert into mysql_users(username,password,default_hostgroup) values('userc','123456',1); load mysql users to runtime; save mysql users to disk;
登入測試(分爲2步:先登入,再查詢):
(1)usera用戶登入無問題,查詢無問題
[root@proxysql ~]# mysql -uusera -p123456 -P6033 -h192.168.10.10 mysql> select count(*) from lijiamandb.test03; +----------+ | count(*) | +----------+ | 1 | +----------+ 1 row in set (0.01 sec)
(2)userb沒法登入,提示用戶名密碼錯誤
[root@proxysql ~]# mysql -uuserb -p123456 -P6033 -h192.168.10.10 mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 1045 (28000): ProxySQL Error: Access denied for user 'userb'@'192.168.10.10' (using password: YES)
(3)userc能夠正常登入,可是查詢的時候提示密碼不對
[root@proxysql ~]# mysql -uuserc -p123456 -P6033 -h192.168.10.10 mysql> mysql> select count(*) from lijiamandb.test03; ERROR 1045 (28000): Access denied for user 'userc'@'192.168.10.10' (using password: YES)
用戶認證小結:只有ProxySQL中的用戶名密碼與MySQL中的用戶名密碼相同時,才能正常訪問底層MySQL數據庫。所以,若是要使用ProxySQL訪問數據庫,須要在MySQL和ProxySQL中都要建立相同的帳號,而且密碼也要保持一致。
(5.6.2)ProxySQL用戶建立
ProxySQL的用戶保存在mysql_users表中,用戶建立直接執行insert插入便可。如建立一個用戶名爲「lijiaman」,密碼爲「123456」,默認用戶組爲1的用戶:
insert into mysql_users(username,password,default_hostgroup) values('lijiaman','123456',1);
load mysql users to runtime; save mysql users to disk;
mysql_users表最重要的字段爲:
(六)故障轉移(failover)測試
在上一節,咱們已經配置了:
此時,ProxySQL已經具有故障轉移的能力了,咱們進行測試一下。
STEP1:如今的配置以下,192.168.10.13主機是寫節點,其它2個節點是備用寫節點:
-- mysql_serve在memory層r的配置信息 mysql> select * from mysql_servers; +--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ | hostgroup_id | hostname | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment | +--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ | 1 | 192.168.10.11 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 1 | 192.168.10.12 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 1 | 192.168.10.13 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | +--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ 3 rows in set (0.00 sec) --加載到RUNTIME後,因爲組定義中最多隻有1個寫節點,其他的主節點移動到備用寫組裏面 mysql> select * from runtime_mysql_servers; +--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ | hostgroup_id | hostname | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment | +--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ | 2 | 192.168.10.11 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 1 | 192.168.10.13 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 2 | 192.168.10.12 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | +--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ 3 rows in set (0.01 sec)
使用ProxySQL來訪問MyQSL集羣,發現能夠支持讀寫
-- 使用ProxySQL 6033端口訪問MySQL數據庫 [root@proxysql ~]# mysql -uusera -p123456 -P6033 -h192.168.10.10 mysql> use testdb -- 經過主機名,額能夠看到,咱們訪問到的是寫節點 mysql> select @@hostname; +------------+ | @@hostname | +------------+ | mgr-node3 | +------------+ 1 row in set (0.00 sec) -- 能夠此次插入、查詢數據 mysql> insert into test01 values(1,'a'); Query OK, 1 row affected (0.00 sec) mysql> select * from test01; +----+------+ | id | name | +----+------+ | 1 | a | +----+------+ 1 row in set (0.00 sec)
STEP2:關閉寫節點
# 直接關閉主機 [root@mgr-node3 ~]# reboot
Connection closed by foreign host. Disconnected from remote host(mgr-node3) at 19:00:31. Type `help' to learn how to use Xshell prompt.
[c:\~]$ -- 須要注意的是,之前鏈接在主節點上的會話會斷開,不會轉移到新的主節點,很正常,Oracle也不會 mysql> select * from test01; ERROR 2013 (HY000): Lost connection to MySQL server during query
STEP3:查看是否會有備用寫節點轉爲寫節點,能夠看到192.168.10.12服務器已經轉爲寫節點,而已經關閉的192.168.10.13服務器已經進入離線組。
mysql> select * from runtime_mysql_servers; +--------------+---------------+------+-----------+---------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ | hostgroup_id | hostname | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment | +--------------+---------------+------+-----------+---------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ | 2 | 192.168.10.11 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 1 | 192.168.10.12 | 3306 | 0 | ONLINE | 1 | 0 | 1000 | 0 | 0 | 0 | | | 4 | 192.168.10.13 | 3306 | 0 | SHUNNED | 1 | 0 | 1000 | 0 | 0 | 0 | | +--------------+---------------+------+-----------+---------+--------+-------------+-----------------+---------------------+---------+----------------+---------+ 3 rows in set (0.00 sec)
STEP4:再次使用ProxySQL來訪問MyQSL集羣,發現能夠支持讀寫,業務不會因主節點的改變而受影響。
-- 使用ProxySQL 6033端口訪問MySQL數據庫 [root@proxysql ~]# mysql -uusera -p123456 -P6033 -h192.168.10.10 mysql> use testdb -- 經過主機名,額能夠看到,咱們訪問到的是新的寫節點 mysql> select @@hostname; +------------+ | @@hostname | +------------+ | mgr-node2 | +------------+ 1 row in set (0.00 sec) -- 能夠此次插入、查詢數據 mysql> insert into test01 values(2,'b'); Query OK, 1 row affected (0.00 sec)
經過上面的測試,能夠看到,MGR結合ProxySQL已經能夠實現業務的自動故障轉移。
接下來,咱們開始研究ProxySQL的讀寫分離功能。