【赵渝强老师】MySQL数据库的分库与分表

本文涉及的产品
RDS Agent(兼容OpenClaw),2核4GB
云数据库 PolarDB MySQL 版,列存表分析加速 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
简介: Mycat是一款开源分布式数据库中间件,支持MySQL等主流数据库,提供分库分表、读写分离、逻辑库/表抽象等功能。本文详解其核心概念(如分片表、ER表、全局序列号)、安装部署(JDK配置、服务启停)及实战配置(schema.xml/rule.xml),并演示基于三节点MySQL的分片数据路由与查询。

b440.png

MySQL数据库目前得到了广泛的应用。在使用过程中会通过搭建MySQL主从复制的架构来提高性能,同时采用分库分表的模式来解决读写分离的问题。ySQL数据库的中间件就是为了更好地使MySQL支持这些应用的场景。主流的MySQL数据库中间件有ProxySQL、Mycat、Atlas和Cobar等等。引入了数据库中间件以后,客户端就不直接操作操作MySQL数据库集群,而是通过数据库中间件进行操作。


一、 Mycat简介与核心对象

Mycat是一个开源的分布式数据库系统,对于数据库用户而言可以把它看作是一个数据库代理。它的后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL 等主流的关系型数据库,同时也支持MongoDB等NoSQL数据库。Mycat的核心功能是实现数据库的分表分库。MyCat支持标准的SQL语句进行数据的操作,在降低了开发难度的同时提升了开发速度。Mycat可以通过使用MySQL原生协议与MySQL数据库服务器进行通信,并且Mycat基于Java语言开发,因此也可以用DBC协议与大多数主流数据库服务器通信。


视频讲解如下:


下面列举了Mycat中的核心对象以及它们的含义:

  • 逻辑库:由于Mycat相当于是数据库的代理,因此Mycat作为数据库中间件其本身就可以被看做是一个或多个数据库集群构成的逻辑库。开发人员只需要面对该逻辑库进行开发即可。
  • 逻辑表:逻辑库由逻辑表组成。对于分布式数据库来说,客户端操作的就是逻辑表。逻辑表的数据来源是分布在后端一个或多个物理数据库。
  • 分片表:分片表是指将原有的大数据量表切分成多张表,其中的每一张表就是一个分片,其中均包含一部分数据。所有分片数据的合集构成了完整的表数据。
  • 非分片表:针对数据量小的表不需要进行分片,这些表就可以看成是非分片表。其实,非分片是相对分片表来说的,就是那些不需要进行数据切分的表。
  • ER表:ER与关系型数据库中的实体关系模型是类似的,它可以将具有父子关系的表及其数据存放在同一个数据分片上,即子表依赖于父表。ER表通过表分组(Table Group)保证不会跨库操作。
  • 全局表:全局表类似数据库的数据字典。它里面的数据一般不会频繁变动,并且数据规模不大,通常数据量在十万以内。
  • 分片节点:将大数据量表进行切分后,每个表的分片所在的数据库服务器节点就是分片节点。因此,可以把一个数据库实例的服务器就理解成是一个分片节点。
  • 节点主机:每个分片节点(dataNode)不一定都会独占一台机器。在同一个物理主机上可以存在多个分片数据库实例。这样一个或多个分片节点(dataNode)所在的机器就是节点主机。
  • 分片规则:分片规则是指将大数据的表切分到多个数据分片的策略。分片表需要根据分片规则进行数据的切分。
  • 全局序列号:大数据量的表被切分后,原有的关系数据库中的主键约束在分布式条件下将无法使用。为了保证数据具有唯一性的标识,从而引入全局序列号的机制。


下图展示了基于MyCat的MySQL分库分表的结构。

image.png


二、 安装部署Mycat


在了解到了Mycat的基本概念与核心对象后,下面通过具体的步骤在proxy的主机上部署Mycat环境。目前Mycat最新的版本是2.0,这里使用一个Mycat的稳定版本(1.6.7.5)来演示。


由于Mycat基于Java语言开发,因此在安装部署Mycat之前需要安装JDK。


(1)使用版本jdk-8u181-linux-x64.tar.gz安装Java运行环境。

mkdir -p /root/training
tar -zxvf jdk-8u181-linux-x64.tar.gz -C /root/training


(2)编辑文件“/root/.bash_profile”设置Java的环境变量。

