
-- ------------------------------------------分库分表 介绍---------------------------------------------------------

/*问题分析
我们学到现在为止，所有的数据库、所以的表，表中的所有数据，都是存放在一个数据库服务器当中的，如果业务每天会产生了大量的数据，
长年累月下来这台数据库中所存放的数据量将会非常大，那如果说这台数据库的磁盘以及内存不足了，该怎么办呢

单数据库的问题分析
1. 当累积的数据量大时，一般会增加磁盘、内存
2. 由于磁盘和内存受硬件影响，所以仅仅这样是不能完全解决问题的，会降低数据库性能

随着互联网及移动互联网的发展，应用系统的数据量也是成指数式增长，若采用单数据库进行数据存储，存在一下性能瓶颈:
1. IO瓶颈: 热点(太多用户访问)数据太多，造成数据库缓存不足，从而产生大量磁盘IO，效率较低。请求数据太多，带宽不够，网络IO瓶颈
2. CPU瓶颈: 排序、分组、连接查询、聚合统计等SQL会耗费大量的CPU资源，请求数太多，CPU出现瓶颈

分库分表
指的是将原来存储在一台数据库服务中的数据，分散地存储在多台数据库服务中，从而缓解单台数据库服务的磁盘存储及访问的压力。
原来是用户所有的请求是一台数据库服务器在处理，现在是分散到多台数据库服务器上面进行处理*/

-- ------------------------------------------分库分表 拆分方式------------------------------------------------------

/*什么是分库: 对一个数据库进行拆分
什么是分表: 对表结构进行拆分，将存储在一张表结构的数据，分散地存储在多张表结构当中

拆分策略(拆分维度)分为以下两种

一、垂直拆分

1. 垂直分库:
2. 垂直拆表

二、水平拆分
1. 水平分库
2. 水平分表

下面会细讲这两种拆分策略
############################################################################################

【垂直拆分】

垂直分库:
指的是以表为依据，根据业务将不同表拆分到不同库中

垂直分库的特点
1. 每个库的表结构都不一样
2. 每个库的数据也不一样
3. 所有库的并集是全量数据

垂直分表:
指的是以字段为依据，根据字段属性将不同字段拆分到不同表中

垂直分表的特点
1. 每个表的结构都不一样
2. 每个表的数据也不一样，多张表之间一般通过一列(主键/外键)关联
3. 所有表的并集是全量数据


【水平拆分】

水平分库:
指的是以字段为依据，按照一定策略，将一个库拆分到多个库中

水平分库的特点
1. 每个库的表结构都一样
2. 每个库的数据都不一样
3. 所有库的并集是全量数据

水平分表:
指的是以字段为依据，按照一定策略，将一个表的数据拆分到多个表中

水平分表的特点
1. 每个表的表结构都一样
2. 每个表的数据都不一样
3. 所有表的并集是全量数据

############################################################################################
思考:当我们把原来存储在一个数据库当中的数据分散地存储在多个数据库当中，对于应用程序来说，原来是操作一个数据
库，现在变成要操作多个数据库，那么我们该如何实现分库分表，以及分库分表之后应用程序的访问该如何进行
下面来介绍分库分表需要依赖什么技术，从此可以来解决我们思考的问题

1. shardingJDBC: 基于AOP原理，在应用程序中对本地执行的SQL进行拦截、解析、改写、路由处理。需要自行编码配
置实现，只支持java语言，性能较高

2. MyCat: 数据库分库分表的中间件，不用调整代码即可实现分库分表，支持多种语言，性能不及前者

什么是数据库分库分表的中间件
指的是使用了MyCat之后，应用程序不需要做任何的改动，也不用考虑每一次应该连接哪个数据库、我们应该操作哪个数据库，而且
我们也不用在应用程序当中去集成任何第三方的依赖，也不用做其它的编码和配置，有了这个中间件之后，我们的应用程序在访问的
时候不用直接访问数据库，直接访问MyCat中间件即可。访问MyCat就和访问MySQL，对于应用程序来说是一样的、无感知的

我们后面的课主要学MyCat*/

-- ------------------------------------------分库分表 MyCat安装----------------------------------------------------

/*MyCat概述
MyCat是阿里巴巴的产品，是开源的、活跃的、基于java语言编写的MySQL数据库中间件。可以像使用mysql一样来使用mycat，对于
开发人员来说根本感觉不到mycat的存在。也就是之前我们的应用程序连接的是MySQL，现在我们连接MyCat，把MyCat看做是一台
MySQL服务器，由MyCat去连接底层的MySQL

原理:
MyCat通过伪装MySQL的协议，所以可以把MyCat看作成一台MySQL服务器

MyCat优点
1. 性能可靠稳定
2. 强大的技术团队
3. 体系完善
4. 社区活跃

下载MyCat安装包(MyCat1.6版本比较主流，也比较稳定，我们课程选取的是Mycat-server-1.6.7.3-release版本)
下载地址: http://dl.mycat.org.cn
官网地址: http://mycat.org.cn

安装
MyCat是采用java语言开发的开源的数据库中间件，支持Windows和linux(该课程用这个)运行环境，下面介绍MyCat的linux中的环境搭建
我们需要准备好如下:
1. 一台linux系统
2. 在linux系统里面安装好MySQL服务(最终数据存储是在mysql里面的，MyCat仅仅是一个中间件，不存储数据)
3. JDK(这个是java语言的运行环境)
4. MyCat

需要准备四台linux系统，都安装一下mysql服务，具体每台安装什么，如下
1. 第一台服务器(192.168.127.138): 安装MySQL、JDK、MyCat。作为MyCat中间件服务器，同时也作为分片服务器
2. 第二台服务器(192.168.127.145): 安装MySQL。作为分片服务器
3. 第三台服务器(192.168.127.149): 安装MySQL。作为分片服务器
4. 第四台服务器(192.168.127.150): 安装MySQL。作为分片服务器

注意MyCat的安装目录(/usr/local/mycat)中的目录代表的意思:
1. bin: 存放可执行文件，用于启动、停止、重启mycat服务
2. conf: 存放mycat的配置文件
3. lib: 存放mycat的项目依赖包(jar包)
4. logs: 存放mycat的日志文件
5. catlet: 在多表联查的时候所涉及到的目录

建议安装直接看视频，不要安装错了*/

-- ------------------------------------------分库分表 MyCat核心概念------------------------------------------------

/*MyCat的结构分为逻辑结构(不存放数据，只是逻辑上的)、物理结构(存储具体的数据)

【逻辑结构】
1. 最上层(第一层)的是schema，称为逻辑库，也就是逻辑上的数据库，并不存储具体的数据
2. 第二层的是table，称为逻辑表，第二层可包含若干个逻辑表
3. 第三层的是dataNode，称为分片节点(也叫数据节点)，一个table的数据会分散地存储在多个dataNode上
4. 第二层table的数据什么时候会关联第三层的节点、什么时候会存储在第三层的节点上，这些都是由分片规则决定的
5. 例如第二层的某个table关联了第三层的3个分片节点，那么就是说该table表的数据会分散地存储在这3个分片节点当中

【物理结构】
有多个数据库，每个数据库负责存储 '逻辑结构的分片节点' 的数据。物理结构的每个数据库，称为节点主机。
一个分片节点对应一个数据库。多个数据库是我们自己的数据库，也就是理解为MyCat帮我们把数据从逻辑
结构那里中转过来

注意
1. 登录进mycat看到的数据库，叫逻辑库，库结构和库数据并不真实存在
2. 登录进mycat看到的数据表，叫逻辑表，表结构和表数据并不真实存在
3. 登录进mysql看到的数据库，叫数据库，里面存储具体的数据，真实存在
4. 登录进mysql看到的数据表，叫数据表，里面存储具体的数据，真实存在
5. 登录进mycat，且执行增删改，数据会同步跟mycat有关的所有mysql数据库

注意
1. SHOPPING ≠ shopping。原因:shopping是我们自定义的数据库名，并不是关键字，所以是严格区分大小写的
2. SHUIPING_FENBIAO ≠ shuiping_fenbiao。原因:shuiping_fenbiao是我们自定义的数据库名，并不是关键字，所以是严格区分大小写的*/

