1. proxysql 作用以及架构

1.连接池功能
2. 读写分离(端口号, 用户, 正则, 某个sql)
3. 缓存功能
4. sql改写
5. 监控诊断系统
6. sql防火墙
7. sql审计 && query log (proxysql 2.5)

 

proxy安装:

配置yum源:

cat <<EOF | tee /etc/yum.repos.d/proxysql.repo
[proxysql_repo]
name= ProxySQL YUM repository
baseurl=https://repo.proxysql.com/ProxySQL/proxysql-2.1.x/centos/\$releasever
gpgcheck=1
gpgkey=https://repo.proxysql.com/ProxySQL/repo_pub_key
EOF

 

安装proxysql

yum  -y  install proxysql

配置文件在 : /etc/proxysql.conf

启动/关闭 proxysql
service proxysql  start
service proxysql stop

查看安装版本
proxysql --version

proxysql 需要的监听端口
6032  管理端口
6033  对外服务端口

默认管理用户名密码:   admin/admin

登陆proxysql
mysql -u admin  -padmin  -h 127.0.0.1 -P 6032

启动proxysql
systemctl start proxysql
systemctl enable  proxysql

 

 

proxysql 重要概念:

配置文件:  proxysql中的配置文件可以动态的更改生效

# 提供正在运行的程序应用
1. runtime   

#提供管理者修改
2. memory

#持久化存储, 下次重启后还可以生效
3. disk(sqlite, configle)


