ProxySQL快速上手

安裝並登陸管理界面

1 wgethttps://github.com/sysown/proxysql/releases/download/v1.3.6/proxysql-1.3.6-1-centos67.x86_64.rpm

2 yum install perl-DBD-MySQL

3 rpm -ivh proxysql-1.3.6-1-centos67.x86_64.rpm

4 service proxysql start

5 proxysql --version

ProxySQL version 1.3.6-0-g434b376, codename Truls

6 登陸管理界面(配置信息從啓動進程的配置文件查看)

mysql -u admin -padmin -h127.0.0.1 -P6032--prompt='proxysql>'

mysql -u admin -padmin -S /tmp/proxysql_admin.sock--prompt='proxysql>'

配置讀寫分離和路由規則

環境(三個後臺服務器,一主兩從的架構)

Master 10.9.160.248:3306

Slave1  10.9.117.107:3306  設置read_only

Slave2    10.9.150.86:3306    設置read_only

 
在db的主節點上創建proxy的監控賬戶和業務賬戶

GRANT ALLPRIVILEGES ON *.* TO 'monitor'@'%' IDENTIFIED BY ‘monitor’;

GRANT ALLPRIVILEGES ON *.* TO 'msandbox'@'%' IDENTIFIED BY ‘msandbox’;

在proxy管理命令行添加後端服務器列表

proxysql>INSERTINTO mysql_servers(hostgroup_id,hostname,port) VALUES (1,'10.9.160.248',3306);

proxysql>INSERTINTO mysql_servers(hostgroup_id,hostname,port) VALUES (1,'10.9.150.86',3306);

proxysql>INSERTINTO mysql_servers(hostgroup_id,hostname,port) VALUES (1,'10.9.117.107',3306);

注意到這時的hostgroup都爲1,這沒什麼問題

即使生效

LOAD MYSQL SERVERS TO RUNTIME;

 
配置和註冊監控賬戶

UPDATE global_variablesSET variable_value='monitor'WHERE variable_name='mysql-monitor_username';

UPDATE global_variables SET variable_value='monitor'WHERE variable_name='mysql-monitor_password';

這裏填的賬戶和密碼均爲monitor的信息就是步驟1中在後端服務器創建的監控賬戶

即使生效,並持久化到磁盤

LOAD MYSQL VARIABLES TO RUNTIME;
SAVE MYSQL VARIABLES TO DISK;
查看監控是否生效
proxysql>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 |
+--------------+------+------------------+-------------------------+---------------+
| 10.9.160.248 | 3306 | 1497001266520778 | 688                     | NULL          |
| 10.9.150.86  | 3306 | 1497001266510692 | 541                     | NULL          |
| 10.9.117.107 | 3306 | 1497001266500632 | 718                     | NULL          |
| 10.9.160.248 | 3306 | 1497001206520719 | 652                     | NULL          |
| 10.9.150.86  | 3306 | 1497001206510580 | 618                     | NULL          |
| 10.9.117.107 | 3306 | 1497001206500519 | 744                     | NULL          |
| 10.9.160.248 | 3306 | 1497001146520616 | 699                     | NULL          |
| 10.9.150.86  | 3306 | 1497001146510561 | 557                     | NULL          |
| 10.9.117.107 | 3306 | 1497001146500487 | 759                     | NULL          |
| 10.9.160.248 | 3306 | 1497001086520458 | 595                     | NULL          |
+--------------+------+------------------+-------------------------+---------------+
10 rows in set (0.00 sec)
proxysql>SELECT * FROM monitor.mysql_server_ping_log ORDER BY time_start_us DESC LIMIT 10;
+--------------+------+------------------+----------------------+------------+
| hostname     | port | time_start_us    | ping_success_time_us | ping_error |
+--------------+------+------------------+----------------------+------------+
| 10.9.160.248 | 3306 | 1497001317166006 | 181                  | NULL       |
| 10.9.150.86  | 3306 | 1497001317164253 | 153                  | NULL       |
| 10.9.117.107 | 3306 | 1497001317162511 | 262                  | NULL       |
| 10.9.160.248 | 3306 | 1497001307165766 | 218                  | NULL       |
| 10.9.150.86  | 3306 | 1497001307163997 | 137                  | NULL       |
| 10.9.117.107 | 3306 | 1497001307162247 | 289                  | NULL       |
| 10.9.160.248 | 3306 | 1497001297165761 | 213                  | NULL       |
| 10.9.150.86  | 3306 | 1497001297163999 | 175                  | NULL       |
| 10.9.117.107 | 3306 | 1497001297162241 | 280                  | NULL       |
| 10.9.160.248 | 3306 | 1497001287165645 | 183                  | NULL       |
+--------------+------+------------------+----------------------+------------+
10 rows in set (0.00 sec)
 

 

