Mycat之数据库分片(时间分片,按月份分片)-yellowcong

取模分片,简单来讲,根据数据库的主键和存储的节点数进行取模操作,然后根据取模的结果,将数据存放到对应的节点中,取模分表,可以将数据均匀的分配到各个库中。实现的步骤:1、创建数据库,2、配置schema.xml文件,3、配置server.xml,4、添加rule.xml。这种方式。 数据库时间分片,有个问题,就比如按照月份分片,我只能分片这一年的数据,如果来年了,我还需要自己手动来创建一个表,然后在做相同的处理。

创建数据库

我创建一个用户表,根据用户加入的时间,进行分片。例如‘2012-02-03’,我想根据入职的月份 02 来分片,装到12个数据库中

1、创建存储过程

添加存储过程来动态创建表,因为12个库和12个表,有点多,所以偷点懒

-- 删除存储过程
DROP PROCEDURE IF EXISTS CREATE_USER_DB;

-- 添加; 的转义
DELIMITER ;;

-- 创建存储过程
CREATE PROCEDURE CREATE_USER_DB(IN dbPre VARCHAR(32) CHARSET utf8,IN tableNm VARCHAR(32) CHARSET utf8)
BEGIN
    -- 声明变量
    DECLARE i INT DEFAULT 0;
    DECLARE dbname VARCHAR(32) DEFAULT '';
    -- 声明 表名称
    DECLARE tblname VARCHAR(32);

    SET i = 1;
        WHILE i <= 12 DO 

            SET dbname = CONCAT(dbPre,i);

            SET tblname = CONCAT(dbname,'.',tableNm);

            -- 创建数据库    
            SET @createDatabasesql = CONCAT('CREATE DATABASE IF NOT EXISTS ',dbname);

            -- 执行动态生成的sql语句
            PREPARE temp FROM @createDatabasesql;
            EXECUTE temp;

            -- 删除表
            SET @delTabl = CONCAT(' DROP TABLE IF EXISTS ',tblname);

            -- 执行动态生成的sql语句
            PREPARE temp FROM @delTabl;
            EXECUTE temp;

            -- 创建表
            SET @createTbsql = CONCAT('create table ',tblname,'(addData datetime,dbname varchar(32) ,username varchar(32) ,age int(3))');

            -- 执行动态生成的sql语句
            PREPARE temp FROM @createTbsql;

            EXECUTE temp;

            -- 增加角标
            SET i = i + 1; 
    END WHILE;
END;
;;
DELIMITER ;

Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第1张图片

调用存储过程

call CREATE_USER_DB('mycat_demo','user');

Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第2张图片

查看建立好的表结构
Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第3张图片

配置mycat

1、配置schema.xml

vim ./conf/schema.xml

#添加表
#通过这种$的方法,解决了有很多数据库的情况
#jdbc_node$1-3 ,表示的是jdbc_node、jdbc_node、jdbc_node3
"user" dataNode="jdbc_node$1-3" rule="sharding-by-month-user"/>

完整配置



<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="yellowcong" checkSQLschema="true" sqlMaxLimit="1000">             

                 <table name="user" dataNode="jdbc_node$1-12" rule="sharding-by-month-user"/>
        schema>

        <dataNode name="jdbc_node1" dataHost="localhost" database="mycat_demo1" />
        <dataNode name="jdbc_node2" dataHost="localhost" database="mycat_demo2" />
        <dataNode name="jdbc_node3" dataHost="localhost" database="mycat_demo3" />
        <dataNode name="jdbc_node4" dataHost="localhost" database="mycat_demo4" />
        <dataNode name="jdbc_node5" dataHost="localhost" database="mycat_demo5" />
        <dataNode name="jdbc_node6" dataHost="localhost" database="mycat_demo6" />
        <dataNode name="jdbc_node7" dataHost="localhost" database="mycat_demo7" />
        <dataNode name="jdbc_node8" dataHost="localhost" database="mycat_demo8" />
        <dataNode name="jdbc_node9" dataHost="localhost" database="mycat_demo9" />
        <dataNode name="jdbc_node10" dataHost="localhost" database="mycat_demo10" />
        <dataNode name="jdbc_node11" dataHost="localhost" database="mycat_demo11" />
        <dataNode name="jdbc_node12" dataHost="localhost" database="mycat_demo12" />


        <dataHost name="localhost" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()heartbeat>

                <writeHost host="hostM1" url="127.0.0.1:3306" user="root" password="root" />

        dataHost>

mycat:schema>

2、配置server.xml