-- ------------------------------------------分库分表 MyCat入门(水平分表)------------------------------------------

/*这节课我们以一个需求，来演示通过MyCat中间件如何来完成分片操作

需求:
由于tb_order表中的数据很大，磁盘IO及容量都到达了瓶颈，现在需要对tb_order表进行数据分片，分为三个数据节点，
每个节点主机位于不同的服务器上。简单理解就是tb_order表的数据被分成了三份，分别在三台数据库服务器，每份的
表结构是一样的，但是表结构里面存放的数据是不一样的，也就是要求我们对tb_order表进行水平分表

环境准备
1. 第一台服务器(192.168.127.138): 安装MySQL、JDK、MyCat。作为MyCat中间件服务器，同时也作为分片服务器
2. 第二台服务器(192.168.127.145): 安装MySQL。作为分片服务器
3. 第三台服务器(192.168.127.149): 安装MySQL。作为分片服务器
4. 第四台服务器(192.168.127.150): 安装MySQL。作为分片服务器

启动mycat服务(注意mycat启动之后，会占用端口号8066，我们只要访问8066端口对应的服务即可)
切换到mycat的安装目录，执行如下指令:
#启动
cd /usr/local/mycat && bin/mycat start
#停止
cd /usr/local/mycat && bin/mycat stop
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log

登录mycat
服务mycat和服务mysql是一样的，可以把mycat就看做是mysql，登录进去后使用的命令也是跟mysql一样
mysql -h 192.168.127.138 -P 8066 -uroot -p123456
登录进去会发现跟mysql好像差不多，注意区别: 看登录后的提示显示'Server version: 5.6.29-mycat-1.6.7.3-release-20210913163959 MyCat Server

#################################################################################################################

具体过程:

1. 在第二、三、四服务器的mysql服务上都创建db01数据库

2. 在第一台服务器进行分片配置(cd /usr/local/mycat/conf && vim schema.xml): 详细见'模板'文件(我会写好发出来)

3. 在第一台服务器进行分片配置的mycat用户及其用户的权限信息(cd /usr/local/mycat/conf && vim server.xml): 见'模板'文件(我会写好发出来)

4. 在第一台服务器启动mycat
cd /usr/local/mycat && bin/mycat start
cd /usr/local/mycat && tail -f logs/wrapper.log

5. 登录mycat。访问需要的用户和密码，我们是在server.xml配置的，就是上面第3步那里配置过的
mysql -h 192.168.127.138 -P 8066 -uroot -p123456

6. 查看mycat里面有哪些数据库
show databases;#只有一个DB01数据库(就是上面第2步那里配置的schema.xml文件我们写的)

7. 查看DB01数据库有哪些表
use DB01;
show tables;#只有一个tb_order表(就是上面第2步那里配置的schema.xml文件我们写的)

8. 简单来玩一下。1个create命令，6个insert命令。在mycat中来创建表，并往表结构中插入数据，查看数据在不同分片节点服务器MySQL中的分布情况
create table tb_order(
    id bigint(20) not null,
    title varchar(100) not null,
    primary key (id)
)engine=innodb default charset=utf8;
insert into tb_order(id,title) values(1,'goods1');
insert into tb_order(id,title) values(2,'goods2');
insert into tb_order(id,title) values(3,'goods3');
insert into tb_order(id,title) values(1000000,'goods1000000');
insert into tb_order(id,title) values(10000000,'goods10000000');
insert into tb_order(id,title) values(12000000,'goods12000000');

我们是在'第一台服务器'的mycat里面执行上面的create命令，
会发现创建的表结构(也就是表的字段)会同时同步在第二、三、四台机器上，
原因是我们的是水平分表

我们是在'第一台服务器'的mycat里面执行上面的前3个insert命令，
会发现产生的数据都在'第二台机器'上，思考为什么不会平均分散到第二、三、四台及其上呢
原因:数据怎么分配取决于我们在上面第2步配置的schema.xml文件，里面有一个'rule'，表示'分片规则'
(1)rule: auto-sharding-long表示id值在0~500百万，那么会存放在第一个节点服务器(第二台机器)。id值在500百万~1000万，会存放到第二个节点，...

我们是在'第一台服务器'的mycat里面执行上面的后3个insert命令，
会发现产生的数据在第二、三、四台机器上分别有一条数据。原因同上

注意是不同步到'第一台服务器'的，感觉非常奇妙。因为我们配置第2步配置的schema.xml文件时，指定了分片节点服务器为第二、三、四台服务器

9. 如何修改第8步的分片规则，就是我们想自己指定'哪个范围的数据'会分配给'哪个分片MySQL服务器'
cd /usr/local/mycat/conf && vim autopartition-long.txt
为什么我们需要自己修改:
原因:
(1)我们只在第2步的schema.xml文件配置了三台分片MySQL服务器，也就是id值的上限默认是1500万，当id值大于这个数就会报错，
当我们业务中需要插入id值是大于1500万的话，我们就修改这个默认值(500万为单位递增)，修改为每700万单位递增，或者每1000万数据就存到下一个
分片服务器
(2)当我们业务中的数据远没有500万的时候，数据就会全部只存到'第二台服务器'，那我们的第三、四台服务器就会被闲置，造成浪费资源。我们就可以
给默认值(500万)调低一些，比如我们业务实际只有20万数据，那么分库分表的话，这个默认只为7万即可。当数据的id值是0~7万就会存入'第二台服务器'，
当数据的id值是7万~14万就会存入'第三台服务器'，当数据的id值是14万~21万数据就会存入'第三台服务器'。后续数据的id值超过21万的话，就在schema.xml
文件里面再增加一台分片服务器即可，然后在autopartition-long.txt文件添加一条默认值记录

【到这里就完成啦，下几节课开始我们会详细讲mycat配置、mycat分片、分片规则。这节课是笼统的讲一下全部知识点，好有个概况】
【ps: 知识点有点撑，我一下午就只完成了这节课的笔记，任重道远，如果不会的话，没关系，下一节课会详细讲其中的知识点】*/

-- ------------------------------------------分库分表 MyCat配置--------------------------------------------------