[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之前,它们不会被激活,并且未保存到DISK的任何更改在ProxySQL重新启动后将不可用。

 

 

mysql8.0 MGR +  proxysql 部署_MySQL

 

 

# Active current in-memory MySQL User configuration
LOAD MYSQL USERS TO RUNTIME;
 
# Save the current in-memory MySQL User configuration to disk
SAVE MYSQL USERS TO DISK;
 
# Active current in-memory MySQL Server and Replication Hostgroup configuration
LOAD MYSQL SERVERS TO RUNTIME;
 
# Save the current in-memory MySQL Server and Replication Hostgroup configuration to disk
SAVE MYSQL SERVERS TO DISK;

# Active current in-memory MySQL Query Rule configuration
LOAD MYSQL QUERY RULES TO RUNTIME;
 
# Save the current in-memory MySQL Query Rule configuration to disk
SAVE MYSQL QUERY RULES TO DISK;

# Active current in-memory MySQL Variable configuration
LOAD MYSQL VARIABLES TO RUNTIME;
 
# Save the current in-memory MySQL Variable configuration to disk
SAVE MYSQL VARIABLES TO DISK;
 
# Active current in-memory ProxySQL Admin Variable configuration
LOAD ADMIN VARIABLES TO RUNTIME;
 
# Save the current in-memory ProxySQL Admin Variable configuration to disk
SAVE ADMIN VARIABLES TO DISK;

 

 

Hg-> HostGroupp
机器分组:  writer_hg(read_only=0), read_hg(read_only=1), max_writers

Query digest
每一个类型的Query形成一个唯一的Hash Code

Query Rule
通过正则或者 Hash Code 指定查询到不同的Hg

proxysql 用户
链接proxysql 的用户(frontend,backup同时为1)

 

核心表

1. mysql_users
2. mysql_servers
3. mysql_replication_hostgroups
4. mysql_query_rules

 

实现 一主两从的节点读写分离

角色

ip

port

database

数据库状态

user/password

master

172.16.230.53

3306

t1

read_only=0

fengjian/123456

slave1

172.16.230.51

3306

t1

read_only=1

fengjian/123456

slave2

172.16.230.52

3306

t1

read_only=1

fengjian/123456

proxy

172.16.230.54

6032

6033

t1

 

fengjian/123456

 

 

 

 

 

 

 

 

 启动proxysql并且登陆

systemctl start proxysql
systemctl enable proxysql

mysql -u admin -padmin  -h 127.0.0.1 -P 6032

 

 

PXC集群使用的 mysql_galera_hostgroups

MGR集群使用的 mysql_group_replication_hostgroups

配置复制(半同步) mysql_replication_hosgroups

 

注意:  账号必须用 with   mysql_native_password  认证方式.

 

登陆从库 设置数据库为可读状态:

# 登陆到172.16.230.151 mysql从库
[root@mysql1 ~]#   mysql -u root -p 
# 设置为可读
root@localhost 15:49:  [(none)]> set global read_only=1;
root@localhost 15:49:  [(none)]> show global variables like '%read_only%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_read_only      | OFF   |
| read_only             | ON    |


# 登陆到172.16.230.152 mysql从库
[root@mysql1 ~]#   mysql -u root -p 
# 设置为可读
root@localhost 15:49:  [(none)]> set global read_only=1;
root@localhost 15:49:  [(none)]> show global variables like '%read_only%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_read_only      | OFF   |
| read_only             | ON    |

 

创建monitor用户名, 用于监控

admin@localhost 15:18:  [(none)]> select * from global_variables;
| mysql-monitor_username                                       | monitor                     |
| mysql-monitor_password                                       | monitor                     |


create user 'monitor'@'%' identified with mysql_native_password by 'monitor';
grant replication client on *.* to 'monitor'@'%';

 

1. 创建分组

admin@localhost 16:25:  [(none)]> insert into mysql_replication_hostgroups(writer_hostgroup,reader_hostgroup,comment) values(100,101,'senyint3306')

mysql8.0 MGR +  proxysql 部署_sql_02

 

 

 

2. 添加数据库到server中

admin@localhost 16:27:  [(none)]> show create table mysql_servers;

| mysql_servers | CREATE TABLE mysql_servers (
    hostgroup_id INT CHECK (hostgroup_id>=0) NOT NULL DEFAULT 0,
    hostname VARCHAR NOT NULL,
    port INT CHECK (port >= 0 AND port <= 65535) NOT NULL DEFAULT 3306,
    gtid_port INT CHECK ((gtid_port <> port OR gtid_port=0) AND gtid_port >= 0 AND gtid_port <= 65535) NOT NULL DEFAULT 0,
    status VARCHAR CHECK (UPPER(status) IN ('ONLINE','SHUNNED','OFFLINE_SOFT', 'OFFLINE_HARD')) NOT NULL DEFAULT 'ONLINE',
    weight INT CHECK (weight >= 0 AND weight <=10000000) NOT NULL DEFAULT 1,
    compression INT CHECK (compression IN(0,1)) NOT NULL DEFAULT 0,
    max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 1000,
    max_replication_lag INT CHECK (max_replication_lag >= 0 AND max_replication_lag <= 126144000) NOT NULL DEFAULT 0,
    use_ssl INT CHECK (use_ssl IN(0,1)) NOT NULL DEFAULT 0,
    max_latency_ms INT UNSIGNED CHECK (max_latency_ms>=0) NOT NULL DEFAULT 0,
    comment VARCHAR NOT NULL DEFAULT '',
    PRIMARY KEY (hostgroup_id, hostname, port) ) |



admin@localhost 16:27:  [(none)]> insert into mysql_servers(hostgroup_id,hostname,port,max_connections) values(100,'172.16.230.53',3306,200);
Query OK, 1 row affected (0.00 sec)

admin@localhost 16:29:  [(none)]> insert into mysql_servers(hostgroup_id,hostname,port,max_connections) values(101,'172.16.230.51',3306,200);
Query OK, 1 row affected (0.00 sec)

admin@localhost 16:29:  [(none)]> insert into mysql_servers(hostgroup_id,hostname,port,max_connections) values(101,'172.16.230.52',3306,200);
Query OK, 1 row affected (0.00 sec)

mysql8.0 MGR +  proxysql 部署_MySQL_03

 

 

 

3. 加载到runtime 并保存

load mysql servers  to runtime;
save mysql servers to  disk;

 

4. 配置账号:

admin@localhost 16:32:  [(none)]> show create table mysql_users;


| mysql_users | CREATE TABLE mysql_users (
    username VARCHAR NOT NULL,
    password VARCHAR,
    active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1,
    use_ssl INT CHECK (use_ssl IN (0,1)) NOT NULL DEFAULT 0,
    default_hostgroup INT NOT NULL DEFAULT 0,
    default_schema VARCHAR,
    schema_locked INT CHECK (schema_locked IN (0,1)) NOT NULL DEFAULT 0,
    transaction_persistent INT CHECK (transaction_persistent IN (0,1)) NOT NULL DEFAULT 1,
    fast_forward INT CHECK (fast_forward IN (0,1)) NOT NULL DEFAULT 0,
    backend INT CHECK (backend IN (0,1)) NOT NULL DEFAULT 1,
    frontend INT CHECK (frontend IN (0,1)) NOT NULL DEFAULT 1,
    max_connections INT CHECK (max_connections >=0) NOT NULL DEFAULT 10000,
    attributes VARCHAR CHECK (JSON_VALID(attributes) OR attributes = '') NOT NULL DEFAULT '',
    comment VARCHAR NOT NULL DEFAULT '',
    PRIMARY KEY (username, backend),
    UNIQUE (username, frontend)) |

admin@localhost 16:40: [(none)]> insert into mysql_users(username,password,default_hostgroup,default_schema,max_connections) values('fengjian','123456',100,'t1',1000)

 

mysql8.0 MGR +  proxysql 部署_MySQL_04

 

 

 

admin@localhost 16:40:  [(none)]> load mysql users to runtime;

admin@localhost 16:40:  [(none)]> save mysql users to disk;

 

查看runtime 是否为online状态

mysql8.0 MGR +  proxysql 部署_sql_05

 

 

设置读写规则

admin@localhost 17:06:  [(none)]> insert into mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply) values(1,1,'^SELECT.*FOR UPDATE$',100,1),(2,1,'SELECT',101,1);