JAVA_HOME=/root/training/jdk1.8.0_181
export JAVA_HOME
PATH=$JAVA_HOME/bin:$PATH
export PATH


(3)生效环境变量。

source /root/.bash_profile


(4)验证Java环境。

java -version
# 输出的信息如下:
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)


(5)下载Mycat-server-1.6.7.5-release-20200410174409-linux.tar.gz安装包。

wget \
http://dl.mycat.org.cn/1.6.7.5/2020-4-10/Mycat-server-1.6.7.5-release-20200410174409-linux.tar.gz


(6)将Mycat安装包解压到目录“/root/training”下。

tar -zxvf \
    Mycat-server-1.6.7.5-release-20200410174409-linux.tar.gz \
    -C /root/training/


(7)编辑文件“/root/.bash_profile”设置Java的环境变量。

export MYCAT_HOME=/root/training/mycat
export PATH=$MYCAT_HOME/bin:$JAVA_HOME/bin:$PATH


(8)生效环境变量。

source /root/.bash_profile


(9)启动Mycat。

mycat start


(10)查看Mycat的状态。

mycat status
# 输出的信息如下:
Mycat-server is running (89121).


三、 使用Mycat实现分库分表


Mycat实现分库分表的核心是在于配置mycat/conf/schema.xml文件和mycat/conf/rule.xml文件。前者用于定义Mycat的逻辑库、逻辑表、分片节点和节点主机等信息;而后者主要定义分片的规则。下面通过具体的步骤来演示如何基于Mycat实现后端MySQL数据库的分库与分表。这里将使用mysql11、mysql12和mysql13三台MySQL服务器作为Mycat的后端节点。


(1)在mysql11、mysql12和mysql13上创建数据库“TESTDB”,并在该库中创建一张员工表。

mysql> create database TESTDB;
mysql> use TESTDB;
mysql> create table emp
      (empno int primary key comment '员工号',
       ename varchar(10)  comment '员工姓名',
       job varchar(10) comment '员工职位',
       mgr int comment '员工老板的员工号',
       hiredate varchar(10) comment '员工的入职日期',
       sal int  comment '员工的月薪',
       comm int  comment '员工的奖金',
       deptno int comment '员工的部门号');
       
# 这里创建的数据库“TESTDB”也是Mycat默认的逻辑库名称。
# 在文件“/root/training/mycat/conf/schema.xml”中定义了该逻辑库的名称。
# 相关的定义如下:
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">


(2)在mysql11的后端数据库实例上插入10号部门的员工数据。

mysql> insert into emp values
       (7782,'CLARK','MANAGER',7839,'1981/6/9',2450,null,10),
       (7839,'KING','PRESIDENT',-1,'1981/11/17',5000,null,10),
       (7934,'MILLER','CLERK',7782,'1982/1/23',1300,null,10);


(3)在mysql12的后端数据库实例上插入20号部门的员工数据。

mysql> insert into emp values
      (7369,'SMITH','CLERK',7902,'1980/12/17',800,null,20),
      (7566,'JONES','MANAGER',7839,'1981/4/2',2975,null,20),
      (7788,'SCOTT','ANALYST',7566,'1987/4/19',3000,null,20),
      (7876,'ADAMS','CLERK',7788,'1987/5/23',1100,null,20),
      (7902,'FORD','ANALYST',7566,'1981/12/3',3000,null,20);


(4)在mysql13的后端数据库实例上插入30号部门的员工数据。

mysql> insert into emp values
      (7499,'ALLEN','SALESMAN',7698,'1981/2/20',1600,300,30),
      (7521,'WARD','SALESMAN',7698,'1981/2/22',1250,500,30),
      (7654,'MARTIN','SALESMAN',7698,'1981/9/28',1250,1400,30),
      (7698,'BLAKE','MANAGER',7839,'1981/5/1',2850,null,30),
      (7844,'TURNER','SALESMAN',7698,'1981/9/8',1500,null,30),
      (7900,'JAMES','CLERK',7698,'1981/12/3',950,null,30);


(5)编辑文件“/root/training/mycat/conf/server.xml”的内容。