/*通过上节课的学习，我们主要是关注其中的四个配置文件，分别是如下

1. 配置逻辑库、逻辑表等相关信息
cd /usr/local/mycat/conf && vim schema.xml

2. 配置MyCat运行的服务信息，例如用户及其用户权限
cd /usr/local/mycat/conf && vim server.xml

3. 配置分片规则
cd /usr/local/mycat/conf && vim rule.xml

4. 配置单台分片节点服务器的id值上限，默认是500万
cd /usr/local/mycat/conf && vim autopartition-long.txt


我们会在下面详细介绍schema.xml、server.xml、rule.xml配置文件
##########################################################################################################

【schema.xml】

schema.xml作为MyCat中最重要的配置文件之一，涵盖了MyCat的逻辑库、逻辑表、分片规则、分片节点及数据源的配置
主要包含以下三组标签(我们打开schema.xml文件后，会看到以html格式的文本，里面都是一些标签，其中我们会详细学三组重要的标签)

一、 schema标签
schema标签用于定义MyCat实例中的逻辑库，一个MyCat实例中，可以有多个逻辑库，可以通过schema标签来划分不同的逻辑库。
MyCat中的逻辑库的概念，等同于MySQL中的数据库概念，需要操作某个逻辑库下的表时，也需要切换逻辑库(use xxx)。

核心属性:

1. name: 指定自定义的逻辑库库名

2. checkSQLschema: 在SQL语句操作时指定了数据库名称，执行时是否自动去除。true: 自动去除，false: 不自动去除。举例如下
true: 在没有use DB01的情况下，可以直接使用DB01.tb_order来查看表数据
false: 必须先use DB01，才能查看BD01数据库里面的表数据

3. sqlMaxLimit: 如果未指定limit进行查询，列表查询模式查询多少条记录。即在不手动指定limit情况下，最多可查询多少条记录

4. table: schema标签里面的table标签定义了MyCat中逻辑库schema下的逻辑表，所以需要拆分的表都需要在table标签中定义。有如下属性
(1)name: 定义逻辑表表名，在该逻辑表下唯一
(2)dataNode: 定义逻辑表所属的dataNode，该属性需要与dataNode标签中的name相对应。多个dataNode，用逗号分隔
(3)rule: 分片规则的名字，分片规则名字是在rule.xml中定义的。注意只有使用分表的时候才有，如果是使用分库的话，是不写rule属性的
(4)primaryKey: 逻辑表对应真实表的主键
(5)type: 逻辑表的类型，目前逻辑表只有全局表和普通表，如果为配置，就是普通表。配置为global，就是全局表

二、 dataNode标签
dataNode标签中定义了MyCat中的数据节点，也就是我们通常说的数据分片。一个dataNode标签就是一个独立的数据分片

核心属性:

1. name: 定义数据节点名称
2. dataHost: 数据库实例主机名称，引用自dataHost标签中name属性
3. database: 定义分片所属数据库

三、 dataHost标签
dataHost标签在MyCat逻辑库中作为底层标签存在，直接定义了具体的数据库实例、读写分离、心跳语句

核心属性:

1. name: 唯一标识，供上层标签使用
2. maxCon/minCon: 最大连接数/最小连接数
3. balance: 负载均衡策略，取值0,1,2,3共4种取值，分别对应了不同的负载均衡策略。后面学读写分离的时候会重点介绍
4. writeType: 写操作的分发方式。0表示所以的写操作都转发到第一个writeHost，第一个挂了，才会切换到第二个。1表示写操作随机分发到配置的writeHost
5. dbDriver: 数据库驱动，支持两种，分别是native、jdbc


【rule.xml】
rule.xml里面的是分片规则，定义所有拆分表的规则，在使用过程中可以灵活的使用分片算法，或者对同一个分片算法使用不同的参数，来达到分片过程的可配置化。
主要包含以下两类标签: tableRule、Function


【server.xml】
server.xml配置文件包含了MyCat的系统配置信息。
主要包含以下两个重要的标签:system、user

一、system标签
系统在运行时的参数及配置信息。也就是对应的系统配置项及其含义，里面可以自定义配置MyCat的端口，默认是8066端口。后面还会讲9066，是MyCat的管理端口

二、user标签
主要配置的是当前MyCat服务中间件，能够被哪些用户访问，用户名是什么，密码是什么，用户能够访问哪些数据库，以及访问数据库时所具备的权限，
简单说就是配置的是用户及其用户所具备的权限信息

有以下属性:

1. user name: 用户名
2. property password: 密码
3. property schemas: 该用户可以访问的逻辑库，多个逻辑库之间用逗号分隔
4. check: 是否开启DML权限检查，默认为false
5. schema name:配置指定逻辑库的权限
6. table dml: 配置指定逻辑表的权限，用四位的数字表示，每一位分别表示增、查、改、删，例如1110，表示该用户拥有增查改，没有删的权限。
可以出现多个权限可选的话，会默认采用就近原则
7. property name: 是否只读，默认为false*/

-- ------------------------------------------分库分表 垂直分库---------------------------------------------------------

/*【垂直拆分】
分为垂直分表和垂直分库，我们这节课演示的是垂直分库
场景:在业务系统中，设计以下表结构，但是由于用户与订单每天都会产生大量的数据，单台服务器的数据存储及处理能力是有限的，可以对
数据库进行拆分，原有的数据库表如下:

tb_areas_city、tb_areas_provinces、tb_areas_region、tb_goods_base、tb_goods_brand、tb_goods_cat、tb_goods_desc、
tb_goods_item、tb_order_item、tb_order_master、tb_order_pay_log、tb_user、tb_user、tb_user_address

也就是将上面的那些表(都是存放到一个数据库的)，由于一个数据库压力较大，需要将这些表拆分到多个数据库中，采用垂直分库
分析一下上面那些表可以怎么分类。例如前三个是代表'省市区'、往后五个是代表'商品'、往后三个是代表'订单'、最后两个是代表'用户'
我们现在把其中的'用户'和'省市区'放到同一个数据库服务器 ，把另外两个分别放到一个数据库服务器

共要准备三台数据库服务器。分别在三台数据库服务器中创建数据库shopping
1. 第一台: 192.168.127.138
2. 第二台: 192.168.127.149
3. 第三台: 192.168.127.150

启动mycat服务(注意mycat启动之后，会占用端口号8066，我们只要访问8066端口对应的服务即可)
切换到mycat的安装目录，执行如下指令:
#启动
cd /usr/local/mycat && bin/mycat start
#停止
cd /usr/local/mycat && bin/mycat stop
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log

【具体过程如下:】

1. 在第一台服务器的MyCat需要进行如下配置。详细见'模板'文件(我会写好发出来)
cd /usr/local/mycat/conf && vim schema.xml

2. 在第一台服务器的MyCat需要进行如下配置。详细见'模板'文件(我会写好发出来)
cd /usr/local/mycat/conf && vim server.xml

3. 在第一台服务器重新启动mycat
cd /usr/local/mycat && bin/mycat stop
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log

4. 在第一台服务器上登录mycat
mysql -h 192.168.127.138 -P 8066 -u root -p123456

5. 查看mycat里面有哪些数据库
show databases;#只有一个SHOPPING数据库(就是上面第1步那里配置的schema.xml文件我们写的)

6. 查看SHOPPING数据库有哪些表
use SHOPPING;
show tables;#有13个tb_...表(就是上面第1步那里配置的schema.xml文件我们写的)，注意这些表是表结构，还没有插入数据

7. 给上面的13个表插入数据。使用脚本(我会放到模板文件那里)，拿到之后把脚本放到/root目录下面，在上面第6步之后接着执行如下
source /root/shopping-table.sql
source /root/shopping-insert.sql

8. 此时在datagrip软件(或直接在终端&命令行)去第一、二、三台服务器看看shopping表，数据就出来了

9. 演示到这步就算是结束垂直分库啦，下面的就是演示一些特殊的情况，也就是在多表查询的场景下，来查询我们上面导入的数据

10. 如下
(1) 在第一台服务器(登录进mysql即可)、第二台服务器(登录进mysql即可)、第三台服务器(登录进mysql即可)里面查询用户的
收件人及收件人地址信息(包含省市区)

特点: 多表联查涉及的表都在同一台服务器
选中如下四行并执行，在三台服务器都执行一下，看能不能查，会不会报错。总结: 都能查，不报错

use shopping;
select ua.user_id,ua.contact,p.province,c.city,r.area,ua.address from
tb_user_address as ua, tb_areas_provinces as p, tb_areas_city as c, tb_areas_region  as r where
ua.province_id = p.provinceid and ua.city_id = c.cityid and ua.town_id = r.areaid;

(2) 在第一台服务器(登录进mysql即可)、第二台服务器(登录进mysql即可)、第三台服务器(登录进mysql即可)里面查询每
一笔订单及订单的收件地址信息(包含省市区)

特点: 多表联查涉及的表都在多台服务器当中
选中如下四行并执行，在三台服务器都执行一下，看看有什么区别。总结: 都报错，不能执行成功
原因: mycat底层的路由(route)，在为SQL语句进行路由的时候，发现SQL语句当中关联的表在不同的分片中(不同服务器)，就会、
导致mycat不知道要路由到哪个分片

use shopping;
select order_id,payment,receiver,province,city,area from
tb_order_master as o, tb_areas_provinces as p, tb_areas_city as c, tb_areas_region as r where
o.receiver_province = p.provinceid and o.receiver_city = c.cityid and o.receiver_region = r.areaid;

解决:
需要涉及到'全局表'的配置。对于省、市、区/县表: tb_areas_provinces、tb_areas_city、tb_areas_region，是属于'数据字典表'，
在多个业务模板中都可能会遇到，可以将其设置为'全局表'，利于业务操作

什么是字典表: 其实就是比较常用的表，就统称为字典表，例如省、市、区/县表
什么是全局表: 在每一个分片(也就是每一台服务器)中，都有这个表

如何将表配置为全局表，具体做法如下

第一步:
在第一台服务器[root@localhost ~](只有这台服务器有mycat)，进行配置。在<table标签那里加一个属性type，并把值写为global，即type="global"
并在<table标签把dataNode修改为"dn1,dn2,dn3"代表这张表会同时在三台分片服务器都存在。该配置文件我也打包放在模板文件了
cd /usr/local/mycat/conf && vim schema.xml

第二步:
在第一(登录进mysql，不是登录进mycat)、二、三台服务器分别都删除shopping数据库，并重新创建一个shopping数据库
drop database if exists shopping;
create database if not exists shopping;

第三步:
在第一台服务器[root@localhost ~]重启mycat
cd /usr/local/mycat && bin/mycat stop
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log

第四步:
在第一台服务器上登录mycat，并重新导入数据
mysql -h 192.168.127.138 -P 8066 -u root -p123456
use SHOPPING;
source /root/shopping-table.sql
source /root/shopping-insert.sql

第五步:
此时在datagrip软件(或直接在终端&命令行)去第一、二、三台服务器看看shopping表，数据就出来了

第六步:
重新执行'在第一台服务器(登录进mysql即可)、第二台服务器(登录进mysql即可)、第三台服务器(登录进mysql即可)里面查询每
一笔订单及订单的收件地址信息(包含省市区)'

use shopping;
select order_id,payment,receiver,province,city,area from
tb_order_master as o, tb_areas_provinces as p, tb_areas_city as c, tb_areas_region as r where
o.receiver_province = p.provinceid and o.receiver_city = c.cityid and o.receiver_region = r.areaid;

在第一、二台服务器都能查了，不报错。第三台会报错是因为我们是按需把特定的表(省、市、区/县表)修改为了全局表，
第三台服务器如果要不报错的话，只需要把tb_order_master表也修改为全局表即可。我们在实际业务中，可以灵活的把我们
要多表联查，但是在当前服务器没有这个表的情况下，把我们需要的表设置为全局表，即可


最后，全局表还有一个特性，如下
在第一台服务器(登录进mysql即可)，执行一个更新语句，会发现只有第一台服务器的数据发生了变化，第二、三台服务器的数据依旧没变
update tb_areas_provinces set province = '北京' where id = 1;
在第一台服务器(必须登录进mycat)，执行一个更新语句，会发现第一、第二、三台服务器的数据都发生了变化
update tb_areas_provinces set province = 'ikun' where id = 2;
总结: 在mycat里面执行的操作会同步修改所以分片服务器里面所属的数据。另外不要单独在分片服务器进行数据更新，不然会导致数据的不一致
也就是当我们要修改数据时，要登录进mycat进行修改数据，不要登录进mysql进行修改数据*/