配置主從信息

表示該複製組,1爲寫入組的編號,2爲讀取組的編號
INSERT INTO mysql_replication_hostgroups VALUES (1,2,’ one-master-2-slave’);
即時生效
LOAD MYSQL SERVERS TO RUNTIME;    
當生效後,proxysql會去檢測後端的數據節點
假設該節點read_only1,則會將該server移入group 2
假設該節點read_only0,則會將該server移入group 1
這時再查mysql_servers表,就會發現節點的hostgroup_id根據read_only的情況自動變化了
proxysql>select hostgroup_id,hostname from mysql_servers;
+--------------+--------------+
| hostgroup_id | hostname     |
+--------------+--------------+
| 1            | 10.9.160.248 |
| 2            | 10.9.117.107 |
| 2            | 10.9.150.86  |
+--------------+--------------+
3 rows in set (0.00 sec)
確認無誤後  持久化到磁盤
SAVE MYSQL SERVERS TO DISK;
 

 

配置和註冊業務賬戶

插入步驟1中生成的業務賬戶
INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('msandbox','msandbox',1);
proxysql>select * from mysql_users\G
*************************** 1. row ***************************
              username: msandbox
              password: msandbox
                active: 1
               use_ssl: 0
     default_hostgroup: 1
        default_schema: NULL
         schema_locked: 0
transaction_persistent: 0
          fast_forward: 0
               backend: 1
              frontend: 1
       max_connections: 10000