......
<!-- 全局SQL防火墙设置 -->
<!--白名单可以使用通配符%或着*-->
<!--例如<host host="127.0.0.*" user="root"/>-->
<!--例如<host host="127.0.*" user="root"/>-->
<!--例如<host host="127.*" user="root"/>-->
<!--例如<host host="1*7.*" user="root"/>-->
<!--这些配置情况下对于127.0.0.1都能以root账户登录-->
<firewall>
   <whitehost>
    <host host="1*7.0.0.*" user="root"/>
      <!--增加下面的配置情况下对于192.168.79.*的主机都能以root账户登录-->
    <host host="192.168.79.*" user="root"/>
   </whitehost>
<blacklist check="false">
</blacklist>
</firewall>
<user name="root" defaultAccount="true">
    <!--root账户登录的密码-->
     <property name="password">123456</property>
    <!--root账户默认的逻辑库-->
     <property name="schemas">TESTDB</property>
     <property name="defaultSchema">TESTDB</property>
  ......
</user>
......


(6)编辑文件“/root/training/mycat/conf/schema.xml”的内容,配置逻辑库的表信息与分片的信息。

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
    <!--定义逻辑库的名称是TESTDB-->
    <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
        <!--定义一张逻辑表emp,主键是empno-->
        <!--逻辑表emp的数据分片分别位于dn1,dn2,dn3的分片节点上-->
        <!--逻辑表emp的分片路由规则采用mod-long-->
        <table name="emp" primaryKey="empno" autoIncrement="true" 
               dataNode="dn1,dn2,dn3" rule="mod-long"/>
    </schema>
    
    <!--定义分片节点,并指定该分片节点上的分片数据库-->
    <dataNode name="dn1" dataHost="mysql11" database="TESTDB"/>
    <dataNode name="dn2" dataHost="mysql12" database="TESTDB"/>
   <dataNode name="dn3" dataHost="mysql13" database="TESTDB"/>
    <!--定义节点主机-->
    <dataHost name="mysql11" maxCon="1000" minCon="10" balance="0" 
              writeType="0" dbType="mysql" dbDriver="native" 
              switchType="1" slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="mysql11" url="192.168.79.11:3306" 
                   user="root" password="Welcome_1">
        </writeHost>
    </dataHost>
    <!--定义节点主机-->
    <dataHost name="mysql12" maxCon="1000" minCon="10" balance="0" 
              writeType="0" dbType="mysql" dbDriver="native" 
              switchType="1" slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="mysql12" url="192.168.79.12:3306" 
                   user="root" password="Welcome_1">
        </writeHost>
    </dataHost>
    <!--定义节点主机-->
    <dataHost name="mysql13" maxCon="1000" minCon="10" balance="0" 
              writeType="0" dbType="mysql" dbDriver="native" 
              switchType="1" slaveThreshold="100">
        <heartbeat>select user()</heartbeat>
        <writeHost host="mysql13" url="192.168.79.13:3306" 
                   user="root" password="Welcome_1">
        </writeHost>
    </dataHost>
</mycat:schema>


(7)修改文件“/root/training/mycat/conf/rule.xml”中定义分片路由规则。

......
<tableRule name="mod-long">
   <rule>
      <!--根据员工号empno进行分片路由-->
      <columns>empno</columns>
      <algorithm>mod-long</algorithm>
   </rule>
</tableRule>
......
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
    <!--由于有3个分片节点,因此采用3为进制的轮询算法进行分片路由-->
    <property name="count">3</property>
</function>
......


(8)重启Mycat。

mycat restart

# 输出的信息如下:
Stopping Mycat-server...
Stopped Mycat-server.
Starting Mycat-server...

# 如果在启动的过程在wrapper.log日志文件中出现了下面的错误:
Startup failed: Timed out waiting for a signal from the JVM.

# 可以在conf/wrapper.conf文件增加下面的参数:
wrapper.startup.timeout=300

# 然后进入mycat的bin目录执行重启操作。
./mycat console 或者./mycat start


(9)借助MySQL的图形客户端工具“Navicat for MySQL”连接Mycat服务器。如下图所示。

image.png


(10)连接成功后,可以看到Mycat中存在一个逻辑库“TESTDB”和一张逻辑表“emp”,如上图所示。


(11)查询逻辑表“emp”中的数据,这里返回的14条数据分别来自于后端的mysq11、mysql12和mysql13上的MySQL数据库实例。如下图所示。

image.png


(12)往逻辑表“emp”中插入3条新的数据,如下图所示。