mysql8.0 MGR +  proxysql 部署_sql_06

 

 

保存

load mysql query rules to runtime;

save mysql query rules to disk

 

登陆测试

[root@proxysql ~]# mysql -h 172.16.230.54 -P 6033 -u fengjian -p123456

#select 查询在slave2上, 查询总是查到一台机器上, 退出再登陆后,会切换到另一台机器上.

fengjian@localhost 17:17: [(none)]> select @@hostname;
+------------+
| @@hostname |
+------------+
| mysql2 |
+------------+
1 row in set (0.01 sec)

 

# select for update 写在了master上

fengjian@localhost 17:17: [(none)]> select @@hostname for update;
+------------+
| @@hostname |
+------------+
| mysql3 |
+------------+
1 row in set (0.00 sec)

 

mysql8.0 MGR +  proxysql 部署_sql_07

 

 

mysql8.0 MGR +  proxysql 部署_MySQL_08

 

 

 

https://proxysql.com/documentation/proxysql-read-write-split-howto/

路由规则

 

高级路由规则, 通过使用 stats_mysql_query_digest 查询 执行时间最长的select语句, 

Admin> SELECT digest,SUBSTR(digest_text,0,25),count_star,sum_time FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' ORDER BY sum_time DESC LIMIT 5;
+--------------------+--------------------------+------------+---------------+
| digest             | SUBSTR(digest_text,0,25) | count_star | sum_time      |
+--------------------+--------------------------+------------+---------------+
| 0x037C3E6D996DAFE2 | SELECT a.ip_id as ip_id, | 2030026798 | 1479082636017 |
| 0xB081A85245DEA5B7 | SELECT a.ip_id as ip_id, | 2025902778 | 1206116187539 |
| 0x38BE36BDFFDBE638 | SELECT instance.name as  | 59343662   | 1096236803754 |
| 0xB4233552504E43B8 | SELECT ir.type as type,  | 1362897166 | 488971769571  |
| 0x4A131A16DCFFD6C6 | SELECT i.id as id, i.sta | 934402293  | 475253770301  |
+--------------------+--------------------------+------------+---------------+
5 rows in set (0.01 sec)

 