<mycat:server xmlns:mycat="http://io.mycat/">
        <system>
        <property name="useSqlStat">0property>  
        <property name="useGlobleTableCheck">0property>  

                <property name="sequnceHandlerType">2property>

                
                <property name="processorBufferPoolType">0property>           
                
                <property name="handleDistributedTransactions">0property>

                        
                <property name="useOffHeapForMerge">1property>

                
                <property name="memoryPageSize">1mproperty>

                
                <property name="spillsFileBufferSize">1kproperty>

                <property name="useStreamOutput">0property>

                
                <property name="systemReserveMemorySize">384mproperty>


                
                <property name="useZKSwitch">trueproperty>


        system>

        <user name="root">
                <property name="password">rootproperty>
                <property name="schemas">yellowcongproperty>

        user>

        <user name="user">
                <property name="password">userproperty>
                <property name="schemas">yellowcongproperty>
                <property name="readOnly">trueproperty>
        user>

mycat:server>

3、配置rule.xml

通过学生的学号(code)字段,进行分片操作。

vim ./conf/rule.xml

#添加rule ,
#设置通过addData这个字段进行分片
<tableRule name="sharding-by-month-user">
         <rule>
                <columns>addDatacolumns>
                <algorithm>partbymonth-useralgorithm>
        rule>
tableRule>

#sBeginDate  表示开始的月份,只能搞2015年的月分片,如果是16年的就会报错
<function name="partbymonth-user"
        class="io.mycat.route.function.PartitionByMonth">
        <property name="dateFormat">yyyy-MM-ddproperty>
        <property name="sBeginDate">2015-01-01property>
function>

这个需要注意的点: tableRule和function节点不能混着放,不然解析不了,郁闷啊,这都不可以,菊花疼。

Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第4张图片

说明:起始日期是用来计算数据所在的分片位置,例如2015年1月的message就会找到第1个分片,即dn1,2015年12月的message就会找到第12个分片,即dn12,但是如果出现了2016年1月的message,mycat就会去找第13个分片,但是配置文件中又没有对应的配置,那么就会抛出无法找到分片的错误。

测试插入数据

插入数据的时候,必须指定列名。mycat不支持直接插入不带列明的数据。

#连接mycat 
mysql -h 127.0.0.1 -P 8066 -u root -proot

#使用yellowcong 数据库
use yellowcong 

#插入数据
insert into user (addData,dbname,username,age) values ('2015-01-01',database(),'yellowcong',12);

insert into user (addData,dbname,username,age) values ('2015-02-01',database(),'yellowcong',12);

insert into user (addData,dbname,username,age) values ('2015-03-01',database(),'yellowcong',12);

insert into user (addData,dbname,username,age) values ('2015-04-01',database(),'yellowcong',12);

insert into user (addData,dbname,username,age) values ('2015-05-01',database(),'yellowcong',12);

insert into user (addData,dbname,username,age) values ('2015-06-01',database(),'yellowcong',12);

大家可以发现,每一个月份,对应这一个节点,1月对应着节点1,2月,对应节点2,依次类推。

Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第5张图片

分析sql

看分析结果可以看到,直接就跑到了第7个节点了。

explain insert into user (addData,dbname,username,age) values ('2015-07-01',database(),'yellowcong',12);

Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第6张图片

小知识

mysql中数据字符串的连接

-- 文字和字符串相连接
select concat('doub',121);

-- 字符串和字符串相连接
select concat('doub','xxx');

Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第7张图片

存储过程或函数 多行的问题

多行的时候,需要使用分号结尾,然而分号;在数据库表示这段语句的结束,我们可以使用DELIMITER 这个字段,来解决这个问题,最后运行DELIMITER ;,表示分行结束。存储过程中,不能用tabl制表符,不然就会报Display all 778 possibilities? (y or n)错误

创建表

-- 添加一张测试表
create table user3(dbname varchar(32),username varchar(32),province varchar(16),age int(3));

创建存储过程

-- 删除存储过程
DROP PROCEDURE IF EXISTS INSERT_USER;
-- 这个 DELIMITER 可以让 我们在命令行中,直接使用;
DELIMITER ;;
-- 创建存储过程
create procedure INSERT_USER()

BEGIN
    -- 声明变量
    declare i int default 0;
    declare dbname varchar(20) default '';

    set i = 0;
        while i < 12 do 
            set dbname = concat('doubi',i);
            insert into user values (database(),dbname,'xx',12);

            set i = i + 1; 
    end while;
END ;
;;
DELIMITER ;

大家可以看下面的效果
Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第8张图片

调用存储过程

call  INSERT_USER();

Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第9张图片

问题集合

Display all 778 possibilities? (y or n)

导致这个问题的是,我添加存储过程的时候,有空格的存在,导致了这个问题。
Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第10张图片

Unknown system variable ‘i’

导致这个问题的原因是,没有声明变量i 是啥玩意。需要在设定存储过程的时候,添加变量
Mycat之数据库分片(时间分片,按月份分片)-yellowcong_第11张图片

064 (HY000): Can’t find a valid data node for specified node index :USER -> ADDDATA -> 2012-12-01 00:00:00 -> Index : -25

出现这个问题的原因,多半是分片配置有问题。后来发现问题所在点是,我配置的2015-01-01,而我插入的是 2012年的数据,所以找不到 插入的节点了。
这里写图片描述

你可能感兴趣的:(数据库中间件)