IP | 主机 | 应用 |
---|---|---|
192.168.161.165 | 读写分离解析主机 | proxysql |
192.168.161.166 | mysql/master | mysql |
192.168.161.162 | mysql/slave | mysql |
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# vim /etc/my.cnf
[mysqld]
log-bin=mysql-bin #开启二进制日志
server-id=1 #设置server-id,主从不能一样
[root@localhost ~]# server mysqld restart 重启mysql
[root@localhost ~]# mysql -uroot -p
Enter password:
mysql> create user 'kong'@'192.168.161.162' identified by '123456'; 创建用户并授权:用户:root密码:123456,ip修改为从的ip
Query OK, 0 rows affected (0.01 sec)
mysql> grant replication slave on *.* to 'kong'@'192.168.161.162'; 分配权限
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW MASTER STATUS; 查看binlog日志位置
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 775 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# vim /etc/my.cnf
[mysqld]
server-id=2
[root@localhost ~]# service mysqld restart
mysql> change master to master_host='192.168.161.166',master_user='kong',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=775; 需要主服务器主机名,登陆凭据,二进制文件的名称和位置
Query OK, 0 rows affected, 2 warnings (0.35 sec)
mysql> start slave;
mysql> SHOW SLAVE STATUS\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.161.166
Master_User: kong
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 775
Relay_Log_File: localhost-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
都是yes即可
[root@localhost ~]# vim /etc/yum.repos.d/proxysql.repo 配置proxysql的yum源
[proxysql_repo]
name=proxysql
baseurl=http://repo.proxysql.com/ProxySQL/proxysql-1.4.x/centos/7
gpgcheck=1
gpgkey=http://repo.proxysql.com/ProxySQL/repo_pub_key
[root@localhost ~]# yum clean all 清理yum源
[root@localhost ~]# yum -y install proxysql
[root@localhost ~]# systemctl start proxysql 启动proxysql
[root@localhost ~]# chkconfig proxysql on proxysql默认只提供了sysv风格的启动脚本,所以想设置开机自启则需借助于chkconfig工具
mysql> grant all on *.* to 'proxysql'@'192.168.161.165' identified by '123456';
Query OK, 0 rows affected, 1 warning (0.05 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
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 |
+-----+---------------+-------------------------------------+
5 rows in set (0.00 sec)
数据库说明:
main 内存配置数据库,表里存放后端db实例、用户验证、路由规则等信息。表名以 runtime开头的表示proxysql当前运行的配置内容,不能通过dml语句修改,只能修改对应的不以 runtime 开头的(在内存)里的表,然后 LOAD 使其生效, SAVE 使其存到硬盘以供下次重启加载
disk 是持久化到硬盘的配置,sqlite数据文件
stats 是proxysql运行抓取的统计信息,包括到后端各命令的执行次数、流量、processlist、查询种类汇总/执行时间等等
monitor 库存储 monitor 模块收集的信息,主要是对后端db的健康/延迟检查
stats_history 统计信息历史库
mysql> show tables from main;
+--------------------------------------------+
| tables |
+--------------------------------------------+
| global_variables | # ProxySQL的基本配置参数,类似与MySQL
| mysql_collations | # 配置对MySQL字符集的支持
| mysql_group_replication_hostgroups | # MGR相关的表,用于实例的读写组自动分配
| mysql_query_rules | # 路由表
| mysql_query_rules_fast_routing | # 主从复制相关的表,用于实例的读写组自动分配
| mysql_replication_hostgroups | # 存储MySQL实例的信息
| mysql_servers | # 存储MySQL用户
| mysql_users | # 存储ProxySQL的信息,用于ProxySQL Cluster同步
| proxysql_servers | # 运行环境的存储校验值
| runtime_checksums_values |
| runtime_global_variables |
| runtime_mysql_group_replication_hostgroups |
| runtime_mysql_query_rules |
| runtime_mysql_query_rules_fast_routing |
| runtime_mysql_replication_hostgroups | # 与上面对应,但是运行环境正在使用的配置
| runtime_mysql_servers |
| runtime_mysql_users |
| runtime_proxysql_servers |
| runtime_scheduler |
| scheduler | # 定时任务表
+--------------------------------------------+
20 rows in set (0.00 sec)
runtime_ 开头的是运行时的配置,这些是不能修改的。要修改 ProxySQL 的配置,需要修改了非 runtime_ 表,修改后必须执行 LOAD … TO RUNTIME 才能加载到 RUNTIME 生效,执行 save … to disk 才能将配置持久化保存到磁盘
下面语句中没有先切换到 main 库也执行成功了,因为 ProxySQL 内部使用的 SQLite3 数据库引擎,和 MySQL 的解析方式是不一样的。即使执行了 USE main 语句也是无任何效果的,但不会报错
mysql> insert into mysql_servers(hostgroup_id,hostname,port,weight,comment) values(1,'192.168.161.166',3306,1,'Write Group');
Query OK, 1 row affected (0.00 sec)
mysql> insert into mysql_servers(hostgroup_id,hostname,port,weight,comment) values(2,'192.168.161.162',3306,1,'Read Group');
Query OK, 1 row affected (0.00 sec)
mysql> mysql> select * from mysql_servers;
+--------------+-----------------+------+--------+--------+-------------+-----------------+-----
| hostgroup_id | hostname | port | status | weight | compression | max_connections | max_
+--------------+-----------------+------+--------+--------+-------------+-----------------+-----
| 1 | 192.168.161.166 | 3306 | ONLINE | 1 | 0 | 1000 | 0
| 2 | 192.168.161.162 | 3306 | ONLINE | 1 | 0 | 1000 | 0
+--------------+-----------------+------+--------+--------+-------------+-----------------+-----
mysql> load mysql servers to runtime;
Query OK, 0 rows affected (0.00 sec)
mysql> save mysql servers to disk;
Query OK, 0 rows affected (0.33 sec)
mysql> insert into mysql_users(username,password,default_hostgroup,transaction_persistent)values('proxysql','123456',1,1);
Query OK, 1 row affected (0.00 sec)
([email protected]:6032) [(none)]> select * from mysql_users \G
*************************** 1. row ***************************
username: proxysql # 后端mysql实例的用户名
password: pwproxysql # 后端mysql实例的密码
active: 1 # active=1表示用户生效,0表示不生效
use_ssl: 0
default_hostgroup: 1 # 用户默认登录到哪个hostgroup_id下的实例
default_schema: NULL # 用户默认登录后端mysql实例时连接的数据库,这个地方为NULL的话,则由全局变量mysql-default_schema决定,默认是information_schema
schema_locked: 0
transaction_persistent: 1 # 如果设置为1,连接上ProxySQL的会话后,如果在一个hostgroup上开启了事务,那么后续的sql都继续维持在这个hostgroup上,不论是否会匹配上其它路由规则,直到事务结束。虽然默认是0
fast_forward: 0 # 忽略查询重写/缓存层,直接把这个用户的请求透传到后端DB。相当于只用它的连接池功能,一般不用,路由规则 .* 就行了
backend: 1
frontend: 1
max_connections: 10000 # 该用户允许的最大连接数
1 row in set (0.00 sec)
mysql> load mysql users to runtime;
Query OK, 0 rows affected (0.00 sec)
mysql> save mysql users to disk;
Query OK, 0 rows affected (0.01 sec)
mysql> GRANT SELECT ON *.* TO 'monitor'@'192.168.161.%' IDENTIFIED BY 'monitor';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> set mysql-monitor_username='monitor';
Query OK, 1 row affected (0.00 sec)
mysql> set mysql-monitor_password='monitor';
Query OK, 1 row affected (0.00 sec)
mysql> load mysql variables to runtime;
Query OK, 0 rows affected (0.00 sec)
mysql> save mysql variables to disk;
Query OK, 97 rows affected (0.00 sec)
需求:
将 select 查询语句全部路由至 hostgroup_id=2 的组(也就是读组)
但是 select * from tb for update 这样的语句是会修改数据的,所以需要单独定义,将它路由至 hostgroup_id=1 的组(也就是写组)
其他没有被规则匹配到的组将会被路由至用户默认的组(mysql_users 表中的 default_hostgroup)
mysql> insert into mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply)values(1,1,'^SELECT.*FOR UPDATE$',1,1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply)values(2,1,'^SELECT',2,1);
Query OK, 1 row affected (0.00 sec)
mysql> select rule_id,active,match_digest,destination_hostgroup,apply from mysql_query_rules;
+---------+--------+----------------------+-----------------------+-------+
| rule_id | active | match_digest | destination_hostgroup | apply |
+---------+--------+----------------------+-----------------------+-------+
| 1 | 1 | ^SELECT.*FOR UPDATE$ | 1 | 1 |
| 2 | 1 | ^SELECT | 2 | 1 |
+---------+--------+----------------------+-----------------------+-------+
2 rows in set (0.00 sec)
mysql> load mysql query rules to runtime;
Query OK, 0 rows affected (0.00 sec)
mysql> load admin variables to runtime;
Query OK, 0 rows affected (0.00 sec)
mysql> save mysql query rules to disk;
Query OK, 0 rows affected (0.00 sec)
mysql> save admin variables to disk;
Query OK, 31 rows affected (0.01 sec)
登录用户是刚才我们在 mysql_user 表中创建的用户,端口为6033
[root@localhost ~]# mysql -uproxysql -p123456 -h127.0.0.1 -P6033
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.01 sec)
mysql> create database aaa;
Query OK, 1 row affected (0.01 sec)
mysql> create database bbb;
Query OK, 1 row affected (0.00 sec)
mysql> select user,host from mysql.user;
+---------------+-----------------+
| user | host |
+---------------+-----------------+
| monitor | 192.168.161.% |
| proxysql | 192.168.161.165 |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+---------------+-----------------+
5 rows in set (0.01 sec)
[root@localhost ~]# mysql -uadmin -padmin -h127.0.0.1 -P6032
mysql> select * from stats_mysql_query_digest;
+-----------+--------------------+----------+--------------------+----------------------------------+------------+------------+------------+----------+----------+----------+
| hostgroup | schemaname | username | digest | digest_text | count_star | first_seen | last_seen | sum_time | min_time | max_time |
+-----------+--------------------+----------+--------------------+----------------------------------+------------+------------+------------+----------+----------+----------+
| 1 | information_schema | proxysql | 0xEFBF7B9071567331 | create database bbb | 1 | 1543198310 | 1543198310 | 940 | 940 | 940 |
| 1 | information_schema | proxysql | 0x5FE63C9D9C52A1E9 | create database aaa | 1 | 1543198307 | 1543198307 | 2203 | 2203 | 2203 |
| 2 | information_schema | proxysql | 0x0F02B330C823D739 | select user,host from mysql.user | 1 | 1543198335 | 1543198335 | 2839 | 2839 | 2839 |
| 1 | information_schema | proxysql | 0x02033E45904D3DF0 | show databases | 1 | 1543198263 | 1543198263 | 3812 | 3812 | 3812 |
| 1 | information_schema | proxysql | 0x226CD90D52A2BA0B | select @@version_comment limit ? | 1 | 1543198242 | 1543198242 | 0 | 0 | 0 |
+-----------+--------------------+----------+--------------------+----------------------------------+------------+------------+------------+----------+----------+----------+
6 rows in set (0.00 sec)
从上面的 hostgroup 和 digest_text 值来看,所有的写操作都被路由至1组,读操作都被路由至2组,其中1组为写组,2组为读组
由此可见,读写分离成功