查询数最多的sql语句

Admin> SELECT digest,SUBSTR(digest_text,0,25),count_star,sum_time FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' ORDER BY count_star DESC LIMIT 5;
+--------------------+--------------------------+------------+---------------+
| digest             | SUBSTR(digest_text,0,25) | count_star | sum_time      |
+--------------------+--------------------------+------------+---------------+
| 0x037C3E6D996DAFE2 | SELECT a.ip_id as ip_id, | 2030040688 | 1479092529369 |
| 0xB081A85245DEA5B7 | SELECT a.ip_id as ip_id, | 2025916528 | 1206123010791 |
| 0x22E0A5C585C53EAD | SELECT id as instanceid, | 1551361254 | 426419508609  |
| 0x3DB4B9FA4B2CB36F | SELECT i.id as instancei | 1465274289 | 415565419867  |
| 0xB4233552504E43B8 | SELECT ir.type as type,  | 1362906755 | 488974931108  |
+--------------------+--------------------------+------------+---------------+
5 rows in set (0.00 sec)

 

路由规则变成

INSERT INTO mysql_query_rules (rule_id,active,digest,destination_hostgroup,apply)
VALUES(1,1,'0x38BE36BDFFDBE638',101,1);

 

Query cache

对查询语句进行cache 缓存, 还是使用 mysql_query_rules表

admin@localhost 10:18:  [(none)]> show create table mysql_query_rules;

mysql8.0 MGR +  proxysql 部署_MySQL_09

 

 

 

mysql8.0 MGR +  proxysql 部署_sql_10

 

 

 

 

设置 cache_ttl 缓存时间

admin@localhost 10:21:  [(none)]> update mysql_query_rules set cache_ttl=10000 where rule_id=2;
Query OK, 1 row affected (0.00 sec)

load mysql query rules to runtime;
save mysql query rules to disk;

查看缓存

admin@localhost 10:33: [(none)]> select hostgroup, digest_text, digest, first_seen, last_seen, count_star from stats_mysql_query_digest order by count_star desc;

 

2. 利用proxysql 实现透明读写分离以及最佳实践

proxysql  firewall 

proxysql 审计

proxysql + MGR 使用

mysql router 与 proxysql 对比

mysql router 提供MGR的高可用, 节点故障自动处理
只能提供基于端口号的读写分离

proxysql:  功能丰富的中间件
更丰富的sql 路由规则,  更丰富的sql控制以及监控分析方法.

 

 

 

1. MGR mysql8.0 集群

mysql8.0 MGR +  proxysql 部署_mysql_11

 

 2. 初始化proxysql(好像不好用)

service proxysql-initial start

 

3.  在 mysql 主上 准备监控脚本

 vim sys8_new.sql

USE sys;
 
DELIMITER $$
 