-- ------------------------------------------分库分表 水平分表---------------------------------------------------------

/*水平拆分
分为水平分表和水平分库，我们这节课演示的是水平分表
场景: 在业务系统中，有一张表(日志表)，业务系统每天都会产生大量的日志数据，单台服务器的数据存储及存储能力是有限的，
现需要对数据库表进行拆分(水平分表)

共要准备三台数据库服务器。分别在三台数据库服务器中创建数据库shuiping_fenbiao
1. 第一台: 192.168.127.138
2. 第二台: 192.168.127.149
3. 第三台: 192.168.127.150

这节课我们配置第一台服务器的schema.xml文件时，不删除上节课SHOPPING数据库的任何数据，只是在上节课的基础上进行添加，
看一下等下在第一台服务器登录mycat的时候，能不能有权访问SHOPPING、SHUIPING_FENBIAO

注意SHOPPING ≠ shopping。原因:shopping是我们自定义的数据库名，并不是关键字，所以是严格区分大小写的
注意SHUIPING_FENBIAO ≠ shuiping_fenbiao。原因:shuiping_fenbiao是我们自定义的数据库名，并不是关键字，所以是严格区分大小写的

由于是水平分表，所以我们要在第一台服务器的schema.xml文件的<schema标签里面的table标签指定rule分片规则，我们在a_128_0
课的时候，指定的rule为"auto-sharding-long"，代表的意思是根据主键范围进行分片，例如主键值(id值)在0~500万的时候，数据就会
在第一台服务器存储，在500~1000万的时候，数据就会在第二台服务器存储，...。如果我们需要数据均匀分散的存储在三台服务器上，
怎么办呢，只需要把rule分片规则设置为"mod-long"即可

启动mycat服务(注意mycat启动之后，会占用端口号8066，我们只要访问8066端口对应的服务即可)
切换到mycat的安装目录，执行如下指令:
#停止
cd /usr/local/mycat && bin/mycat stop
#启动
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log

【具体过程如下:】

1. 在第一台服务器的MyCat需要进行如下配置。详细见'模板'文件(我会写好发出来)
cd /usr/local/mycat/conf && vim schema.xml

2. 在第一台服务器的MyCat需要进行如下配置。详细见'模板'文件(我会写好发出来)
cd /usr/local/mycat/conf && vim server.xml

3. 在第一台服务器重新启动mycat
cd /usr/local/mycat && bin/mycat stop
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log

4. 在第一、二、三台服务器创建shuiping_fenbiao数据库

5. 在第一台服务器上登录mycat
mysql -h 192.168.127.138 -P 8066 -u root -p123456

6. 查看mycat里面有哪些数据库
show databases;#有SHOPPING、SHUIPING_FENBIAO数据库(就是上面第1步那里配置的schema.xml文件我们写的)

7. 查看SHUIPING_FENBIAO数据库有哪些表
use SHUIPING_FENBIAO;#SHUIPING_FENBIAO数据库才是我们这节课的重点，我们要在SHUIPING_FENBIAO数据库实现水平分表
show tables;#里面有tb_log逻辑表表。目前tb_log表是空表，我们还没有导入表结构、表数据进去

8. 手动把tb_log的表结构、表数据命令粘贴到终端。命令如下
CREATE TABLE tb_log (
  id bigint(20) NOT NULL COMMENT 'ID',
  model_name varchar(200) DEFAULT NULL COMMENT '模块名',
  model_value varchar(200) DEFAULT NULL COMMENT '模块值',
  return_value varchar(200) DEFAULT NULL COMMENT '返回值',
  return_class varchar(200) DEFAULT NULL COMMENT '返回值类型',
  operate_user varchar(20) DEFAULT NULL COMMENT '操作用户',
  operate_time varchar(20) DEFAULT NULL COMMENT '操作时间',
  param_and_value varchar(500) DEFAULT NULL COMMENT '请求参数名及参数值',
  operate_class varchar(200) DEFAULT NULL COMMENT '操作类',
  operate_method varchar(200) DEFAULT NULL COMMENT '操作方法',
  cost_time bigint(20) DEFAULT NULL COMMENT '执行方法耗时, 单位 ms',
  source int(1) DEFAULT NULL COMMENT '来源 : 1 PC , 2 Android , 3 IOS',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO tb_log (id, model_name, model_value, return_value, return_class, operate_user, operate_time, param_and_value, operate_class, operate_method, cost_time，source) VALUES('1','user','insert','success','java.lang.String','10001','2022-01-06 18:12:28','{\"age\":\"20\",\"name\":\"Tom\",\"gender\":\"1\"}','cn.itcast.controller.UserController','insert','10',1);
INSERT INTO tb_log (id, model_name, model_value, return_value, return_class, operate_user, operate_time, param_and_value, operate_class, operate_method, cost_time，source) VALUES('2','user','insert','success','java.lang.String','10001','2022-01-06 18:12:27','{\"age\":\"20\",\"name\":\"Tom\",\"gender\":\"1\"}','cn.itcast.controller.UserController','insert','23',1);
INSERT INTO tb_log (id, model_name, model_value, return_value, return_class, operate_user, operate_time, param_and_value, operate_class, operate_method, cost_time，source) VALUES('3','user','update','success','java.lang.String','10001','2022-01-06 18:16:45','{\"age\":\"20\",\"name\":\"Tom\",\"gender\":\"1\"}','cn.itcast.controller.UserController','update','34',1);
INSERT INTO tb_log (id, model_name, model_value, return_value, return_class, operate_user, operate_time, param_and_value, operate_class, operate_method, cost_time，source) VALUES('4','user','update','success','java.lang.String','10001','2022-01-06 18:16:45','{\"age\":\"20\",\"name\":\"Tom\",\"gender\":\"1\"}','cn.itcast.controller.UserController','update','13',2);
INSERT INTO tb_log (id, model_name, model_value, return_value, return_class, operate_user, operate_time, param_and_value, operate_class, operate_method, cost_time，source) VALUES('5','user','insert','success','java.lang.String','10001','2022-01-06 18:30:31','{\"age\":\"200\",\"name\":\"TomCat\",\"gender\":\"0\"}','cn.itcast.controller.UserController','insert','29',3);
INSERT INTO tb_log (id, model_name, model_value, return_value, return_class, operate_user, operate_time, param_and_value, operate_class, operate_method, cost_time，source) VALUES('6','user','find','success','java.lang.String','10001','2022-01-06 18:30:31','{\"age\":\"200\",\"name\":\"TomCat\",\"gender\":\"0\"}','cn.itcast.controller.UserController','find','29',2);

9. 此时去datagrip软件，看我们的第一、二、三台服务器的shuiping_fenbiao数据库
会发现第一台服务器的shuiping_fenbiao表有2条数据
会发现第二台服务器的shuiping_fenbiao表有2条数据
会发现第三台服务器的shuiping_fenbiao表有2条数据
原因: 我们在第1步配置schema.xml文件时的rule分片规则设置为了"mod-long"，表示的就是: 数据均匀分散的存储在三台服务器上*/

