MyCAT枚举分片规则 & childTable
一、MyCAT简介和原理 MYCAT基于阿里开源的Cobar产品而研发,Cobar的稳定性、可靠性、优秀的架构和性能以及众多成熟的使用案例使得MYCAT一开始就拥有一个很好的起点,站在巨人的肩膀上,我们能看到更远。业界优秀的开源项目和创新思路被广泛融入到MYCAT的基因中,使得MYCAT在很多方面都领先于目前其他一些同类的开源项目,甚至超越某些商业产品。MyCAT作为通用代理设计的,后端是以Mysql协议和JDBC的方式连接数据库,可以支持Oracle、DB2、SQL Server 、 mongodb、mysql 这里简单分享一下 Mycat 中的概念及配置的相关基础 ,详细内容可以参考 官方文档 、 Mycat-Server 和 Get Start 数据库中间件 Mycat 其实只是一个数据中间件,或数据库代理 Tip: 所有难搞定的事情都可以通过中间件有效处理,中间件能有效解耦并专注于特定领域问题, LVM、LVS、MQ 都是这个思路(房屋中介,银行也都是这个思路) 所以Mycat没有存储引擎,本身并不存储数据,只是起到了请求分析,拆解,路由与结果聚合的作用,为前端应用提供统一接口,Mycat 与后端的数据库集群有机组合才一起构成一个分布式数据库系统 逻辑库(schema) 类似于LVM中VG的概念(VG由一个或多个PV构成),逻辑库是由一个或多个后端数据库构成的,展示给应用的是一个单一视图,是分布式数据库在逻辑上的一个抽象 逻辑表(table) 逻辑表 与数据库中表相对应的,分布式数据表在逻辑上的一个抽象 分片表 数据表切分后的一个部分(原表的一个真子集) 非分片表 没有分片的表,就是非分片表 ER表 保留了实体关系特性的表,就是ER表 关系型数据库是基于实体关系模型的相关理论来构建的数据库,表与表间有依赖关系,通过表分组(Table Group) 让有依赖的表在同一实例库中从而避免了数据Join不会跨库操作 全局表 全局表是所有分片上都有一份完整拷贝的表 字典表或符合字典特性的表可以被设置为全局表 有以下特点的表,被称作字典表: 变动不频繁 数据量总体变化不大 数据规模不大(很少超过十万条记录) 会与其它表发生关联 这类表可以通过冗余来解决join问题,也就是所有的分片都放上一份数据的拷贝来避免跨分片联查 Tip: 数据冗余和表分组是解决跨分片数据join的好思路,也是数据切分规划的重要规则 二、MyCAT使用测试 1、背景:schem.xml文件父表和子表,以及使用枚举分片规则 #vim ./schema.xml <table name="customer" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile"> <childTable name="orders" primaryKey="ID" joinKey="customer_id" parentKey="id"> <childTable name="order_items" joinKey="order_id" parentKey="id" /> </childTable> <childTable name="customer_addr" primaryKey="ID" joinKey="customer_id" parentKey="id" /> </table> #vim ./rule.xml <tableRule name="sharding-by-intfile"> <rule> <columns>sharding_id</columns> <algorithm>hash-int</algorithm> </rule> </tableRule> <function name="hash-int" class="io.mycat.route.function.PartitionByFileMap"> <property name="mapFile">partition-hash-int.txt</property> </function> #vim partition-hash-int.txt 1=0 2=1 10000=0 10010=1 2、登陆mycat后分别建立对应的表以及插入数据 mycat@TESTDB 08:08:56>show create table customer ; +----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table| Create Table| +----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | customer | CREATE TABLE `customer` ( `SHARDING_ID` int(11) DEFAULT NULL, `id` int(11) NOT NULL, `customer_id` int(11) DEFAULT NULL, `order_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.01 sec) mycat@TESTDB 07:19:09>insert into customer (SHARDING_ID, id ,customer_id,order_id) values (1,1,1,1); Query OK, 1 rows affected (0.05 sec) mycat@TESTDB 07:19:09>insert into customer (SHARDING_ID, id ,customer_id,order_id) values (2,2,2,2); Query OK, 1 rows affected (0.05 sec) mycat@TESTDB 07:54:27>select * from customer ; +-------------+----+-------------+----------+ | SHARDING_ID | id | customer_id | order_id | +-------------+----+-------------+----------+ |2 |2 |2 |2 | |1 |1 |1 |1 | +-------------+----+-------------+----------+ 2 rows in set (0.02 sec) mycat@TESTDB 07:43:10>show create table orders ; +--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table| Create Table| +--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | orders | CREATE TABLE `orders` ( `SHARDING_ID` int(11) DEFAULT NULL, `id` int(11) NOT NULL, `customer_id` int(11) DEFAULT NULL, `customer_name` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +--------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mycat@TESTDB 07:43:57>insert into orders (SHARDING_ID, id , customer_id ,customer_name) values (1,1,1,'qw'); Query OK, 1 row affected (0.24 sec) mycat@TESTDB 07:44:39>insert into orders (SHARDING_ID, id , customer_id ,customer_name) values (1,2,1,'qw'); Query OK, 1 row affected (0.25 sec) mycat@TESTDB 07:44:45>insert into orders (SHARDING_ID, id , customer_id ,customer_name) values (1,3,1,'qw'); Query OK, 1 row affected (0.24 sec) mycat@TESTDB 07:44:45>insert into orders (SHARDING_ID, id , customer_id ,customer_name) values (1,3,3,'qw'); ERROR 1064 (HY000): can't find (root) parent sharding node for sql:insert into orders(SHARDING_ID,id,customer_id,customer_name) values (1,3,3,'qw') mycat@TESTDB 07:45:50>select * from orders ; +-------------+----+-------------+---------------+ | SHARDING_ID | id | customer_id | customer_name | +-------------+----+-------------+---------------+ | 2 |1 | 1 | qw | | 2 |2 | 2 | qw | | 1 |3 | 2 | qw | +-------------+----+-------------+---------------+ 3 rows in set (0.01 sec) mycat@TESTDB 07:53:01>show create table order_items; +-------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table| Create Table| +-------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | order_items | CREATE TABLE `order_items` ( `SHARDING_ID` int(11) DEFAULT NULL, `order_id` int(11) DEFAULT NULL, `order_name` varchar(15) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +-------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.01 sec) mycat@TESTDB 07:53:59>insert into order_items (SHARDING_ID, order_id ,order_name) values (1,1,'qw'); Query OK, 1 row affected (0.05 sec) mycat@TESTDB 07:55:17>insert into order_items (SHARDING_ID, order_id ,order_name) values (1,2,'qw'); Query OK, 1 row affected (0.07 sec) mycat@TESTDB 07:55:30> insert into order_items (SHARDING_ID, order_id ,order_name) values (1,3,'qw'); Query OK, 1 row affected (0.07 sec) mycat@TESTDB 07:55:52>insert into order_items (SHARDING_ID, order_id ,order_name) values (1,4,'qw'); ERROR 1064 (HY000): can't find (root) parent sharding node for sql:insert into order_items(SHARDING_ID,order_id,order_name) values (1,4,'qw') mycat@TESTDB 07:56:21>select * from order_items ; +-------------+----------+------------+ | SHARDING_ID | order_id | order_name | +-------------+----------+------------+ | 1 | 2 | qw | | 1 | 3 | qw | | 1 | 1 | qw | +-------------+----------+------------+ 3 rows in set (0.02 sec) mycat@TESTDB 08:09:45> show create table customer_addr ; +---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table| Create Table| +---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | customer_addr | CREATE TABLE `customer_addr` ( `SHARDING_ID` int(11) DEFAULT NULL, `customer_id` int(11) DEFAULT NULL, `customer_name` varchar(15) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | +---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.01 sec) mycat@TESTDB 07:57:59>insert into customer_addr (SHARDING_ID, customer_id ,customer_name) values (1,1,'qw'); Query OK, 1 row affected (0.26 sec) mycat@TESTDB 07:58:28>insert into customer_addr (SHARDING_ID, customer_id ,customer_name) values (1,2,'qw'); Query OK, 1 row affected (0.05 sec) mycat@TESTDB 07:58:32>insert into customer_addr (SHARDING_ID, customer_id ,customer_name) values (1,3,'qw'); ERROR 1064 (HY000): can't find (root) parent sharding node for sql:insert into customer_addr(SHARDING_ID,customer_id,customer_name) values (1,3,'yue') mycat@TESTDB 08:04:42>select * from customer_addr; +-------------+----+-------------+---------------+ | SHARDING_ID | id | customer_id | customer_name | +-------------+----+-------------+---------------+ |1 |1 |1 | qw | |1 |2 |2 | qw | |1 |3 |2 | qw | +-------------+----+-------------+---------------+ 3 rows in set (0.01 sec) 3、分片表子表配置 childTable标签: name属性 joinKey属性:插入子表的时候会使用这个列的值查找父表存储的数据节点。 parentKey属性:属性指定的值一般为与父表建立关联关系的列名。程序首先获取joinkey的值,再通过parentKey属性指定的列名产生查询语句,通过执行该语句得到父表存储在哪个分片上。从而确定子表存储的位置。 primaryKey属性:同table标签所描述的。 needAddLimit属性:同table标签所描述的。 总结:子表中的 joinKey="***_id" 字段取值取决于父表 primaryKey="ID"中的值,不然会报错(简单说 joinKey是 primaryKey的外键 )