mysql> insert into emp(empno,ename,sal,deptno) values(1,'Tom1',1000,10);
mysql> insert into emp(empno,ename,sal,deptno) values(2,'Tom2',1000,10);
mysql> insert into emp(empno,ename,sal,deptno) values(3,'Tom3',1000,10);

image.png

(13)直接在后端的mysq11、mysql12和mysql13上的MySQL数据库实例中查询员工表的数据。这时候会发现新插入的三条数据被存储在不同的节点上。如下图所示。

image.png

相关文章
|
2月前
|
机器学习/深度学习 存储 人工智能
业务逻辑的“坍塌”:当应用层只剩下胶水代码,在 AI Agent 时代,我们该构建什么
作者通过亲手编写代码、研究底层原理和对比传统架构,系统地梳理了从“怀疑 AI”到“理解并驾驭 AI”的心路历程。
497 148
业务逻辑的“坍塌”:当应用层只剩下胶水代码,在 AI Agent 时代,我们该构建什么
|
SQL 关系型数据库 数据库
【微服务系列笔记】Seata
Seata是一种开源的分布式事务解决方案,旨在解决分布式事务管理的挑战。它提供了高性能和高可靠性的分布式事务服务,支持XA、TCC、AT等多种事务模式,并提供了全局唯一的事务ID,以确保事务的一致性和隔离性。Seata还提供了分布式事务的协调、事务日志、事务恢复等功能,帮助开发人员简化分布式事务的管理和实现。
871 1
|
机器学习/深度学习 存储 运维
一文读懂智能化运维监控如何赋能IT可观察性
近年来,互联网高速发展下的需求驱动、技术进步以及商业模式的转变,导致了企业各类业务趋向数字化,以此期望突破传统业务来找到新的利润增长点。为此,企业新建、重构了大量互联网类的业务系统,给企业基础设施、网络和应用各条线的运维管控带来了巨大的压力。如何利用已有的各类运行数据来更好地观测我们的系统,提升业务的连续性以及客户体验,是所有正处于数字化转型过程的企业都需要思考的重点。
1197 142
一文读懂智能化运维监控如何赋能IT可观察性
|
存储 数据采集 物联网
SHEVDC平台及物联网技术产品选型
本文的整理自2017云栖大会-南京峰会上技术专家李学根的分享讲义,讲义以新能源汽车发展现状与未来前景为背景,介绍SHEVDC平台搭建设计与物联网技术产品选型应用,其分享的重点在于大数据并发与存储解决方案,与平台体系建设未来展望。
10246 146
|
物联网 数据安全/隐私保护
如何用Link Develop开发一个智能厕所
由于阿里云悬殊的男女比例,以及厕所占地面积的限制,各位男同胞每天都要在特殊味道的包围下等待有限的坑位。我们在想能不能利用物联网技术做一个低成本的解决方案,让男同胞们不需要亲自去现场的情况下也能得知坑位的空余情况(像停车场一样),基于我们IoT事业部的一站式开发平台——Link Develop,做一个IoT的智能厕所。
6298 150
|
物联网 语音技术 开发工具
基于AliOS Things玩转智能语音
随着AI技术的进步,智能语音开始将人机交互从手+眼睛的传统模式中解放出来。带给人们更便捷、更风趣、更有人情味的体验,让被操作对象变得不再只是一个死板的工具,而更像是一个有生命的助理。“帮我打开空调”,“明天上班需要带伞吗”,“快递到哪了”…在万物互联的时代,你的所有需求只需要一句话便能实现。
9761 147
|
监控 安全 固态存储
基于Zero-Ice搭建的物联网监控平台
基于Zero-Ice搭建的物联网远程实时监控平台
14485 147
|
负载均衡 Kubernetes 安全
服务网格ASM使用FAQ之(5):ASM网关支持在SLB侧创建HTTPS类型的监听
ASM网关提供HTTPS安全支持、证书动态加载,从而提升ASM网关安全性。除了在ASM网关侧绑定证书的方式之外, 还可以在负载均衡侧管理证书。 本文介绍如何支持ASM网关服务在负载均衡侧绑定证书, 并创建HTTPS类型的监听。
904 142
|
域名解析 存储 缓存
闲鱼异地多活架构设计与实现
异地多活是高可用架构中复杂度最高的一种。以闲鱼导购链路为例,聊聊怎样实现这样一套复杂系统。
883 143
闲鱼异地多活架构设计与实现