-- ------------------------------------------分库分表 分片规则-------------------------------------------------------

/*【第一种分片规则 - 范围分片】-- 只适用于数字类型的字段进行分片

rule = "auto-sharding-long"

根据指定的字段(默认是主键字段)及其配置的范围(默认是500万)与数据节点的对应情况，来决定该数据属于哪一个分片
例如: id值在0~500万，就存储在第一台分片服务器; id值在500万~1000万，就存储在第二台服务器; ...

如何指定是哪个字段
在/usr/local/mycat/conf目录的schema.xml文件找到如下。primaryKey表示根据什么字段(id)来分片。rule表示分片规则(rang-long)。
<schema name="逻辑库名" checkSQLschema="true" sqlMaxLimit="100">
	<table name="逻辑表名" dataNode="分片服务器名1,分片服务器名2,分片服务器名3" primaryKey="id" rule="rang-long"/>
</schema>
底层的是/usr/local/mycat/conf目录的rule.xml文件找到如下。columns表示根据什么字段(id)来分片。algorithm表示分片规则(rang-long)
<tableRule name="auto-sharding-long">
	<rule>
		<columns>id</columns>
		<algorithm>rang-long</algorithm>
	</rule>
</tableRule>

如何指定范围分片的配置范围
在/usr/local/mycat/conf目录的autopartition-long.txt文件找到如下。M表示万，K表示千，即可修改范围
0-500M=0
500M-1000M=1
1000M-1500M=2

####################################################################################################

【第二种分片规则 - 取模分片】-- 只适用于数字类型的字段进行分片

rule = "mod-long"

根据指定的字段值与节点数量进行求模运算，根据运算结果，来决定该数据属于哪一个分片
例如: id值有0~7，也就是有5条数据。共有3台分片节点服务器。怎么判断哪个id值的数据会存到哪个节点服务器，如下
id为1的数据会存到第二台服务器，原因:1%3=1
id为2的数据会存到第三台服务器，原因:2%3=2
id为3的数据会存到第一台服务器，原因:3%3=0
id为4的数据会存到第二台服务器，原因:4%3=1
id为5的数据会存到第三台服务器，原因:5%3=2
id为6的数据会存到第一台服务器，原因:6%3=0
id为7的数据会存到第二台服务器，原因:7%3=1

如何指定是哪个字段
在/usr/local/mycat/conf目录的schema.xml文件找到如下。primaryKey表示根据什么字段(id)来分片。rule表示分片规则(mod-long)。
<schema name="逻辑库名" checkSQLschema="true" sqlMaxLimit="100">
	<table name="逻辑表名" dataNode="分片服务器名1,分片服务器名2,分片服务器名3" primaryKey="id" rule="mod-long"/>
</schema>
底层的是/usr/local/mycat/conf目录的rule.xml文件找到如下。columns表示根据什么字段(id)来分片。algorithm表示分片规则(mod-long)
<tableRule name="mod-long">
	<rule>
		<columns>id</columns>
		<algorithm>mod-long</algorithm>
	</rule>
</tableRule>

如何指定求模的节点数量
在/usr/local/mycat/conf目录的rule.xml文件找到如下。修改property的数量即可
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
	<property name="count">3</property>
</function>

####################################################################################################

【第三种分片规则 - 一致性hash】-- 适用于任何类型的字段进行分片

rule = "sharding-by-murmur"

根据指定字段的hash值来进行分片。所谓一致性哈希，指的是相同的哈希因子计算值总是被划分到相同的分区表中，不会因为分区节点的
增加而改变原来数据的分区位置。简单说就把id值是一样的、或者hash函数是一样的，那么数据就会被划分到同一台分片服务器，即使以后
增加了或减少了分片服务器，我们的数据是不会改变存储位置的(原来在哪个分片服务器，就在哪个分片服务器)

如何指定是哪个字段
在/usr/local/mycat/conf目录的rule.xml文件找到如下。columns表示根据什么字段(id)来分片。algorithm表示分片规则(murmur)
<tableRule name="sharding-by-murmur">
	<rule>
		<columns>id</columns>
		<algorithm>murmur</algorithm>
	</rule>
</tableRule>

如何指定hash分片
在/usr/local/mycat/conf目录的rule.xml文件找到如下
<function name="murmur"
	class="io.mycat.route.function.PartitionByMurmurHash">
	<property name="seed">0</property> #默认是0
	<property name="count">3</property> #例如有三台分片服务器，那么就指定为3，表示数据会存到3台服务器
	<property name="virtualBucketTimes">160</property>
</function>

具体演示过程
1. 配置/usr/local/mycat/conf目录的schema.xml文件(我会打包放在模板文件里面)
2. 配置/usr/local/mycat/conf目录的rule.xml、server.xml文件(我会打包放在模板文件里面)
3. 在第一台服务器启动mycat
#停止
cd /usr/local/mycat && bin/mycat stop
#启动
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log
4. 在第一、二、三台服务器创建guding数据库
5. 在第一台服务器登录进mycat，并导入表结构和表数据
mysql -h 192.168.127.138 -P 8066 -u root -p123456
use HASH;
create table tb_order(
    id  varchar(100) not null primary key,
    money   int null,
    content varchar(200) null
);
INSERT INTO tb_order (id, money, content) VALUES ('b92fdaaf-6fc4-11ec-b831-482ae33c4a2d', 10, 'b92fdaf8-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b93482b6-6fc4-11ec-b831-482ae33c4a2d', 20, 'b93482d5-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b937e246-6fc4-11ec-b831-482ae33c4a2d', 50, 'b937e25d-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b93be2dd-6fc4-11ec-b831-482ae33c4a2d', 100, 'b93be2f9-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b93f2d68-6fc4-11ec-b831-482ae33c4a2d', 130, 'b93f2d7d-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b9451b98-6fc4-11ec-b831-482ae33c4a2d', 30, 'b9451bcc-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b9488ec1-6fc4-11ec-b831-482ae33c4a2d', 560, 'b9488edb-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b94be6e6-6fc4-11ec-b831-482ae33c4a2d', 10, 'b94be6ff-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b94ee10d-6fc4-11ec-b831-482ae33c4a2d', 123, 'b94ee12c-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b952492a-6fc4-11ec-b831-482ae33c4a2d', 145, 'b9524945-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b95553ac-6fc4-11ec-b831-482ae33c4a2d', 543, 'b95553c8-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b9581cdd-6fc4-11ec-b831-482ae33c4a2d', 17, 'b9581cfa-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b95afc0f-6fc4-11ec-b831-482ae33c4a2d', 18, 'b95afc2a-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b95daa99-6fc4-11ec-b831-482ae33c4a2d', 134, 'b95daab2-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b9667e3c-6fc4-11ec-b831-482ae33c4a2d', 156, 'b9667e60-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b96ab489-6fc4-11ec-b831-482ae33c4a2d', 175, 'b96ab4a5-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b96e2942-6fc4-11ec-b831-482ae33c4a2d', 180, 'b96e295b-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b97092ec-6fc4-11ec-b831-482ae33c4a2d', 123, 'b9709306-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b973727a-6fc4-11ec-b831-482ae33c4a2d', 230, 'b9737293-6fc4-11ec-b831-482ae33c4a2d');
INSERT INTO tb_order (id, money, content) VALUES ('b978840f-6fc4-11ec-b831-482ae33c4a2d', 560, 'b978843c-6fc4-11ec-b831-482ae33c4a2d');

6. 此时去datagrip软件，看我们的第一、二、三台服务器的hash数据库
会发现第一台服务器的tb_order表有相应数据
会发现第二台服务器的tb_order表有相应数据
会发现第三台服务器的tb_order表有相应数据
这些数据是按照一致性hash的规则，把数据分配到三台服务器


####################################################################################################

【第四种分片规则 - 枚举分片】-- 适用于按照省份、性别、状态拆分数据等业务

rule = "sharding-by-intfile-xxxx"

通过在配置文件中配置可能的枚举值，指定数据分布到不同数据节点服务器上

如何指定枚举值
在/usr/local/mycat/conf目录的rule.xml文件找到如下
<tableRule name="sharding-by-intfile">
	<rule>
		<columns>sharding_id</columns>
		<algorithm>hash-int</algorithm>
	</rule>
</tableRule>
<tableRule name="sharding-by-intfile-enumstatus">
	<rule>
		<columns>status</columns>
		<algorithm>hash-int</algorithm>
	</rule>
</tableRule>
底层的是/usr/local/mycat/conf目录的rule.xml文件找到如下
<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
	<property name="defaultNode">2</property> #2表示默认节点，作用当数据都不满足我们的枚举值，那数据就会存到第2台节点服务器
	<property name="mapFile">partition-hash-int.txt</property> #partition-hash-int.txt表示映射文件
</function>

如何修改映射文件，即修改枚举值对应的分片节点
在/usr/local/mycat/conf目录的partition-hash-int.txt文件找到如下。语法: 枚举值=哪台分片服务器
1=0
2=1
3=2
表示如果数据的枚举值为1，那么就存储在第一台分片节点服务器; 枚举值为2就存储在第二台分片服务器; 枚举值为5就存储在第二台节点服
务器(因为上面我们指定了默认节点为2)

tip: 怎么指定枚举值以及对应的节点很简单，就看我们要导入什么数据，比如我们要导入一张tb_user表，表里面有一个字段是status，值要么
是0、要么是1、要么是3，那我们就可以把status字段的三个不同的只当做是枚举值，当某条数据的status为0，该数据就会存到第一台服务器，
当某条数据的status为1，该数据就会存到第二台服务器，当某条数据的status为2，该数据就会存到第三台服务器。

具体演示过程
1. 配置/usr/local/mycat/conf目录的schema.xml文件(我会打包放在模板文件里面)
2. 配置/usr/local/mycat/conf目录的rule.xml、server.xml、partition-hash-int.txt.txt文件(我会打包放在模板文件里面)
3. 在第一台服务器启动mycat
#停止
cd /usr/local/mycat && bin/mycat stop
#启动
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log
4. 在第一、二、三台服务器创建meiju数据库
5. 在第一台服务器登录进mycat，并导入表结构和表数据
mysql -h 192.168.127.138 -P 8066 -u root -p123456
use MEIJU;
CREATE TABLE tb_user (
  id bigint(20) NOT NULL COMMENT 'ID',
  username varchar(200) DEFAULT NULL COMMENT '姓名',
  status int(2) DEFAULT '1' COMMENT '1: 未启用, 2: 已启用, 3: 已关闭',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
insert into tb_user (id,username ,status) values(1,'Tom',1);
insert into tb_user (id,username ,status) values(2,'Cat',2);
insert into tb_user (id,username ,status) values(3,'Rose',3);
insert into tb_user (id,username ,status) values(4,'Coco',2);
insert into tb_user (id,username ,status) values(5,'Lily',1);
insert into tb_user (id,username ,status) values(6,'Tom',1);
insert into tb_user (id,username ,status) values(7,'Cat',2);
insert into tb_user (id,username ,status) values(8,'Rose',3);
insert into tb_user (id,username ,status) values(9,'Coco',2);
insert into tb_user (id,username ,status) values(10,'Lily',1);
insert into tb_user (id,username ,status) values(11,'Lily2',5);

6. 此时去datagrip软件，看我们的第一、二、三台服务器的meiju数据库
会发现第一台服务器的tb_order表有相应数据
会发现第二台服务器的tb_order表有相应数据
会发现第三台服务器的tb_order表有相应数据
这些数据是按照枚举的规则，把数据分配到三台服务器

####################################################################################################

【第五种分片规则 - 应用指定算法】

rule = "sharding-by-substring"

运行阶段由应用自主决定路由到哪个分片，直接根据字符字串(必须是数字)计算分片号。例如指定的字符串是0，该数据就会存储到
第一台服务器上，指定的字符串是1，该数据就会存储到第二台服务器上，指定的字符串是2，该数据就会存储到第三台服务器上

在/usr/local/mycat/conf目录的rule.xml文件添加如下
<tableRule name="sharding-by-substring">
	<rule>
		<columns>id</columns>
		<algorithm>sharding-by-substring</algorithm>
	</rule>
</tableRule>
<function name="sharding-by-substring" class="io.mycat.route.function.PartitionDirectBySubString">
	<!-- 开始索引 -->
	<property name="startIndex">0</property>
	<!-- 截取长度 -->
	<property name="size">2</property>
 	<!-- 分片数量 -->
	<property name="partitionCount">3</property>
	<!-- 默认分片，01开头的数据会放到第一台分片服务器，02会放到第二台，03会放到第三台，其他会放到第一台服务器-->
	<property name="defaultPartition">0</property>
</function>

具体演示过程
1. 配置/usr/local/mycat/conf目录的schema.xml文件(我会打包放在模板文件里面)
2. 配置/usr/local/mycat/conf目录的rule.xml、server.xm文件(我会打包放在模板文件里面)
3. 在第一台服务器启动mycat
#停止
cd /usr/local/mycat && bin/mycat stop
#启动
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log
4. 在第一、二、三台服务器创建建zhiding数据库
5. 在第一台服务器登录进mycat，并导入表结构和表数据
mysql -h 192.168.127.138 -P 8066 -u root -p123456
use ZHIDING;
CREATE TABLE tb_app (
  id varchar(10) NOT NULL COMMENT 'ID',
  name varchar(200) DEFAULT NULL COMMENT '名称',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
insert into tb_app (id,name) values('0000001','Testx00001');
insert into tb_app (id,name) values('0100001','Test100001');
insert into tb_app (id,name) values('0100002','Test200001');
insert into tb_app (id,name) values('0200001','Test300001');
insert into tb_app (id,name) values('0200002','TesT400001');
insert into tb_app (id,name) values('0400002','TesT900001');

6. 此时去datagrip软件，看我们的第一、二、三台服务器的meiju数据库
会发现第一台服务器的tb_app表有相应数据
会发现第二台服务器的tb_app表有相应数据
会发现第三台服务器的tb_app表有相应数据
这些数据是按照应用指定算法的规则，把数据分配到三台服务器

####################################################################################################

【第六种分片规则 - 固定hash算法】

rule = "sharding-by-long-hash"

该算法类似于十进制的求模运算，但是为二进制的操作。例如，取id值的二进制(十位)与1111111111进行与运算。
最后的与运算结果一定在0000000000~11111111111，转换成10进制就是0~1024
我们可以把结果为0~255范围的数据放到第一台服务器，256~511放到第二台服务器，512~1023放到第三台服务器，
超过1024就会存储到第一台服务器

特点:
1. 如果是求模，连续的值，分别分配到各个不同的分片; 但是此算法会将连续的值可能分配到相同的分片，降低了事务处理的难度
2. 可以均匀分配，也可以非均匀分配
3. 分片字段(默认是id字段)必须为数字类型

在/usr/local/mycat/conf目录的rule.xml文件找到并修改为如下
<function name="sharding-by-long-hash" class="io.mycat.route.function.PartitionByLong">
	<property name="partitionCount">2,1</property>
	<property name="partitionLength">256,512</property>
</function>
在/usr/local/mycat/conf目录的rule.xml文件添加如下
<tableRule name="sharding-by-long-hash">
	<rule>
		<columns>id</columns>
		<algorithm>sharding-by-long-hash</algorithm>
	</rule>
</tableRule>

具体演示过程
1. 配置/usr/local/mycat/conf目录的schema.xml文件(我会打包放在模板文件里面)
2. 配置/usr/local/mycat/conf目录的rule.xml、server.xm文件(我会打包放在模板文件里面)
3. 在第一台服务器启动mycat
#停止
cd /usr/local/mycat && bin/mycat stop
#启动
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log
4. 在第一、二、三台服务器创建建guding_hash数据库
5. 在第一台服务器登录进mycat，并导入表结构和表数据
mysql -h 192.168.127.138 -P 8066 -u root -p123456
use GUDING_HASH;
CREATE TABLE tb_longhash (
  id int(11) NOT NULL COMMENT 'ID',
  name varchar(200) DEFAULT NULL COMMENT '名称',
  firstChar char(1)  COMMENT '首字母',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
insert into tb_longhash (id,name,firstChar) values(1,'七匹狼','Q');
insert into tb_longhash (id,name,firstChar) values(2,'八匹狼','B');
insert into tb_longhash (id,name,firstChar) values(3,'九匹狼','J');
insert into tb_longhash (id,name,firstChar) values(4,'十匹狼','S');
insert into tb_longhash (id,name,firstChar) values(5,'六匹狼','L');
insert into tb_longhash (id,name,firstChar) values(6,'五匹狼','W');
insert into tb_longhash (id,name,firstChar) values(7,'四匹狼','S');
insert into tb_longhash (id,name,firstChar) values(8,'三匹狼','S');
insert into tb_longhash (id,name,firstChar) values(9,'两匹狼','L');
insert into tb_longhash (id,name,firstChar) values(269,'两匹狼2','L');
insert into tb_longhash (id,name,firstChar) values(889,'两匹狼2','L');
insert into tb_longhash (id,name,firstChar) values(1589,'两匹狼2','L');

6. 此时去datagrip软件，看我们的第一、二、三台服务器的guding_hash数据库
会发现第一台服务器的tb_longhash表有相应数据
会发现第二台服务器的tb_longhash表有相应数据
会发现第三台服务器的tb_longhash表有相应数据
这些数据是按照应用固定hash算法的规则，把数据分配到三台服务器

####################################################################################################

【第七种分片规则 - 字符串hash解析】

rule = "sharding-by-stringhash"

截取字符串中的指定位置的子字符串，进行hash算法，算出分片。上一种分片规则是直接用字段值(数字类型的)与1111111111(二进制)进行
与运算，然后根据算出来的结果来决定某个数据会存储到哪台服务器。这节课讲的这种分片规则是截取字段值(字符串类型的)其中的子字符串，
再把截取出来的子字符串先转换为hash值(数字类型的)，然后再跟1111111111(二进制)进行与运算，然后根据算出来的结果来决定某个数据
会存储到哪台服务器

在/usr/local/mycat/conf目录的rule.xml文件添加如下
<tableRule name="sharding-by-stringhash">
	<rule>
		<columns>user_id</columns>
		<algorithm>sharding-by-stringhash</algorithm>
	</rule>
</tableRule>
<function name="sharding-by-stringhash" class="io.mycat.route.function.PartitionByString">
	<property name="partitionLength">512</property> <!-- zero-based -->
	<property name="partitionCount">2</property>
	<property name="hashSlice">0:2</property>
</function>

具体演示过程
1. 配置/usr/local/mycat/conf目录的schema.xml文件(我会打包放在模板文件里面)
2. 配置/usr/local/mycat/conf目录的rule.xml、server.xm文件(我会打包放在模板文件里面)
3. 在第一台服务器启动mycat
#停止
cd /usr/local/mycat && bin/mycat stop
#启动
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log
4. 在第一、二、三台服务器创建建zifuchuan_hash数据库
5. 在第一台服务器登录进mycat，并导入表结构和表数据
mysql -h 192.168.127.138 -P 8066 -u root -p123456
use ZIFUCHUAN_HASH;
create table tb_strhash(
	name varchar(20) primary key,
	content varchar(100)
)engine=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO tb_strhash (name,content) VALUES('T1001', UUID());
INSERT INTO tb_strhash (name,content) VALUES('ROSE', UUID());
INSERT INTO tb_strhash (name,content) VALUES('JERRY', UUID());
INSERT INTO tb_strhash (name,content) VALUES('CRISTINA', UUID());
INSERT INTO tb_strhash (name,content) VALUES('TOMCAT', UUID());

6. 此时去datagrip软件，看我们的第一、二台服务器的zifuchuan_hash数据库
会发现第一台服务器的tb_strhash表有相应数据
会发现第二台服务器的tb_strhash表有相应数据
这些数据是按照应用字符hash解析的规则，把数据分配到两台服务器

####################################################################################################

【第八种分片规则 - 按天分片(也叫按日期分片)】

rule = "sharding-by-date"

指定一段时间，在指定周期，产生的数据就存储到哪个分片服务器。例如0~30天，周期10，也就是0~10天产生的数据会存储放到第一台
服务器，10~20天产生的数据会存储在第二台服务器，20~30天产生的数据会存储在第三台服务器。
注意: 例如我们只有三台服务器，有0~30天的数据需要分片存储，那周期必须为10，必须要刚好分完。否则报错
在/usr/local/mycat/conf目录的rule.xml文件添加如下
<tableRule name="sharding-by-date">
	<rule>
		<columns>create_time</columns>
		<algorithm>sharding-by-date</algorithm>
	</rule>
</tableRule>
<function name="sharding-by-date" class="io.mycat.route.function.PartitionByDate">
	<property name="dateFormat">yyyy-MM-dd</property>
	<property name="sBeginDate">2023-02-01</property>
	<property name="sEndDate">2023-02-30</property>
            <property name="sPartionDay">10</property>
</function>

具体演示过程
1. 配置/usr/local/mycat/conf目录的schema.xml文件(我会打包放在模板文件里面)
2. 配置/usr/local/mycat/conf目录的rule.xml、server.xm文件(我会打包放在模板文件里面)
3. 在第一台服务器启动mycat
#停止
cd /usr/local/mycat && bin/mycat stop
#启动
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log
4. 在第一、二、三台服务器创建建date_fenpian数据库
5. 在第一台服务器登录进mycat，并导入表结构和表数据
mysql -h 192.168.127.138 -P 8066 -u root -p123456
use DATE_FENPIAN;
create table tb_datepart(
    id   bigint  not null comment 'ID'  primary key,
    name varchar(100) null comment '姓名',
    create_time date  null
);
insert into tb_datepart(id,name ,create_time) values(1,'Tom','2023-02-01');
insert into tb_datepart(id,name ,create_time) values(2,'Cat','2023-02-10');
insert into tb_datepart(id,name ,create_time) values(3,'Rose','2023-02-11');
insert into tb_datepart(id,name ,create_time) values(4,'Coco','2023-02-20');
insert into tb_datepart(id,name ,create_time) values(5,'Rose2','2023-02-21');
insert into tb_datepart(id,name ,create_time) values(6,'Coco2','2023-02-28');

注意数据必须要在这个范围内，如果插入3月的数据就会报错

6. 此时去datagrip软件，看我们的第一、二、三台服务器的date_fenpian数据库
会发现第一台服务器的tb_datepart表有相应数据
会发现第二台服务器的tb_datepart表有相应数据
这些数据是按照按天分配的规则，把数据分配到三台服务器

####################################################################################################

【第九种分片规则 - 自然月】

rule = "sharding-by-month"

使用场景为按照月份来分片，每个自然月为一个分片。
例如1月的数据在第一台服务器存储，第2月在第二台，第3月在第三台，第4月在第一台，第5月在第二台，....，相当于前面的取模规则
注意:例如02-01 ~ 04-30，其中共三个自然月，那我们必须要有三台分片服务器，不然报错

在/usr/local/mycat/conf目录的rule.xml文件找到并修改为如下
<function name="partbymonth" class="io.mycat.route.function.PartitionByMonth">
	<property name="dateFormat">yyyy-MM-dd</property>
	<!-- 2月到5月，中间有3个自然月，所以会有三个分片。例如2月产生的数据会存储在第一台分片服务器，3月在第二台，4月在第三台 -->
	<property name="sBeginDate">2023-02-01</property>
	<property name="sEndDate">2023-04-30</property><!-- 4月只有30天，写成31会报错 -->
</function>
<tableRule name="sharding-by-month">
	<rule>
		<!-- 根据create_time字段来分片 -->
		<columns>create_time</columns>
		<algorithm>partbymonth</algorithm>
	</rule>
</tableRule>

具体演示过程
1. 配置/usr/local/mycat/conf目录的schema.xml文件(我会打包放在模板文件里面)
2. 配置/usr/local/mycat/conf目录的rule.xml、server.xm文件(我会打包放在模板文件里面)
3. 在第一台服务器启动mycat
#停止
cd /usr/local/mycat && bin/mycat stop
#启动
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log
4. 在第一、二、三台服务器创建建month_fenpian数据库
5. 在第一台服务器登录进mycat，并导入表结构和表数据
mysql -h 192.168.127.138 -P 8066 -u root -p123456
use MONTH_FENPIAN;
create table tb_monthpart(
    id   bigint  not null comment 'ID'  primary key,
    name varchar(100) null comment '姓名',
    create_time date  null
);
insert into tb_monthpart(id,name ,create_time) values(1,'Tom','2023-02-01');
insert into tb_monthpart(id,name ,create_time) values(2,'Cat','2023-02-10');
insert into tb_monthpart(id,name ,create_time) values(3,'Rose','2023-02-26');
insert into tb_monthpart(id,name ,create_time) values(4,'Coco','2023-03-20');
insert into tb_monthpart(id,name ,create_time) values(5,'Rose2','2023-03-25');
insert into tb_monthpart(id,name ,create_time) values(6,'Coco2','2023-03-10');
insert into tb_monthpart(id,name ,create_time) values(7,'Coco3','2023-04-21');
insert into tb_monthpart(id,name ,create_time) values(8,'Coco4','2023-04-10');
insert into tb_monthpart(id,name ,create_time) values(9,'Coco5','2023-04-30');
insert into tb_monthpart(id,name ,create_time) values(10,'CocoA','2023-05-10');
insert into tb_monthpart(id,name ,create_time) values(11,'CocoB','2023-06-10');
insert into tb_monthpart(id,name ,create_time) values(12,'CocoC','2023-07-10');

注意，我们虽然设置的是2~4月，但是不在这个范围内的也是可以插入的
例如5月的数据会在第一台服务器，6月的会在第二台服务器，7月的会在第三台服务器，...

注意，我们的范围是2~4月，里面涉及到是三个自然月，所以必须要有三台服务器，不然mycat启动不了，也就是报错

6. 此时去datagrip软件，看我们的第一、二、三台服务器的month_fenpian数据库
会发现第一台服务器的tb_monthpart表有相应数据
会发现第二台服务器的tb_monthpart表有相应数据
这些数据是按照按自然月分配的规则，把数据分配到三台服务器*/