CREATE FUNCTION my_id() RETURNS TEXT(36) DETERMINISTIC NO SQL RETURN (SELECT @@global.server_uuid as my_id);$$
 
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 NOT IN ('ONLINE', 'RECOVERING')) >=
    ((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 member_id=my_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,
Count_Transactions_Remote_In_Applier_Queue as transactions_behind, Count_Transactions_in_queue as 'transactions_to_cert' 
from performance_schema.replication_group_member_stats where member_id=my_id();$$
 
DELIMITER ;

 

查看各个节点状态:

mysql1 主节点, read_only 为NO

mysql8.0 MGR +  proxysql 部署_mysql_12

 

mysql2 只读节点

mysql8.0 MGR +  proxysql 部署_MySQL_13

 

mysql3 只读节点

mysql8.0 MGR +  proxysql 部署_sql_14

 

 

4 . 创建账号: mysql主上创建程序链接账号

create user 'feng'@'%' identified with mysql_native_password by '123456';
grant all on  *.* to 'feng'@'%';

create user 'monitor'@'%' identified with mysql_native_password  by '123456';
grant replication client,select on *.*  to 'monitor'@'%';

grant  select on  sys.* to 'monitor'@'%';

 

5. 登陆proxysql

[root@proxysql ~]# mysql -h 127.0.0.1 -P 6032 -u admin -padmin

 

6. 配置proxysql  mysql_group_replication_hostgroups 建立分组

mysql8.0 MGR +  proxysql 部署_mysql_15

insert into mysql_group_replication_hostgroups(writer_hostgroup,backup_writer_hostgroup,reader_hostgroup,offline_hostgroup,max_writers) 
values(100,200,300,400,1);

注释:
#该组中用于写操作的分组ID, 一般也是mysql_users中指定为用户的默认节点, 且要求read_only=0
writer_hostgroup : 100

#组中如果有多个 read_only=0 的节点, 其他成员放置的节点
backup_writer_hostgroup : 200
# 该组用户只读组
reader_hostgroup: 300
# 该组为离线组
offline_hostgroup: 400

#设置最多几个成员可以writer_hostgroup中
max_writers: 1

#写组成员是否担任读的工作
writer_is_also_reader

#节点事物延迟情况
max_transactions_behind

 

7. 添加用户名密码 使用 proxysql mysql_users

mysql8.0 MGR +  proxysql 部署_MySQL_16

 

admin@localhost 17:43:  [(none)]> insert into mysql_users(username,password,active,default_hostgroup,max_connections) 
values('feng','123456',1,100,1000);

mysql8.0 MGR +  proxysql 部署_sql_17

8.配置后端数据库地址 使用 proxysql mysql_servers

#插入集群的各节点地址,HG=100代表  backup_writer_hostgroup,后期通过自动检测让其自动再分配组。

 

 

mysql8.0 MGR +  proxysql 部署_mysql_18

admin@localhost 17:47:  [(none)]> insert into mysql_servers(hostgroup_id,hostname,port,max_connections) 
values(400,'172.16.230.51',3306,1000),(400,'172.16.230.52',3306,1000),(400,'172.16.230.53',3306,1000);

mysql8.0 MGR +  proxysql 部署_sql_19

 

9. 修改监控用户名

#set mysql-monitor_username='mon';

#load mysql variables to run;
# save mysql variables to disk;

 

10. 保存配置

load  mysql  users to  runtime;
load  mysql  servers to runtime;

save mysql users to disk;
save mysql servers to disk;

 

 11. 配置读写分离

INSERT INTO mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply)
VALUES(101,1,'^SELECT.*FOR UPDATE$',100,1),(102,1,'^SELECT',300,1);

LOAD MYSQL QUERY RULES TO RUNTIME; 
SAVE MYSQL QUERY RULES TO DISK;

mysql8.0 MGR +  proxysql 部署_sql_20

 

12. proxysql上校验:

select * from mysql_server_read_only_log;

select * from mysql_server_connect_log;

  select * from mysql_server_ping_log;

 

13. 检查分组

select * from runtime_mysql_servers;

 

mysql8.0 MGR +  proxysql 部署_mysql_21

 

 14. proxysql测试

mysql -h 172.16.230.54 -P 6033 -u fengjian  -p12345

#查询

mysql8.0 MGR +  proxysql 部署_mysql_22

 

#update

mysql8.0 MGR +  proxysql 部署_sql_23

 

 java  JDBC 链接mysql

jdbc:mysql//172.16.230.54:6033,172.16.230.55:6033,172.16.230.56:6033/fengjian?failOverReadOnly=false

failOverReadOnly  = true   连接第一个节点 write/read
failOverReadOnly  = false   所有节点都是: write/read

 

读写分离

https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-source-replica-replication-connection.html

 

 

 

 

三. proxysql 可以提供的有可用的metric

 

 

 

官方文档:

https://proxysql.com/Documentation/