1,迁移数据

举例说明,比如一个博客数据库数据表如下:
这里水平拆分,垂直拆分,只是做个简单的实验,真正的线上业务要根据情况,数据进行拆分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 
CREATE TABLE category (
    id INT NOT NULL AUTO_INCREMENT,
    user_id INT NOT NULL,
    name VARCHAR(200) NOT NULL,
    PRIMARY KEY (id)
);
--标签
CREATE TABLE tag (
    id INT NOT NULL AUTO_INCREMENT,
    user_id INT NOT NULL,
    name VARCHAR(100) NOT NULL,
    PRIMARY KEY (id)
);
--文章
CREATE TABLE `article` (
  `id` int(11) NOT NULL PRIMARY KEY ,
  `user_id` int(11) NOT NULL,
  `title` varchar(200) NOT NULL,
  `abstract` text,
  `content` text,
  `publish_time` datetime NOT NULL,
  `create_time` datetime NOT NULL,
  `update_time` datetime NOT NULL,
  `category_id` int(11) NOT NULL,
  KEY `category_id` (`category_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--标签
CREATE TABLE article_tags (
    user_id INT NOT NULL,
    article_id INT NOT NULL,
    tag_id INT NOT NULL,
    PRIMARY KEY (user_id,article_id,tag_id)
);
--用户信息
CREATE TABLE user_info (
    id INT NOT NULL AUTO_INCREMENT,
    email VARCHAR(200) NOT NULL,
    name VARCHAR(200) NOT NULL,
    password VARCHAR(100) NOT NULL,
    create_time DATETIME NOT NULL,
    update_time DATETIME NOT NULL,
    last_login_time DATETIME NOT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY (name)
);
--链接
CREATE TABLE link (
    id INT NOT NULL AUTO_INCREMENT,
    user_id INT NOT NULL,
    name VARCHAR(100) NOT NULL,
    url VARCHAR(300) NOT NULL,
    PRIMARY KEY (id),
    KEY (user_id)
 );
 

将所有数据都迁移到mycat中,一共有4个数据库,blog01,blog02,blog_article01,blog_article02。
article,article_tags分别在blog_article01,blog_article02,按照uid进行水平拆分。
user_info表在blog01,link,category,tag在blog02数据库中。

1
2
3
4
5
6
7
CREATE DATABASE blog01 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE DATABASE blog02 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE DATABASE blog_article01 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE DATABASE blog_article02 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
#创建一共mycat数据库,存储mycat相关数据比如sequence
CREATE DATABASE mycat DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
 

2,schema.xml,配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
 
        <schema name="mycat" checkSQLschema="false" sqlMaxLimit="100">
                <table name="MYCAT_SEQUENCE" primaryKey="name" type="global" dataNode="nodeUser" />
        </schema>
 
        <schema name="blog_user" checkSQLschema="false" sqlMaxLimit="100">
                <table name="user_info" primaryKey="id" type="global" dataNode="nodeUser" />
        </schema>
 
        <schema name="blog_category" checkSQLschema="false" sqlMaxLimit="100">
                <table name="category" primaryKey="id" type="global" dataNode="nodeCategory" />
                <table name="tag" primaryKey="id" type="global" dataNode="nodeCategory" />
                <table name="link" primaryKey="id" type="global" dataNode="nodeCategory" />
        </schema>
 
        <schema name="blog_article" checkSQLschema="false" sqlMaxLimit="100">
            <table name="article" primaryKey="user_id" dataNode="nodeArticle01,nodeArticle02" rule="mod-long" />
            <table name="article_tags" primaryKey="id" type="global" dataNode="nodeArticle01,nodeArticle02" />
 
        </schema>
 
        <dataNode name="nodeMycat" dataHost="dataHost01" database="mycat" />
        <dataNode name="nodeUser" dataHost="dataHost01" database="blog01" />
        <dataNode name="nodeCategory" dataHost="dataHost01" database="blog02" />
        <dataNode name="nodeArticle01" dataHost="dataHost01" database="blog_article01" />
        <dataNode name="nodeArticle02" dataHost="dataHost01" database="blog_article02" />
 
        <dataHost name="dataHost01" maxCon="1000" minCon="10" balance="0"
                writeType="0" dbType="mysql" dbDriver="native">
                <heartbeat>select 1</heartbeat>
                <writeHost host="hostM1" url="127.0.0.1:3306" user="root" password="root"/>
        </dataHost>
 
</mycat:schema>

配置4个数据库连接,user_info做垂直拆分(配置type=global)。
blog_article,数据库进行水平拆分,拆分成两个数据库。
当设置成全局表的时候必须保证这个表在所有的数据库中,和配置的dataNode无关。
article规则配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://org.opencloudb/">
    <!--article 分区配置,按照id进行模2.-->
    <tableRule name="mod-long">
        <rule>
            <columns>user_id</columns>
            <algorithm>mod-long</algorithm>
        </rule>
    </tableRule>
 
    <function name="mod-long"
    class="org.opencloudb.route.function.PartitionByMod">
        <property name="count">2</property>
    </function>
 
</mycat:rule>

配置service.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://org.opencloudb/">
        <system>
            <property name="defaultSqlParser">druidparser</property>
        </system>
 
        <user name="mycat">
                <property name="password">mycat</property>
                <property name="schemas">mycat,blog_user,blog_category,blog_article</property>
        </user>
 
</mycat:server>

3,数据库sequence生成

牵扯到分库的时候就一定要由sequence生成,mysql的主键自增就不能使用了。
mycat的文档里面没有找到这部分的配置资料,但是找到了sequence的存储过程。
可以把这个存储过程存储到一个单独的数据库中,然后进行一次查询,再做入库。
存储过程地址:
https://github.com/MyCATApache/Mycat-doc/blob/master/%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97/sequnce-sql.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
DROP TABLE IF EXISTS MYCAT_SEQUENCE; 
CREATE TABLE MYCAT_SEQUENCE (  name VARCHAR(50) NOT NULL,  current_value INT NOT NULL,  increment INT NOT NULL DEFAULT 100, PRIMARY KEY (name) ) ENGINE=InnoDB;
 
DROP FUNCTION IF EXISTS `mycat_seq_currval`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN 
        DECLARE retval VARCHAR(64);
        SET retval="-999999999,null"
        SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR) ) INTO retval   FROM MYCAT_SEQUENCE  WHERE name = seq_name; 
        RETURN retval ;
END
;;
DELIMITER ;
 
DROP FUNCTION IF EXISTS `mycat_seq_nextval`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN 
         UPDATE MYCAT_SEQUENCE 
                 SET current_value = current_value + increment  WHERE name = seq_name; 
         RETURN mycat_seq_currval(seq_name); 
END
;;
DELIMITER ;
 
DROP FUNCTION IF EXISTS `mycat_seq_setval`;
DELIMITER ;;
CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50), value INTEGER) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN 
         UPDATE MYCAT_SEQUENCE 
                   SET current_value = value 
                   WHERE name = seq_name; 
         RETURN mycat_seq_currval(seq_name); 
END
;;
DELIMITER ;
 
--同时增加权限,否则不能执行。
mysql> grant all privileges on *.* to root@"%" identified by ".";
Query OK, 0 rows affected (0.00 sec)
 
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

4,测试mycat数据库

–mycat数据库的ip是192.168.1.16,端口是8066。
mysql -umycat -pmycat -P8066 -h 192.168.1.16

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 
mysql> show databases;
+---------------+
| DATABASE      |
+---------------+
| blog_article  |
| blog_category |
| blog_user     |
| mycat         |
+---------------+
4 rows in set (0.00 sec)
 
mysql> use blog_user;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Database changed
mysql> show tables;
+---------------------+
| Tables in blog_user |
+---------------------+
| user_info           |
+---------------------+
1 row in set (0.00 sec)
 
mysql> insert into user_info(email,`name`,password,create_time,update_time,last_login_time) values('zhangsan@126.com','zhangsan',password('123456'),now(),now(),now());
Query OK, 1 row affected (0.01 sec)
 
mysql> select * from user_info;
+----+------------------+----------+-------------------------------------------+---------------------+---------------------+---------------------+
| id | email            | name     | password                                  | create_time         | update_time         | last_login_time     |
+----+------------------+----------+-------------------------------------------+---------------------+---------------------+---------------------+
|  1 | zhangsan@126.com | zhangsan | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 | 2015-03-26 02:47:38 | 2015-03-26 02:47:38 | 2015-03-26 02:47:38 |
+----+------------------+----------+-------------------------------------------+---------------------+---------------------+---------------------+
1 row in set (0.11 sec)
 
mysql> update user_info set name = 'lisi' where id = 1;
Query OK, 1 row affected (0.08 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mysql> delete from user_info where name = 'lisi';
Query OK, 1 row affected (0.00 sec)
 
mysql> use blog_category;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Database changed
mysql> show tables;
+-------------------------+
| Tables in blog_category |
+-------------------------+
| category                |
| link                    |
| tag                     |
+-------------------------+
3 rows in set (0.00 sec)
 
mysql> insert into tag(id,user_id,name) values(1,1,'java');
Query OK, 1 row affected (0.11 sec)
 
mysql> select * from tag;
+----+---------+------+
| id | user_id | name |
+----+---------+------+
|  1 |       1 | java |
+----+---------+------+
1 row in set (0.11 sec)
 
mysql> update tag set name = 'j2ee' where id = 1;
Query OK, 1 row affected (0.08 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mysql> insert into tag(user_id,name) values(2,'mysql');
Query OK, 1 row affected (0.00 sec)
 
mysql> select * from tag;
+----+---------+-------+
| id | user_id | name  |
+----+---------+-------+
|  1 |       1 | j2ee  |
|  2 |       2 | mysql |
+----+---------+-------+
2 rows in set (0.00 sec)
 
mysql> delete from tag where id = 1;
Query OK, 1 row affected (0.00 sec)
 
 
 
mysql> use blog_article;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
mysql> insert into article(id,user_id,title,publish_time,create_time,update_time,category_id) \
    -> values (1,1,'test1',now(),now(),now(),1),(2,1,'test2',now(),now(),now(),2),\
    -> (3,1,'test3',now(),now(),now(),3),(4,2,'test4',now(),now(),now(),3);
Query OK, 4 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
 
 
mysql> select * from article;
+----+---------+-------+----------+---------+---------------------+---------------------+---------------------+-------------+
| id | user_id | title | abstract | content | publish_time        | create_time         | update_time         | category_id |
+----+---------+-------+----------+---------+---------------------+---------------------+---------------------+-------------+
|  4 |       2 | test4 | NULL     | NULL    | 2015-03-26 03:30:55 | 2015-03-26 03:30:55 | 2015-03-26 03:30:55 |           3 |
|  1 |       1 | test1 | NULL     | NULL    | 2015-03-26 03:30:55 | 2015-03-26 03:30:55 | 2015-03-26 03:30:55 |           1 |
|  2 |       1 | test2 | NULL     | NULL    | 2015-03-26 03:30:55 | 2015-03-26 03:30:55 | 2015-03-26 03:30:55 |           2 |
|  3 |       1 | test3 | NULL     | NULL    | 2015-03-26 03:30:55 | 2015-03-26 03:30:55 | 2015-03-26 03:30:55 |           3 |
+----+---------+-------+----------+---------+---------------------+---------------------+---------------------+-------------+
4 rows in set (0.00 sec)
 
mysql> update article set title = "new title" where user_id = 1 and id =2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 

测试sequence生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
mysql> INSERT INTO MYCAT_SEQUENCE VALUES ('article_seq', 1, 1);
1 row in set (0.06 sec)
 
mysql> SELECT MYCAT_SEQ_CURRVAL('article_seq');
+----------------------------------+
| MYCAT_SEQ_CURRVAL('article_seq') |
+----------------------------------+
| 1,1                              |
+----------------------------------+
1 row in set (0.01 sec)
 
mysql> SELECT MYCAT_SEQ_SETVAL('article_seq', 2);
+------------------------------------+
| MYCAT_SEQ_SETVAL('article_seq', 2) |
+------------------------------------+
| 2,1                                |
+------------------------------------+
1 row in set (0.01 sec)
 
mysql> SELECT MYCAT_SEQ_CURRVAL('article_seq');
+----------------------------------+
| MYCAT_SEQ_CURRVAL('article_seq') |
+----------------------------------+
| 2,1                              |
+----------------------------------+
1 row in set (0.01 sec)
 
mysql> SELECT MYCAT_SEQ_NEXTVAL('article_seq');
+----------------------------------+
| MYCAT_SEQ_NEXTVAL('article_seq') |
+----------------------------------+
| 3,1                              |
+----------------------------------+
1 row in set (0.01 sec)
 
mysql> SELECT MYCAT_SEQ_NEXTVAL('article_seq');
+----------------------------------+
| MYCAT_SEQ_NEXTVAL('article_seq') |
+----------------------------------+
| 4,1                              |
+----------------------------------+
1 row in set (0.02 sec)

总结

mycat提供了数据库垂直拆分和水平拆分的方案,对于数据迁移可以按照id,user_id进行拆分。
也可以将数据分库存储,不拆分,但必须放到不同的库中(和水平拆分的分开)。
同时,如果进行拆分,则需要修改主键生成方式,目前看到mycat中提供一个sequence的存储过程,可以直接使用。

mycat表拆分操作教程的更多相关文章

  1. Mycat读写分离、主从切换、分库分表的操作记录

    系统开发中,数据库是非常重要的一个点.除了程序的本身的优化,如:SQL语句优化.代码优化,数据库的处理本身优化也是非常重要的.主从.热备.分表分库等都是系统发展迟早会遇到的技术问题问题.Mycat是一 ...

  2. MyCat安装与测试教程 超详细!

    MyCat安装与测试教程 超详细! MyCat基础知识 一.什么是MYCAT? 1. 一个彻底开源的,面向企业应用开发的大数据库集群 2. 支持事务.ACID.可以替代MySQL的加强版数据库 3. ...

  3. c# .Net :Excel NPOI导入导出操作教程之读取Excel文件信息及输出

    c# .Net :Excel NPOI导入导出操作教程之读取Excel文件信息及输出 using NPOI.HSSF.UserModel;using NPOI.SS.UserModel;using S ...

  4. WPS 2019 多个sheet表拆分成独立的excel文件

    参考: https://www.cnblogs.com/hackxiyu/p/8945975.html 场景:将多个sheet表拆分成独立的excel文件 一.安装VB工具: 默认情况下:wps -- ...

  5. SqlServer 数据库/数据表 拆分(分布式)【转】

    通过某种特定的条件,将存放在同一个数据库中的数据分散存放到多个数据库上,实现分布存储,通过路由规则路由访问特定的数据库,这样一来每次访问面对的就不是单台服务器了,而是N台服务器,这样就可以降低单台机器 ...

  6. 个人永久性免费-Excel催化剂功能第68波-父子结构表转换之父子关系BOM表拆分篇

    Excel中制造业行业中,有一个非常刚需的需求是对BOM(成品物料清单)的拆解,一般系统导出的BOM表,是经过压缩处理的,由父子表结构的方式存储数据.对某些有能力使用SAP等专业ERP软件的工厂来说, ...

  7. 个人永久性免费-Excel催化剂功能第30波-工作表快捷操作(批量创建、命名、排序、工作表目录)

    日常使用Excel过程中,最多的操作无外乎单元格和工作表的操作,单元格的操作在前面已经有详细的辅助功能提供,此篇提供工作表相关的操作.这两项的操作若能有提速,日常大量的工作叠加起来真是省下不少时间. ...

  8. MySQL数据库 外键,级联, 修改表的操作

    1.外键: 用来建立两张表之间的关系 - 一对多 - 多对多 - 一对一 研究表与表之间的关系: 1.定义一张 员工部门表 id, name, gender, dep_name, dep_desc - ...

  9. MySQL中表的复制以及大型数据表的备份教程

    MySQL中表的复制以及大型数据表的备份教程     这篇文章主要介绍了MySQL中表的复制以及大型数据表的备份教程,其中大表备份是采用添加触发器增量备份的方法,需要的朋友可以参考下 表复制 mysq ...

随机推荐

  1. 利用循环removeChild删除节点只删除一半问题

    <!DOCTYPE html> <html>   <head>     <title>adduser.html</title>        ...

  2. linux netcat命令

    netcat是网络工具中的“瑞士军刀”,它能通过TCP和UDP在网络中读写数据.通过与其他工具结合和重定向,你可以在脚本中以多种方式使用它.使用netcat命令所能完成的事情令人惊讶. netcat所 ...

  3. 关于rewriteRule的一个小问题

    RewriteEngine on # RewriteRule ^test.php$ modrewrite.php# RewriteRule ^(.*) http://www.baidu.com [L] ...

  4. 转 Android adb root权限

    永久root带文件 因为开发需要,我经常会用到adb这个工具(Android Debug Bridge),我们都知道adb shell默认是没有root权限的,修改系统文件就很不方便了,adb pus ...

  5. bzoj2595

    一开始看是插头dp,后来发现还有一个叫斯坦纳树的东西 什么叫斯坦纳树,就是使给定点连通开销和最小的树(可以包含多余的点) 到这张平面图上,我们不难想到用dp来解决,设f[x,y,S]表示连通集合为S, ...

  6. APIO2010特别行动队(单调队列、斜率优化)

    其实这题一看知道应该是DP,再一看数据范围肯定就是单调队列了. 不过我还不太懂神马单调队列.斜率优化…… 附上天牛的题解:http://www.cnblogs.com/neverforget/arch ...

  7. LeetCode Implement Trie (Prefix Tree) (实现trie树3个函数:插入,查找,前缀)

    题意:实现trie树的3个功能,只含小写字母的串. 思路:老实做即可! class TrieNode { public: TrieNode* chd[]; bool flag; // Initiali ...

  8. 【Java基础之容器】Iterator

    Iterator: ->所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象 ->Iterator对象称作迭代器,用以方便的实 ...

  9. 扩展类加载器-------改变JAVA的父优先类加载顺序

    java的类加载机制默认情况下是采用委托模型:当加载某个类时JVM会首先尝试用当前类加载器的父类加载器加载该类,若父类加载器加载不到再由当前类加载器来加载,因此这种模型又叫做“父优先”模型. 但是在实 ...

  10. ZOJ 3299-Fall the Brick(线段树+离散化)

    题意: n个区间 ,给出区间的左右坐标 ,区间内填满宽度为1的箱子,有m个板子给出板子的高度和左右坐标(同高度不重叠) 所有箱子从上向下落,求每块板子能接到的箱子数. 分析: 首先给的区间很大,一开始 ...