-- ------------------------------------------分库分表 MyCat管理与监控-原理-------------------------------------------

# 客户端 -> '解析SQL' -> '分片分析' -> '路由分析' -> '读写分离分析' -> 'MyCat服务器'
# MyCat服务器 -> '结果合并' -> '聚合处理' -> '排序处理' -> '分页处理' -> 客户端

-- ------------------------------------------分库分表 MyCat管理工具-------------------------------------------------

/*MyCat管理
MyCat默认开通两个端口，可以在server.xml中修改
1. 8066是数据访问端口，即进行DML和DDL操作
2. 9066是数据库管理端口，即MyCat服务管理控制功能，用于管理MyCat的整个集群状态

在第一台服务器，开两个窗口，启动MyCat
#停止
cd /usr/local/mycat && bin/mycat stop
#启动
cd /usr/local/mycat && bin/mycat start
#通过查看mycat日志文件来验证是否启动成功。日志末尾为successfully表示启动成功、Wrapper Stopped表示启动失败
cd /usr/local/mycat && tail -f logs/wrapper.log

在第一台服务器登录MyCat
1. mysql -h 192.168.127.138 -P 8066 -u root -p123456
2. mysql -h 192.168.127.138 -P 9066 -u root -p123456


当我们登录进9066端口的MyCat时，就可以管理MyCat，常用的管理命令如下

命令                          含义
show @@help;                 查看MyCat管理工具帮助文档
show @@version;              查看MyCat的版本
reload @@config;             重新加载MyCat的配置文件，相当于重启MyCat
show @@datasource;           查看MyCat的数据源信息
show @@datanode;             查看MyCat的分片节点关联的数据库
show @@threadpool;           查看MyCat的线程池信息
show @@sql;                  查看8066端口最近执行过的SQL
show @@sql.sum;              查看8066端口执行过的SQL统计*/

