文章目录
一、概念与图示
schema.xml 是 Mycat对应的物理数据库和数据库表的配置。
schema.xml 配置的几个术语与其关系图示:
二、schema 标签:逻辑数据库
schema 标签用于定义 MyCat 实例中的逻辑库。
MyCat 可以有多个逻辑库,每个逻辑库都有自己的相关配置,可以使用 schema 标签来划分这些不同的逻辑库。
ps:如果不配置 schema 标签,所有的表配置,会属于同一个默认的逻辑库。
<schema name="USERDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1" >
</schema>
<schema name="USERDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn3,dn4">
<table name="eg_user" dataNode="dn5,dn6" rule="auto-sharing-long"></table>
</schema>
2.1、属性列表
属性 | 说明 | 备注 |
---|---|---|
name | 配置逻辑库的名字。通过mycat访问看到的数据库名。 逻辑库名和后端物理库名可能不同,也可能对应后端多个物理库。同一个实例下的物理数据库名称不能重复。同一个schema 的逻辑库名也不能重复 |
|
dataNode | 配置该逻辑库默认的分片。 没有通过 table 标签配置的表,就会走到此处配置的默认的分片上。这里注意没有配置在 table 标签的表,用工具查看是无法显示的,但是可以正常使用。 如果该表有配置 table 标签,当满足条件时,则表会在 table 标签指定的 dataNode上建表。 如果没有配置 dataNode 属性,也没有配置在table标签的表,是无法使用的。 |
注意,dual 表在mycat中,也被视为一个表。 dataNode 值与dataNode 标签的name属性值一致。 |
checkSQLschema | 检查发给Mycat的SQL中是否含有库名。boolean类型。 mysql中可以通过dbName.tableName的方式来访问指定库下的指定表。而mycat中却不推荐这样使用,因为mycat对应的逻辑库可能是在不同物理服务器上的。mycat中dbName.tableName访问的方式可能会出错, 当checkSQLschema=ture时,Mycat来检查SQL中是否有dbName.tableName,如果有,则会删除dbName, 默认false,即不检查。 |
|
sqlMaxLimit | 限制每次查询数据所返回的最大行数。 (server.xml中的limit是整个mycat系统的默认值,这里则是当前逻辑库的默认值,默认先看schema.xml的限制数) |
如果table标签的表,needAddLimit 属性为false,则该表的sql禁止自动加上limit 。 |
2.2、其他注意事项:
2.2.1、dataNode属性
注意,dual表在mycat中,也被视为一个表。
查询:select sysdate() from dual LIMIT 0, 1000
错误代码: 1064
can't find table define in schema DUAL schema:USERDB
另外,通过mycat建表,而该表并没有提前配置table标签,则mycat会找到默认的dataNode,并把表建在默认的dataNode上。如果没有配置默认dataNode,则mycat会报错。
查询:create table test(id varchar(10))
错误代码: 1064
op table not in schema----TEST
而如果该表有配置table标签,则表会分别在table标签指定的dataNode上建表。
2.2.2、checkSQLschema 属性
数据库前缀相关设置。boolean类型。
当前端执行 select *from USERDB.tf_user;
时(表名前指定了mycat 逻辑数据库名 ),两种取值:
-
true:mycat会把语句转换为
select * from tf_user;
-
false:会报错,如下:
查询:SELECT * FROM USERDB.tf_user LIMIT 0, 1000 错误代码: 1064 find no Route:SELECT * FROM USERDB.tf_user LIMIT 0, 1000
2.2.3、sqlMaxLimit 属性
相当于sql的结果集中,加上【 limit N 】。如果sql本身已经指定limit,则以sql指定的为准。
mysql> explain select * from tf_user;
+-----------+---------------------------------+
| DATA_NODE | SQL |
+-----------+---------------------------------+
| dn1 | SELECT * FROM tf_user LIMIT 100 |
| dn2 | SELECT * FROM tf_user LIMIT 100 |
+-----------+---------------------------------+
2 rows in set (0.00 sec)
mysql> explain select * from tf_user limit 50;
+-----------+--------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------+
| dn1 | SELECT * FROM tf_user LIMIT 50 |
| dn2 | SELECT * FROM tf_user LIMIT 50 |
+-----------+--------------------------------+
2 rows in set (0.00 sec)
注意: 如果table标签的表,needAddLimit 属性配置为 false ,则该表的 sql 禁止自动加上 limit 。
2.3、table 标签——逻辑表
table标签为schema标签的子标签。
<schema>
与 <table>
的关系?
Mycat请求过来的表,首先会匹配</table>
标签中的表名,如果匹配成功,而按成 </table>
的分片规则进行,否则,按则</schema>
标签的默认分片配置进行。
table 标签用于定义Mycat的逻辑表,以及逻辑表的分片规则。如:
<schema name="USERDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
<table name="eg_user" dataNode="dn2" rule="auto-sharing-long"></table>
</schema>
<dataNode name="dn1" dataHost="host1" database="mysqlDB" />
<dataNode name="dn2" dataHost="host2" database="mysqlDB" />
属性 | 说明 | 备注 |
---|---|---|
name | 物理数据库中的表名。 逻辑表名 和 相应的物理表名 要一致 在同一个 schema 库中,表名必须唯一,不能重复。 |
|
dataNode | 定义了表数据存储的实际物理节点名称。 该值要与dataNode 标签的name属性值一致。 多个用英文逗号间隔,如:dataNode=“dn1,dn2”。顺序一旦定义就不能修改,否则会出现混乱。 |
|
rule | 指定逻辑表要使用的规则名字, 规则名字在 rule.xml 中定义,必须与 tableRule 标签中 name 属性值一一对应。 |
|
ruleRequired | 指定表是否绑定分片规则。 如果配置为 true,但没有配置具体 rule 的话 ,程序会报错 |
|
primaryKey | 物理表的真实主键。 MyCat会缓存主键(通过primaryKey属性配置)与具体 dataNode 的信息。当分片规则使用非主键进行分片时,那么在使用主键进行查询时,MyCat就会通过缓存先确定记录在哪个 dataNode上,然后再在该 dataNode 上执行查询。 |
|
type | 定义了逻辑表的类型, 目前逻辑表只有 “全局表” 和 ”普通表” 两种类型。对应的配置: 全局表:global。在所有的数据节点中,均有相同的数据。数据冗余到每个数据节点中。 普通表:不指定该值为 global,则为普通表。 |
常见,如字典表 |
autoIncrement | 是否自增。 | |
subTables | 分表配置, mycat1.6之后开始支持,但dataNode 在分表条件下只能配置一个 Join。 |
|
needAddLimit | 指定表是否需要自动的在每个语句后面加上limit限制。默认为true。 由于使用了分库分表,数据量有时候会特别庞大,这时候执行查询语句,所以mycat自动为我们加上了limit 100。 与schema标签的 sqlMaxLimit 配合使用。 |
2、dataNode属性
定义这个逻辑表所属的 dataNode,多个时用英文逗号间隔,如:dataNode=“dn1,dn2”
如果dataNode过多,可以使用如下的方法减少配置:
<schema name="USERDB" dataNode="dn1" checkSQLschema="false" sqlMaxLimit="100">
<table name="travelrecord" dataNode="multipleDn$0-99,multipleDn2$100-199" rule="auto-shardinglong" ></table>
</schema>
<dataNode name="multipleDn" dataHost="localhost1" database="db$0-99" ></dataNode>
<dataNode name="multipleDn2" dataHost="localhost2" database="db$0-99" ></dataNode>
db$0-99 为 mysql 的数据库,即从 db0 至 db99 的数据库(100个)。
3、primaryKey 属性
如果缓存并没有命中的话,还是会发送语句给所有的dataNode。
mysql> explain select * from employee where id=101;
+-----------+-------------------------------------+
| DATA_NODE | SQL |
+-----------+-------------------------------------+
| dn1 | select * from employee where id=101 |
| dn2 | select * from employee where id=101 |
+-----------+-------------------------------------+
2 rows in set (0.00 sec)
mysql> select * from employee where id=101;
+-----+------+-------------+
| id | name | sharding_id |
+-----+------+-------------+
| 101 | A | 10000 |
+-----+------+-------------+
1 row in set (0.01 sec)
mysql> explain select * from employee where id=101;
+-----------+-------------------------------------+
| DATA_NODE | SQL |
+-----------+-------------------------------------+
| dn1 | select * from employee where id=101 |
+-----------+-------------------------------------+
1 row in set (0.00 sec)
关于Mycat的主键缓存,其机制是:
当根据主键查询的SQL语句第一次执行时,Mycat会对其结果进行分析,确定该主键在哪个分片上,并进行该主键到分片ID的缓存。通过连接MyCAT的9066管理端口,执行 show @@cache
,可以显示当前缓存的使用情况。可在sql执行前后的2个时间点执行show @@cache
,通过结果信息中的 LAST_PUT 和 LAST_ACCESS 列,判断相应表的缓存是否有被更新过。
2.3.2、childTable 标签
childTable 标签用于定义 E-R 分片的子表。通过标签上的属性与父表进行关联。
<table name="customer" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile">
<childTable name="orders" primaryKey="ID" joinKey="customer_id" parentKey="id">
<childTable name="order_items" joinKey="order_id" parentKey="id" />
</childTable>
<childTable name="customer_addr" primaryKey="ID" joinKey="customer_id" parentKey="id" />
</table>
属性 | 说明 | 备注 |
---|---|---|
name | 子表的表名 | |
joinKey | 子表的那个字段,和主表关联 | |
parentKey | 主表的关联主键 | |
primaryKey | 主表自身的主键 | |
needAddLimit | 是否加 limit 限制 |
三、dataNode 标签:分片信息,也就是分库相关配置
<schema name="USERDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1" >
<table name="tf_user" primaryKey="USER_ID" autoIncrement="true" dataNode="dn1,dn2" rule="hash-int" />
</schema>
<dataNode name="dn1" dataHost="host1" database="mysqlDB" />
<dataNode name="dn2" dataHost="host2" database="mysqlDB2" />
属性 | 说明 | |
---|---|---|
name | 数据节点的名字,自定义,必须唯一。 与table标签的dataNode属性值对应。 | |
dataHost | 定义该分片所在物理主机的名字。 与 dataHost 标签中的name属性值对应上 。 |
|
database | 定义该分片属于哪个具体数据库实例上的具体库。(即对应mysql中实际的数据库) |
四、dataHost 标签:物理数据库,真正存储数据的数据库
定义后端的数据库主机
<schema name="USERDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1" >
<table name="tf_user" primaryKey="USER_ID" autoIncrement="true" dataNode="dn1,dn2" rule="hash-int" />
</schema>
<dataNode name="dn1" dataHost="host1" database="mysqlDB" />
<dataNode name="dn2" dataHost="host2" database="mysqlDB2" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="0" writeType="0"
dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
</dataHost>
属性 | 说明 | 备注 |
---|---|---|
name | dataHost的名字。 与dataNode标签的dataHost属性值保持一致。 | |
maxCon | 指定每个读写实例连接池的最大连接。 标签内嵌套的writeHost、 readHost 标签都会使用这个属性的值来实例化出连接池的最大连接数。 |
|
minCon | 指定每个读写实例连接池的最小连接,初始化连接池的大小。 | |
balance | 读请求的负载均衡。 (1)balance=“0”,不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上。(默认) (2)balance=“1”,全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备),正常情况下,M2,S1,S2 都参与 select 语句的负载均衡。(双主双从) (3)balance=“2”,所有读操作都随机的在 writeHost、 readhost 上分发。(学习,测试时使用) (4)balance=“3”,所有读请求随机的分发到 wiriterHost 对应的 readhost 执行,writerHost 不负担读压力。(单主单从,单读单写) |
注意: balance=3 只在 V1.4 及其以后版本有,V1.3 没有。 |
writeType | 写请求的负载均衡。 (1)writeType=“0”,所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties 。 (2)writeType=“1”,所有写操作都随机的发送到配置的 writeHost,1.5 以后废弃不推荐。 (3)writeType=“2”,不执行写操作。 |
|
dbType | 指定后端连接的数据库类型。 目前支持二进制的 mysql 协议,还有其他使用 JDBC 连接的数据库。例如:mongodb、 oracle、 spark 等。 |
|
dbDriver | 指定连接后端数据库使用的 Driver,目前可选的值有 native 和 JDBC。 使用native 的话,因为这个值执行的是二进制的 mysql 协议,所以可以使用 mysql 和 maridb。 其他类型的数据库则需要使用 JDBC 驱动来支持。 |
|
switchType | 写数据库如何进行高可用切换。-1 :表示不自动切换 。1 :默认值,自动切换 。2 :基于 MySQL 主从同步的状态决定是否切换。心跳语句为 show slave status 。3 :基于 MySQL galary cluster 的切换机制(适合集群)(1.4.1)。心跳语句为 show status like 'wsrep%' 。 |
|
tempReadHostAvailable | 如果配置了这个属性 writeHost 下面的 readHost 仍旧可用,默认 0 可配置(0、 1)。 |
4.1、heartbeat标签
这个标签内指明用于和后端数据库进行心跳检查的语句。
例如:MYSQL 可以使用 select user()
,Oracle 可以使用 select 1 from dual
等。
4.2、writeHost 标签、 readHost 标签
writeHost、readHost 标签都指定后端数据库的相关配置,用于实例化后端连接池。唯一不同的是,writeHost 指定写实例、readHost 指定读实例。
readHost必须镶嵌在writeHost内的 (一个writeHost里可以定义多个readHost标签)。
在一个 dataHost 内可以定义多个 writeHost 和 readHost。但是,如果 writeHost 指定的后端数据库宕机,那么这个 writeHost 绑定的所有 readHost 都将不可用。
另一方面,由于这个 writeHost 宕机,系统会自动的检测到,并切换到 备用的 writeHost 上去。这两个标签的属性相同,这里就一起介绍。
<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="AAAA" password="AAAA">
<readHost host="hostS2" url="localhost:3307" user="BBBB" password="BBBB" />
</writeHost>
<writeHost host="hostM2" url="localhost:3316" user="CCCC" password="CCCC"/>
<writeHost host="hostS1" url="localhost:3317" user="DDDD" password="DDDD" />
</dataHost>
属性 | 说明 | 备注 |
---|---|---|
host | mysql实例的名称。 一般习惯于 writeHost 我们使用 *Mn( 如:hostM1、myM2…),readHost 我们用 *Sn(如:hostS1、myS2…)。 |
|
url | 物理数据库的连接地址。 如果是使用 native 的 dbDriver,则一般为 ip:port ,也可以是域名。如果使用 JDBC 或其他的 dbDriver,则需要特殊指定。当使用 JDBC 时则可以这么写: jdbc:mysql://localhost:3306/ 。 |
|
user | 数据库的用户名 | |
password | 数据库的密码 | |
weight | 权重。配置在 readhost 中作为读节点的权重(1.4 以后) | |
usingDecrypt | 是否对密码加密 。 默认是 0,否 ,不加密 。 配置-1,同时使用加密程序对密码加密。 |
来源:CSDN
作者:xiaojin21cen
链接:https://blog.csdn.net/xiaojin21cen/article/details/103855544