环境: dble 2.19.03.0
os版本: centos linux release 7.6.1810 (core)
ip: 192.168.20.10/24
mysql版本: mysql-社区版-5.7.26
添加2个账号授权:
create user 'rw'@'%' identified by 'rw123456';
create user 'rd'@'%' identified by 'rd123456';
grant select, insert, update, delete, create,references,create temporary tables,index on *.* to rw@'%' ;
grant select on *.* to 'rd'@'%' ;
连接方式:
读写:
mysql -urw -prw123456 --port 8066 -h 192.168.20.10 testdb
只读:
mysql -urd -prd123456 --port 8066 -h 192.168.20.10 testdb
ddl专用:
mysql -uop -p123456 --port 8066 -h 192.168.20.10 testdb
管理账号:
mysql -uman1 -p654321 --port 9066 -h 192.168.20.10
解压dble:
tar xf dble-2.19.03.tar.gz /usr/local/
cd /usr/local
ln -s dble-2.19.03 dble
cd conf/
vim schema.xml 修改后的如下:
vim rule.xml 修改后的内容如下:
[root@centos7 /usr/local/dble/conf ]# vim autopartition-long_t.txt # 增加一个路由规则文件
vim server.xml 内容如下:
然后, reload 下 dble , 进行测试
mysql -uop -p123456 --port 8066 -h 192.168.20.10 testdb
去创建符合上面的要求的几个表,并写入数据测试:
############################################################################
上面就是几种常用的分区了, 另外还有种 date类型按时间分区的可能在日志表的场景下也常用些。
date类型分区的实验:
先去后端的db上创建物理的库:
修改后的 schema.xml 类似如下:
然后,到 rule.xml中添加规则:
date类型的可用分区的监控(脚本的原理同样适用于其他类型的分区):
简单的做法就是定期执行一个explain的insert插入测试, 如果有error关键字就告警出来
date类型加新的分片的方法:
######################################################################################################
er 表 (互联网场景下用多表join的不多,因此er分片规则不太常用到,但是需要大致的了解):
下面的内容大篇幅参考: https://blog.csdn.net/zhanglei_16/article/details/50779929
1:er分片关系简介
有一类业务,例如订单(order)跟订单明细表(order_detail),明细表会依赖订单单,就是该会存在表的主从关系,
这类似业务的切分可以抽象出合适的切分规则,比如根据用户id切分,其它相关的表都依赖于用户id,再或者根据订单id进行切分,
总之部分业务总会可以抽象出父子关系的表。这类表适用于er分片表,子表的记录与所关联的父表记录存放在同一个数据分片上,
避免数据join跨库操作,以order与order_detail例子为例,schema.xml中定义合适的分片配置,order,order_detail 根据order_id
迕行数据切分,保证相同order_id的数据分到同一个分片上,在进行数据插入操作时,mycat会获取order所在的分片,
然后将order_detail也插入到order所在的分片
2:父表按照主键id分片,字表的分片字段与主表id关联,配置为ER分片
2.1:在schema.xml添加如下配置配置文件修改
<!-- er 分区 -->
<table name="order1" datanode="dn1,dn2,dn3" rule="id-sharding-by-mod3">
<childtable name="order_detail" primarykey="id" joinkey="order_id" parentkey="id" />
</table>
在rule.xml里面设定分片规则:
<tablerule name="id-sharding-by-mod3">
<rule>
<columns>id</columns>
<algorithm>hashmod3</algorithm>
</rule>
</tablerule>
<!-- mod 3 -->
<function name="hashmod3" class="hash">
<property name="partitioncount">3</property>
<property name="partitionlength">1</property>
</function>
然后, reload 下 dble
2.2 先建表, order 和 order_detail 表,有主外键关系
mysql> explain create table order1 (id int not null auto_increment primary key,sn varchar(64),create_time datetime) engine=innodb default charset=utf8;
+-----------+-----------------------------------------------------------------------------------------------------+
| data_node | sql |
| dn1 | create table order1(id int unsigned not null auto_increment primary key,sn varchar(64),create_time datetime) |
| dn2 | create table order1(id int unsigned not null auto_increment primary key,sn varchar(64),create_time datetime) |
| dn3 | create table order1(id int unsigned not null auto_increment primary key,sn varchar(64),create_time datetime) |
3 rows in set (0.02 sec)
mysql> create table order1(id int not null auto_increment primary key,sn varchar(64),create_time datetime) engine=innodb default charset=utf8;
query ok, 0 rows affected (0.35 sec)
mysql> create table order_detail(id int auto_increment primary key, order_id int,ord_status char(1),address varchar(128),create_time datetime,constraint fk_ordid foreign key (order_id) references order1 (id)) engine=innodb default charset=utf8;
query ok, 0 rows affected (0.44 sec)
3.3 录入数据:
mysql> explain insert into order1(id,sn,create_time) values(1,'bj0001',now());
+-----------+----------------------------------------------------------------+
| data_node | sql |
| dn2 | insert into order1(id,sn,create_time) values(1,'bj0001',now()) |
1 row in set (0.03 sec)
录入数据,一组组录入,涉及到外键关系:
第一组北京的订单
mysql> insert into order1(id,sn,create_time) values(1,'bj0001',now());
query ok, 1 row affected (0.05 sec)
mysql> insert into order_detail(id,order_id,ord_status,address,create_time) values (1,1,'1','test data of order1(id=1,bj001) ',now());
第二组上海的订单:
mysql> explain insert into order1(id,sn,create_time) values(3,'shh001',now());
| dn1 | insert into order1(id,sn,create_time) values(3,'shh001',now()) |
1 row in set (0.02 sec)
mysql> insert into order1(id,sn,create_time) values(3,'shh001',now());
query ok, 1 row affected (0.04 sec)
mysql> insert into order_detail(id,order_id,ord_status,address,create_time) values (3,3,'1','test data of order1(id=3,shh001)',now());
query ok, 1 row affected (0.06 sec)
第三组广州的订单:
mysql> explain insert into order1(id,sn,create_time) values(4,'gzh004',now());
| dn2 | insert into order1(id,sn,create_time) values(4,'gzh004',now()) |
1 row in set (0.00 sec)
mysql> insert into order1(id,sn,create_time) values(4,'gzh004',now());
mysql> insert into order_detail(id,order_id,ord_status,address,create_time) values (4,4,'1','test data of order1(id=4,gzh004) ',now());
第四组 武汉的订单,这里故意将order_id设置成4,看看效果,是否随id为4的广州的那组分片:
mysql> explain insert into order1(id,sn,create_time) values(5,'wuhan005',now());
+-----------+------------------------------------------------------------------+
| data_node | sql |
| dn3 | insert into order1(id,sn,create_time) values(5,'wuhan005',now()) |
1 row in set (0.01 sec)
mysql> explain insert into order1(id,sn,create_time) values(6,'wuhan006',now());
query ok, 1 row affected (0.03 sec)
mysql> insert into order_detail(id,order_id,ord_status,address,create_time) values (6,4,'1','test data of order1(id=6,wuhan006) ',now());
通过dble,查看下数据写入的情况:
(testdb) > select * from order1;
+----+--------+---------------------+
| id | sn | create_time |
| 1 | bj0001 | 2019-08-31 23:05:36 |
| 4 | gzh004 | 2019-08-31 23:06:57 |
| 3 | shh001 | 2019-08-31 23:06:43 |
3 rows in set (0.01 sec)
(testdb) > select * from order_detail ;
+----+----------+------------+--------------------------------------+---------------------+
| id | order_id | ord_status | address | create_time |
| 1 | 1 | 1 | test data of order1(id=1,bj001) | 2019-08-31 23:06:17 |
| 4 | 4 | 1 | test data of order1(id=4,gzh004) | 2019-08-31 23:07:01 |
| 6 | 4 | 1 | test data of order1(id=6,wuhan006) | 2019-08-31 23:07:23 |
| 3 | 3 | 1 | test data of order1(id=3,shh001) | 2019-08-31 23:06:47 |
4 rows in set (0.01 sec)
直连后端的db1,看下数据情况 (db2 和 db3 上面的数据查看,使用同样的方法);
((none)) > select * from db1.order1;
((none)) > select * from db1.order_detail;
+----+----------+------------+----------------------------------+---------------------+
| id | order_id | ord_status | address | create_time |
| 3 | 3 | 1 | test data of order1(id=3,shh001) | 2019-08-31 23:06:47 |
2.6 走dble,模拟下业务的查询:
(testdb) > explain select t1.*,t2.* from order1 t1,order_detail t2 where t2.ord_status='1' and t2.id=1 and t1.id=t2.order_id;
+-----------------+---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| data_node | type | sql/ref |
| dn1_0 | base sql | select `t2`.`id`,`t2`.`order_id`,`t2`.`ord_status`,`t2`.`address`,`t2`.`create_time`,`t1`.`id`,`t1`.`sn`,`t1`.`create_time` from `order1` `t1` join `order_detail` `t2` on `t1`.`id` = `t2`.`order_id` where (`t2`.`ord_status` = '1') and (`t2`.`id` = 1) |
| dn2_0 | base sql | select `t2`.`id`,`t2`.`order_id`,`t2`.`ord_status`,`t2`.`address`,`t2`.`create_time`,`t1`.`id`,`t1`.`sn`,`t1`.`create_time` from `order1` `t1` join `order_detail` `t2` on `t1`.`id` = `t2`.`order_id` where (`t2`.`ord_status` = '1') and (`t2`.`id` = 1) |
| dn3_0 | base sql | select `t2`.`id`,`t2`.`order_id`,`t2`.`ord_status`,`t2`.`address`,`t2`.`create_time`,`t1`.`id`,`t1`.`sn`,`t1`.`create_time` from `order1` `t1` join `order_detail` `t2` on `t1`.`id` = `t2`.`order_id` where (`t2`.`ord_status` = '1') and (`t2`.`id` = 1) |
| merge_1 | merge | dn1_0; dn2_0; dn3_0 |
| shuffle_field_1 | shuffle_field | merge_1 |
5 rows in set (0.00 sec)
(testdb) > select
t1.*,
t2.*
from
order1 t1,
order_detail t2
where t2.ord_status = '1'
and t2.id = 1
and t1.id = t2.order_id ;
+----+--------+---------------------+----+----------+------------+-----------------------------------+---------------------+
| id | sn | create_time | id | order_id | ord_status | address | create_time |
| 1 | bj0001 | 2019-08-31 23:05:36 | 1 | 1 | 1 | test data of order1(id=1,bj001) | 2019-08-31 23:06:17 |
2.7 总结:当子表与父表的关联字段正好是父表的分片字段时,子表直接根据父表规则进行分片,在数据录入的时候子表直接放在父表的分片上面,在进行关联查询join的时候,走的是父表的路由。
【重要】其它的总结:
当子表与父表的关联字段不是父表的分片字段时,必须通过查找对应的父表记录来确认子表所在分片,如果找不到则会抛出错误,在join查询的时候,路由走的是所有分片节点!!!!