1 row in set (0.00 sec)
proxysql>update mysql_users set transaction_persistent=1 where username='msandbox';
Query OK, 1 row affected (0.00 sec)
即時生效,持久化
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
 
 
說明幾個比較重要的列名含義
Active:表示該用戶是否生效
default_hostgroup :表示如果沒有配置其他路由規則,那麼默認走的就是該值指定的hostgroup
max_connections:該用戶能創建的最大連接數
transaction_persistent :如果爲1,則一個完整的SQL只可能路由到一個節點;這點非常重要,主要解決這種情況:一個事務有混合的讀操作和寫操作組成,事務未提交前,如果事務中的讀操作和寫操作路由到不同節點,那麼讀取到的結果必然是髒數據。所以一般情況下,該值應該設置爲1,尤其是業務中使用到事務機制的情況(默認爲0
PS:該值設爲1後,sysbench不好測試讀寫分離的情況,因爲sysbench中的oltp腳本中的SQL都是包含在一個個事務中的,所以測試階段可以將其值改爲0
frontend backend列目前的版本必須爲1,因爲目前的proxy和底層的節點共用一套賬戶認證體系,後續可能會單獨分離出來,所以增加了這兩個字段。
 
這時驗證下賬戶登陸,確定登陸上去的就是預想中的主庫
[root@10-9-192-94 ~]# mysql -u msandbox -pmsandbox -h 127.0.0.1 -P6033 -e "show slave hosts"
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID                           |
+-----------+------+------+-----------+--------------------------------------+
| 168392043 |      | 3306 | 168403192 | baaf5e8b-4cbe-11e7-8ca2-e8611f12fd90 |
| 168400470 |      | 3306 | 168403192 | aed780a0-4cbe-11e7-8ca2-6c92bf15bed0 |
 

配置讀寫分離策略

1 除了select ..for update以爲的select都路由到從庫

2 其他所有操作都路由到主庫

proxysql>showcreate table mysql_query_rules\G

***************************1. row ***************************

       table: mysql_query_rules

Create Table:CREATE TABLE mysql_query_rules (

    rule_id INTEGER PRIMARY KEY AUTOINCREMENTNOT NULL,

    active INT CHECK (active IN (0,1)) NOT NULLDEFAULT 0,

    username VARCHAR,

    schemaname VARCHAR,

    flagIN INT NOT NULL DEFAULT 0,

    client_addr VARCHAR,

    proxy_addr VARCHAR,

    proxy_port INT,

    digest VARCHAR,

    match_digest VARCHAR,

    match_pattern VARCHAR,

    negate_match_pattern INT CHECK(negate_match_pattern IN (0,1)) NOT NULL DEFAULT 0,

    flagOUT INT,

    replace_pattern VARCHAR,

    destination_hostgroup INT DEFAULT NULL,

    cache_ttl INT CHECK(cache_ttl > 0),

    reconnect INT CHECK (reconnect IN (0,1))DEFAULT NULL,

    timeout INT UNSIGNED,

    retries INT CHECK (retries>=0 ANDretries <=1000),

    delay INT UNSIGNED,

    mirror_flagOUT INT UNSIGNED,

    mirror_hostgroup INT UNSIGNED,

    error_msg VARCHAR,

    log INT CHECK (log IN (0,1)),

    apply INT CHECK(apply IN (0,1)) NOT NULLDEFAULT 0,

    comment VARCHAR)

1 row in set(0.00 sec)

Active:是否啓用這個路由規則

Username:如果不爲空,該規則匹配該用戶

schemaname :如果不爲空,該規則只匹配該庫名稱

 

destination_hostgroup:該路由規則發往哪個組

apply:1表示該正則匹配後,將不再接受其他匹配,直接轉發

match_digest:描述規則的正則表達式,其中1.4版本以後,正則表達式支持PCRE和RE2兩種,默認使用pcre,即perl語言支持的正則表達式

cache_ttl:用戶查詢緩存的時間閾值,單位爲毫秒

更多字段說明,參考官方wiki文檔

https://github.com/sysown/proxysql/wiki/MySQL-Query-Rules

通過查看該表的表結構,不難看出所有的路由規則是用戶完全自定義的,也就是說不僅僅可以實現讀寫分離,任何SQL類型都可以自定義發送到指定的數據節點執行,比如在實現大部分讀寫分離的同時,一些對實時性要求很高的SQL,可以定義成發送到master節點運行;

Insert into mysql_query_rules(rule_id,active,username,match_digest, destination_hostgroup,apply) values(10,1,’ msandbox’,’ ^SELECT.*FORUPDATE$’,1,1);

Insert into mysql_query_rules(rule_id,active,username,match_digest, destination_hostgroup,apply) values(11,1,’ msandbox’,’ ^SELECT’,2,1);

剛纔通過mysql_users表的配置和解釋可知,路由規則以外的SQL都發往mysql_users表中的default_hostgroup字段,即數值1,該組爲master節點;

即時生效並持久化
load mysql query rules to runtime;
save mysql query rules todisk;

 

讀寫分離測試

清空歷史查詢記錄

proxysql>select* from stats.stats_mysql_query_digest_reset limit 1;

通過查詢stats_mysql_query_digest_reset的效果是這樣的:返回stats_mysql_query_digest表的查詢結果,並且執行truncate table stats_mysql_query_digest清空stats_mysql_query_digest表

proxysql>select* from stats.stats_mysql_query_digest;

Empty set (0.00sec)

修改transaction_persistent爲0,使得sysbench適用該場景

update mysql_users set transaction_persistent=0 where username='msandbox';
LOAD MYSQL USERS TO RUNTIME;

 

sysbench壓測proxy

sysbench--report-interval=1 --num-threads=4 --max-time=2000 --test=sysbench/tests/db/oltp.lua--mysql-user='msandbox' --mysql-password='msandbox' --oltp-table-size=10000--mysql-host=127.0.0.1 --mysql-port=6033 --mysql-db=proxytest  --max-requests=100000000 prepare

sysbench--report-interval=1 --num-threads=4 --max-time=2000 --test=sysbench/tests/db/oltp.lua--mysql-user='msandbox' --mysql-password='msandbox' --oltp-table-size=10000--mysql-host=127.0.0.1 --mysql-port=6033 --mysql-db=proxytest  --max-requests=100000000 run

壓測過程中觀察讀寫分離情況


可以看到查詢都是發往group 2,寫操作都是發往group 1,即實現了讀寫分離

另外可以分別登陸三個數據節點show  processlist確定proxysql真實實現了讀寫分離;

關於select ..for update和事務的路由測試,可以手工寫幾條特定的SQL測試,這裏忽略;

測試proxysql的查詢緩存

Proxysql的查詢緩存和mysql的查詢緩存有點類似,但不是一回事;proxysql的查詢緩存指的是:如果在指定時間大小範圍內發送的SQL一摸一樣,那麼直接返回結果集,而返回的結果集可能並不是準確的查詢結果,所以需要設置合適的時間範圍,既能提升性能,又得滿足業務需求,即查詢結果足夠的“新”。這個特性我想可以用於這個方便:針對一些查詢頻率很高但結果並不需要太精確的業務,可以單獨給這些SQL配置查詢緩存

proxysql>update mysql_query_rules setcache_ttl=2000 where rule_id=11\G

Query OK, 1 row affected (0.00 sec)

proxysql>LOAD MYSQL QUERY RULES TO RUNTIME;

Query OK, 0 rows affected (0.00 sec)         

sysbench --report-interval=1--num-threads=4  --max-time=2000--test=sysbench/tests/db/oltp.lua --mysql-user='msandbox'--mysql-password='msandbox' --oltp-table-size=10000 --mysql-host=127.0.0.1--mysql-port=6033 --mysql-db=proxytest --max-requests=100000000 run



可以看到host部分爲-1,表示這些查詢是使用了proxy查詢緩存的,耗時爲0,這裏的0不可能是真的沒有耗時,只是不好統計,顯示上直接顯示成0

測試查詢重寫

範例   將帶distinct的SQL去掉排序      

9.1 寫入下面這條改寫規則,注意規則中大小寫是敏感的

proxysql>select * frommysql_query_rules\G

*************************** 1. row***************************

              rule_id: 31

               active: 1 

            username: msandbox

          schemaname: NULL

               flagIN: 0

         client_addr: NULL

          proxy_addr: NULL

          proxy_port: NULL

               digest: NULL

        match_digest: NULL

        match_pattern: DISTINCT(.*)ORDER BY c

 negate_match_pattern: 0

              flagOUT: NULL

     replace_pattern: DISTINCT\1

destination_hostgroup: NULL

           cache_ttl: NULL

           reconnect: NULL

              timeout: NULL

              retries: NULL

                delay: NULL

      mirror_flagOUT: NULL

    mirror_hostgroup: NULL

           error_msg: NULL

                  log: NULL

                apply: 1

              comment: NULL

1 row in set (0.00 sec)

9.2 執行下面這個SQL


可以看到解析計劃中沒有using filesort,SQL已經被改寫了

9.3 執行一把SQL內容,查看規則命中情況和執行列表確認

proxysql>select * fromstats_mysql_query_rules ;

+---------+------+

| rule_id | hits |

+---------+------+

| 31     | 1    |

+---------+------+

1 row in set (0.00 sec)

proxysql>select hostgroup,digest_textfrom stats.stats_mysql_query_digest;

+-----------+--------------------------------------------------------------------+

| hostgroup | digest_text                                                       |

+-----------+--------------------------------------------------------------------+

| 1        | SELECT DISTINCT c FROM sbtest1 WHERE id BETWEEN ? and ? order by c |

+-----------+--------------------------------------------------------------------+

1 row in set (0.00 sec)

 

 

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章