-- ------------------------------------------分库分表 MyCat监控-------------------------------------------------------

/*MyCat监控

Mycat-web(Mycat-eye)是对mycat-server提供监控服务，功能不局限与对mycat-server使用。Mycat-web通过JDBC连接对Mycat、MySQL监控，监控
远程服务器(目前仅限于linux系统)的cpu、内存、网络、磁盘。也就是说Mycat-web既可以监控Mycat，也可以监控MySQL

Mycat-eye运行过程中需要依赖zookeeper，因此需要先安装zookeeper

安装
1. Zookeeper软件
2. MyCat-web软件

安装好之后，访问http://你的ip:8082/mycat，例如如下
http://192.168.127.138:8082/mycat

进去浏览器管理后台之后，进行如下操作

【管理MyCat】

点击'Mycat-配置'，点击'mycat服务管理'，点击新增，录入mycat的相关信息
1. Mycat名称: Mycat01
2. IP地址(你MyCat安装在哪台服务器): 192.168.127.138
3. 管理端口: 9066
4. 服务端口: 8066
5. 数据库名称(你MyCat里面的逻辑库，只能输入一个): MEIJU
6. 登录你MyCat的用户名: root
7.  登录你MyCat的密码: 123456
8. 点击保存，点击弹出来的关闭，点击返回列表

使用
1. 点击左侧的mycat日志管理，即可查看我们指定逻辑库的日志信息
2. 点击左侧的MyCat监控，即可查看mycat的监控信息
3. 点击左侧的SQL监控，即可查看mycat里面执行过的SQL语句的监控信息
4. 点击左侧的MyCat监控，点击里面的mycat物理节点，节课查看我们MyCat的所以分片节点服务器
5. 我们主要使用的是左侧的SQL监控，里面的SQL统计，可以显示哪些用户对哪些表进行了读写操作

回到我们的终端，在第一台服务器(192.168.127.138)登录进mycat，对MEIJU数据库执行一些SQL语句，看看会不会被监控到
use MEIJU;
select * from tb_user limit 3;
select * from tb_user where status in(1,3);
select * from tb_user where id < 8;
insert into tb_user (id, username, status) values (12,'李四',2),(13,'王五',2);
update tb_user set username = 'libai' where id = 2;
delete from tb_user where id = 5;

进入http://192.168.127.138:8082/mycat，刷新一下，点击左侧的SQL监控，点击里面的SQL统计*/
