DB | Mycat分库分表

1,756 阅读6分钟

一、MyCat简介

MyCat是一款数据库中间件,上层用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问。

MyCat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储。

可以这样理解:数据库是对底层存储文件的抽象,而Mycat是对数据库的抽象。

二、拆表机制

  • 横向(水平)拆分:根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面; 比如,id1-10000在表1,10001-20000在表2
  • 纵向(垂直)拆分:将表中的某些字段拆分成单独的表,一般被拆分的表的字段数比较多。主要是避免查询的时候出现因为数据量大而造成的“跨页”问题。(MySQL底层是通过数据页存储的,一条记录占用空间过大会导致跨页,造成额外的性能开销。)

三、MyCat原理

MyCat技术原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户。

四、分库分表实战:

schema.xml中定义逻辑库,表、分片节点等内容 ,该文件中定义了数据库服务器,表的拆分规则等等重要信息 rule.xml主要配置路由策略,主要有分片的片键,拆分的策略(取模还是按区间划分等) server.xmlservice.xml主要配置mycat服务的参数,比如端口号,myact用户名和密码使用的逻辑数据库等

1、下载mycat、jdk、mysql客户端命令行工具

2、启动mysql服务:docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:latest

3、设置 MYCAT_HOME 的变量

export MYCAT_HOME=/usr/local/mycat/
export PATH=${JAVA_HOME}/bin:${MYCAT_HOME}/lib:$PATH
source /etc/profile

#
将/mycat/bin目录添加到环境变量:方便使用mycat命令
export PATH=/data/mycat/bin:$PATH
source /etc/profile

4、配置 JDK 路径

vim wrapper.conf
wrapper.java.command=/lib/jvm/bin/java #告诉Mycat需要使用哪个JDK,要使用本机的jdb路径

5、修改配置文件

  • server.xml

    <user name="root" defaultAccount="true">
      <property name="password">123456</property>
      <property name="schemas">testdb</property>
    <\user>
    配置mycat的连接信息,这里虚拟了一个逻辑数据库testdb
  • schema.xml

    <mycat:schema xmlns:mycat="http://io.mycat/">
        <!--逻辑数据库的配置,name和上面的schemas的值是对应的-->
        <schema name="testdb" checkSQLschema="false" sqlMaxLimit="100">
            <!--逻辑数据库的表,这些表在对应的数据库要存在,并且结构一致-->
            <!--取模分片(分片也就是切分)-->
            <table name="student" primaryKey="id" dataNode="dn1,dn2,dn3" rule="mod-long" />
            <table name="grade" primaryKey="id" dataNode="dn4"/>
        </schema>

        <!-- 申明节点对应的database ,dataHost和下面的dataHost的name是对应的-->
        <dataNode name="dn1" dataHost="localhost1" database="beijing" />
        <dataNode name="dn2" dataHost="localhost1" database="shanghai" />
        <dataNode name="dn3" dataHost="localhost1" database="guangzhou" />
        <dataNode name="dn4" dataHost="localhost1" database="basic" />

        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
                  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">

            <heartbeat>select user()</heartbeat>
            <!-- 可读写的数据库实例 -->
            <writeHost host="hostM1" url="localhost:3306" user="test" password="test123...">
            </writeHost>            
        </dataHost>
    </mycat:schema>

    <!--注意:这里自己创建一个用户,不要使用mysql的root用户,否则一直连接不上;-->
    报错:ERROR 1184 (HY000): Invalid DataSource:0,具体原因不详;
    (配置中的test用户的host是%,而root用户的host有%也有loaclhost,难道是这个原因?)
    (默认的账号的host属性都是localhost,意思是这个账号只能本地使用,如果要使用某个账号来远程登录,必须将账号的host属性值更改成%)

    还是连接不上时,试试把localhost改成127.0.0.1

6、启动mycat

mycat start #启动后要等会再进行操作,不然会Lost connection to MySQL server during query

7、在命令行访问mycat逻辑数据库

mysql -h 127.0.0.1 -P 3306 -u test -ptest123... #连接mysql

mysql -uroot -p123456 -h127.0.0.1 -P8066 TESTDB #连接mycat服务端,平时对数据库进行操作是连这个
mysql -uroot -p123456 -h127.0.0.1 -P9066 TESTDB #连接mycat管理端

8、操作逻辑数据库,就跟操作单库似的了

#创建数据库和表
create database beijing;
use beijing;
create table student(
    id    int primary key,
    name   varchar(8not null,
    grade  int  not null
);

create database shanghai;
use shanghai;
create table student(
    id    int primary key,
    name   varchar(8not null,
    grade  int  not null
);

create database guangzhou;
use guangzhou;
create table student(
    id    int primary key,
    name   varchar(8not null,
    grade  int  not null
);

create database basic;
use basic;
create table grade(
    id    int primary key,
    name   varchar(8not null
);

#插入数据
insert into grade (id,namevalues (1,'一年级');
insert into grade (id,namevalues (2,'二年级');
insert into grade (id,namevalues (3,'三年级');

insert into student (id,name,grade) values (1,'张三',2);
insert into student (id,name,grade) values (2,'李四',1);
insert into student (id,name,grade) values (3,'王五',3);
insert into student (id,name,grade) values (4,'甲',3);
insert into student (id,name,grade) values (5,'乙',2);
insert into student (id,name,grade) values (6,'丙',1);

#此时,去每个物理库查看数据,student表的6条数据是分布的存储的
select * from student;插叙结果是6条数据

至此,分库分表简单操作已经完成;

本文使用 mdnice 排版