本文目录导读:

- 案例一:基础读写分离(一主一从)
- 案例二:垂直分库(业务拆分)
- 案例三:水平分表(分库分表核心)
- 案例四:全局表(字典表冗余)
- 案例五:分片 + 读写分离组合(生产高可用)
- 高级案例:多租户(按租户 ID 分片)
- MyCat 常见注意点与性能陷阱
MyCat 作为经典的数据库中间件,主要用于分库分表、读写分离和多租户隔离,下面提供几个从入门到进阶的真实案例,涵盖核心配置和业务场景。
基础读写分离(一主一从)
场景:单库压力大,读多写少,需要将查询请求分发到从库。
核心配置 schema.xml:
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 逻辑库 -->
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
<!-- 逻辑表:指向 dataNode -->
<table name="user" primaryKey="id" dataNode="dn_user" />
</schema>
<!-- 数据节点:指向具体主机 -->
<dataNode name="dn_user" dataHost="host1" database="user_db" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">
<!-- writeHost 为主库,readHost 为从库 -->
<writeHost host="192.168.1.100" url="192.168.1.100:3306" user="root" password="123456">
<readHost host="192.168.1.101" url="192.168.1.101:3306" user="root" password="123456" />
</writeHost>
</dataHost>
</mycat:schema>
使用效果:
- 执行
INSERT/UPDATE/DELETE时,MyCat 会将 SQL 路由到168.1.100(主库)。 - 执行
SELECT时,MyCat 会根据balance="1"的负载均衡算法,将请求分发到168.1.100和168.1.101,有效降低主库读压力。
垂直分库(业务拆分)
场景:将订单和用户业务拆分为独立的数据库,降低单一数据库的表数量。
核心配置 schema.xml:
<schema name="SHOP" checkSQLschema="false" sqlMaxLimit="100">
<!-- 订单表 -> 订单库 -->
<table name="orders" primaryKey="id" dataNode="dn_order" />
<!-- 用户表 -> 用户库 -->
<table name="users" primaryKey="id" dataNode="dn_user" />
<!-- 关联表:跨库查询(需全局表或ER Join) -->
<table name="order_items" primaryKey="id" dataNode="dn_order,dn_user" rule="sharding-by-intfile" />
</schema>
<dataNode name="dn_order" dataHost="host1" database="order_db" />
<dataNode name="dn_user" dataHost="host2" database="user_db" />
<dataHost name="host1" ...>...</dataHost>
<dataHost name="host2" ...>...</dataHost>
使用效果:
- 订单相关的 SQL 自动发往
host1的order_db。 - 用户相关的 SQL 自动发往
host2的user_db。 - 注意:
SELECT * FROM orders o JOIN users u ON o.user_id = u.id这种跨库关联查询在分库后无法直接执行,通常需要修改为应用层拼接,或者在 MyCat 中配置全局表或ER Join。
水平分表(分库分表核心)
场景:订单表数据量极大(亿级),需要按规则将数据分散到多个 MySQL 实例中。
核心配置 schema.xml:
<schema name="BIGDATA" checkSQLschema="false" sqlMaxLimit="100">
<!-- 水平拆分:订单表按 id 取模 3,数据分布到 3 个数据节点 -->
<table name="order_info" primaryKey="id" dataNode="dn1,dn2,dn3" rule="mod-long" />
</schema>
<dataNode name="dn1" dataHost="host1" database="db1" />
<dataNode name="dn2" dataHost="host2" database="db2" />
<dataNode name="dn3" dataHost="host3" database="db3" />
核心配置 rule.xml:
<!-- 取模分片规则:按 id % 3 分配 -->
<rule name="mod-long">
<columns>id</columns>
<algorithm>mod-long</algorithm>
</rule>
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<property name="count">3</property> <!-- 分片数量 -->
</function>
使用效果:
INSERT INTO order_info (id, name) VALUES (1, 'a')-> 数据写入dn1(因为 1%3=1)。SELECT * FROM order_info WHERE id = 5-> MyCat 直接路由到dn2,查询速度极快。SELECT * FROM order_info WHERE name = 'x'(无分片键)-> MyCat 会广播到所有 3 个节点进行查询(全表扫描),然后合并结果。
全局表(字典表冗余)
场景:分库后,每个分片数据库都有自己的 dict(字典表),避免跨库 JOIN。status_name 表。
核心配置 schema.xml:
<schema name="BIGDATA" checkSQLschema="false" sqlMaxLimit="100">
<table name="order_info" primaryKey="id" dataNode="dn1,dn2,dn3" rule="mod-long" />
<!-- type="global" 表示全局表,数据自动冗余到所有分片 -->
<table name="dict" primaryKey="code" dataNode="dn1,dn2,dn3" type="global" />
</schema>
使用效果:
- 当执行
INSERT INTO dict (code, name) VALUES ('01', '待支付')时,MyCat 会将这条数据同时插入到dn1、dn2、dn3三个库中。 - 查询时,
SELECT * FROM order_info o JOIN dict d ON o.status = d.code无需跨库,因为每个分片库中都有完整的dict表,Join 操作可以直接在本地完成。
分片 + 读写分离组合(生产高可用)
场景:每个分片再有主从同步,实现水平扩展 + 高可用。
核心配置 schema.xml:
<!-- 分片1:使用 host1(主)和 host2(从) -->
<dataNode name="dn1" dataHost="shard1" database="db1" />
<!-- 分片2:使用 host3(主)和 host4(从) -->
<dataNode name="dn2" dataHost="shard2" database="db2" />
<dataNode name="dn3" dataHost="shard3" database="db3" />
<dataHost name="shard1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">
<writeHost host="host1" url="host1:3306" user="root" password="123">
<readHost host="host2" url="host2:3306" user="root" password="123" />
</writeHost>
</dataHost>
<dataHost name="shard2" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native">
<writeHost host="host3" url="host3:3306" user="root" password="123">
<readHost host="host4" url="host4:3306" user="root" password="123" />
</writeHost>
</dataHost>
<!-- shard3 配置类似... -->
使用效果:
- 写入
dn1分片时,只写host1,从库host2自动复制。 - 读取
dn1分片时,可以在host1和host2之间负载均衡。 host1宕机,MyCat 自动将写操作切到host2(如果开启了故障切换),保证高可用。
高级案例:多租户(按租户 ID 分片)
场景:SaaS 系统,不同租户的数据隔离,且租户间数据量差异大。
配置 schema.xml 和 rule.xml:
- 规则:使用
PartitionByString或PartitionByPrefixPattern,根据tenant_id字符串的特征(如首字符或哈希)进行分片。 - 所有 SQL 必须强制携带
tenant_id,否则 MyCat 会广播所有分片,导致性能问题。
<table name="biz_data" primaryKey="id" dataNode="dn1,dn2,dn3,dn4" rule="hash-tenancy" />
<function name="hash-tenancy" class="io.mycat.route.function.PartitionByHash">
<property name="partitionCount">4</property> <!-- 4 个分区 -->
</function>
使用效果:
- 查询时:
WHERE tenant_id = 'T001',MyCat 秒速定位到特定分片。 - 查询时:
WHERE name = 'x'(缺少租户条件),MyCat 需要扫描 4 个分片,性能极差(在这个场景下需要业务层强制限制)。
MyCat 常见注意点与性能陷阱
- 分片键必须出现在 WHERE 中:
SELECT * FROM order WHERE id = 100很快(直接路由);SELECT * FROM order WHERE name = 'xx'会全分片扫描(慢)。 - 跨分片 JOIN 限制:MyCat 支持跨分片 JOIN(如
order和order_item使用ER Join),但如果跨分片且无关联关系,必须使用全局表或应用层处理。 - 分布式事务弱化:MyCat 默认
SET AUTOCOMMIT=0的分布式事务有性能开销(XA 协议),通常建议业务尽量使用本地事务。 - 计数限制:
COUNT(*)在大数据分片下,MyCat 需要聚合所有分片结果,数据量巨大时建议在应用层通过Redis维护计数。
如果需要针对上述某个具体案例提供 具体的 server.xml(账号权限)配置 或 启动/连接测试命令,可以随时告诉我,我可以继续补充。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播