介绍
当数据库压力变大,在繁忙操作的时候数据库的性能会越来越低,为了分担数据库的读负载可以采用主从复制,读写分离的方式来解决.随着数据的增长,单一的数据库并无法负担写的负载,可以通过分库分表来解决.
在数据库中并不是所有的表都会频繁的写入数据,也就是不会所有的表都进行分区.对于不用分片的表可以在每个分片中都存储一份相同的数据,前提是该表的数据量不大,但是一致性并不好维护需要定期检查.或者将不用分区的表存储在其他节点进行统一.但是查询效率会降低,如过要进行关联查询就需要查询两次再进行合并.
数据库水平拆分,也就是数据库分片操作.需要注意的是数据库的分片并不是很容易实现而且难以维护,在数据库没有并发和负载并没有达到限制时不建议使用数据库分.
分区健
分区健的选择决定了数据库分区后的性能,尽量减少跨分区的查询
,例如新闻表(新闻id,记者id)如果用新闻id作为分区键,那么在查询某一记者下的所有新闻就可能会垮很多的分区查询,性能会比没分区之前还要低.如按照记者id进行分区,在查询某一记者下的所有新闻都会在一个分区上进行.所以分区建的选择也是至关重要的.
分区键使用hash方式进行分区使各个分片中的数据尽可能的平均.
演示说明
服务器功能说明
服务器 | 功能 | 说明 |
---|---|---|
192.168.128.136 | oneproxy | 不启用mysql,oneproxy改成3306,连接oneproxy类似相当于连接mysql |
192.168.128.137 | mysql分表节点1 | 在oneproxy中命名为school1,分区表后缀_0 |
192.168.128.138 | mysql分表节点2 | 在oneproxy中命名为school2,分区表后缀_1 |
数据库说明
数据表 | 功能 | 分区健 |
---|---|---|
school_student | 存储学校学生表,关联班级表 | 班级id |
school_class | 存储学校班级表,关联城市表 | 城市id |
school_city | 存储城市表 | 不分区(两个节点数据一样) |
软件安装
# 如果https不能下载换成http.顺便提醒我一下
wget https://file.qvbilam.xin/MySQL/oneproxy-rhel6-linux64-v5.8.1-ga.tar.gz
# 解压
tar -zxvf oneproxy-rhel6-linux64-v5.8.1-ga.tar.gz
cd /data/package/oneproxy
# vi demo.sh
# 修改ONEPROXY_HOME为当前目录/data/package/oneproxy
chmod +x demo.sh
./demo.sh
# 验证是否成功
ps -ef | grep oneproxy
配置
演示
进入oneproxy管理端
mysql -uadmin -pOneProxy -h127.0.0.1 -P4041
进入查看集群
-- 可通过list;查看所有命令
-- 查看服务器状态都为up
MySQL [(none)]> list backend;
+------+----------------------+-----------+--------+--------+----------+--------+---------+------+------+-------+---------+-------+---------+-------+---------+------+------+---------+
| INDX | ADDRESS | TYPE | STATUS | MARKUP | REQUESTS | DEGREE | GROUP | IS_M | IS_S | MFile | MOffset | DFile | DOffset | RFile | ROffset | IO | SQL | Seconds |
+------+----------------------+-----------+--------+--------+----------+--------+---------+------+------+-------+---------+-------+---------+-------+---------+------+------+---------+
| 1 | 127.0.0.1:3306 | RW/Master | UP | 0 | 0 | 0 | | No | No | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 2 | 192.168.128.137:3306 | RW/Master | UP | 1 | 0 | 0 | school1 | No | No | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
| 3 | 192.168.128.138:3306 | RW/Master | UP | 1 | 0 | 0 | school2 | No | No | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+------+----------------------+-----------+--------+--------+----------+--------+---------+------+------+-------+---------+-------+---------+-------+---------+------+------+---------+
3 rows in set (0.00 sec)
查看用户
-- 查看用户及库权限
MySQL [(none)]> list users;
+---------------+----------------+
| USERNAME | DATABASE |
+---------------+----------------+
| qvbilam_proxy | qvbilam_school |
+---------------+----------------+
1 row in set (0.00 sec)
查看分区表
-- 查看分区表
MySQL [(none)]> list tables;
+----------------+----------+------+--------+------------+----------+----------+
| TABLENAME | KEY | TYPE | METHOD | PARTITIONS | KEYCACHE | TEMPLATE |
+----------------+----------+------+--------+------------+----------+----------+
| school_class | city_id | int | hash | 2 | 0 | NULL |
| school_student | class_id | int | hash | 2 | 0 | NULL |
| school_city | id | int | global | 2 | 0 | NULL |
+----------------+----------+------+--------+------------+----------+----------+
3 rows in set (0.00 sec)
进入oneproxy客户端
mysql -uqvbilam_proxy -pqvbilam -h127.0.0.1 -P3306
进入进入客户端
-- 可以看到连接的不是mysql而是OneProxy-Agent-5.8.1
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 106
Server version: 5.6.27 OneProxy-Agent-5.8.1 (OneXSoft)
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
分片表插入数据测试
MySQL [(none)]> insert into school_class (class_id,city_id,class_name,create_time) values (1,1,'PHP初级班01',now()),(2,1,'PHP初级班02',now());
Query OK, 2 rows affected (0.00 sec)
MySQL [(none)]> insert into school_class (class_id,city_id,class_name,create_time) values (3,1,'PHP中级班01',now()),(4,2,'PHP中级班02',now());
ERROR 1044 (42000): Partitioned tables should choose only one partition for DML queries!
-- 出现报错,原因不同分区的数据不能同时插入,改成逐条插入即可
MySQL [(none)]> insert into school_class (class_id,city_id,class_name,create_time) values (3,1,'PHP中级班01',now());
Query OK, 1 row affected (0.00 sec)
MySQL [(none)]> insert into school_class (class_id,city_id,class_name,create_time) values (4,2,'PHP中级班02',now());
Query OK, 1 row affected (0.00 sec)
全局表插入数据测试
MySQL [(none)]> insert into school_city (id,city_name) values (1,'北京'),(2,'杭州'),(3,'石家庄');
Query OK, 6 rows affected (0.00 sec)
验证
结果如下则表示成功:
- 每个节点分片表数据总数之和等于oneproxy查询总数.
- 根据分片健相同的数据在同一节点上.
- 每个分片几点的全局表数据和oneproxy全局表的数据相同,数量相同.
oneproxy客户端
mysql -uqvbilam_proxy -pqvbilam -h127.0.0.1 -P3306
进入班级分表查询
-- 查询总数
MySQL [(none)]> select count(*) from school_class;
+----------+
| count(*) |
+----------+
| 4 |
+----------+
1 row in set (0.00 sec)
-- 查询所有数据
MySQL [(none)]> select * from school_class order by class_id asc;
+----------+---------+----------------+---------------------+
| class_id | city_id | class_name | create_time |
+----------+---------+----------------+---------------------+
| 1 | 1 | PHP初级班01 | 2020-03-13 16:36:53 |
| 2 | 1 | PHP初级班02 | 2020-03-13 16:36:53 |
| 3 | 1 | PHP中级班01 | 2020-03-13 16:42:54 |
| 4 | 2 | PHP中级班02 | 2020-03-13 16:43:15 |
+----------+---------+----------------+---------------------+
4 rows in set (0.00 sec)
全局城市表查询
-- 查询总数
MySQL [(none)]> select count(*) from school_city;
+----------+
| count(*) |
+----------+
| 3 |
+----------+
1 row in set (0.00 sec)
-- 查询数据
MySQL [(none)]> select * from school_city;
+----+-----------+
| id | city_name |
+----+-----------+
| 1 | 北京 |
| 2 | 杭州 |
| 3 | 石家庄 |
+----+-----------+
3 rows in set (0.00 sec)
分片节点一
班级分表查询
MySQL [(none)]> use qvbilam_school
Database changed
-- 查询总数
MySQL [qvbilam_school]> select count(*) from school_class_0;
+----------+
| count(*) |
+----------+
| 1 |
+----------+
1 row in set (0.00 sec)
-- 查询数据
MySQL [qvbilam_school]> select * from school_class_0;
+----------+---------+----------------+---------------------+
| class_id | city_id | class_name | create_time |
+----------+---------+----------------+---------------------+
| 4 | 2 | PHP中级班02 | 2020-03-13 16:43:15 |
+----------+---------+----------------+---------------------+
1 row in set (0.00 sec)
全局城市表查询
MySQL [qvbilam_school]> select * from school_city;
+----+-----------+
| id | city_name |
+----+-----------+
| 1 | 北京 |
| 2 | 杭州 |
| 3 | 石家庄 |
+----+-----------+
3 rows in set (0.00 sec)
分片节点二
班级分表查询
MySQL [(none)]> use qvbilam_school
Database changed
MySQL [qvbilam_school]> select * from school_class_1;
+----------+---------+----------------+---------------------+
| class_id | city_id | class_name | create_time |
+----------+---------+----------------+---------------------+
| 1 | 1 | PHP初级班01 | 2020-03-13 16:36:53 |
| 2 | 1 | PHP初级班02 | 2020-03-13 16:36:53 |
| 3 | 1 | PHP中级班01 | 2020-03-13 16:42:54 |
+----------+---------+----------------+---------------------+
3 rows in set (0.00 sec)
全局城市表查询
MySQL [qvbilam_school]> select * from school_city;
+----+-----------+
| id | city_name |
+----+-----------+
| 1 | 北京 |
| 2 | 杭州 |
| 3 | 石家庄 |
+----+-----------+
3 rows in set (0.00 sec)
真6