1.schema.xml是干什么用的?
Schema.xml 作為 MyCat 中重要的配置文件之一,管理著 MyCat 的邏輯庫、表、分片規(guī)則、 DataNode 以及 DataSource。弄懂這些配置,是正確使用 MyCat 的前提。
xml結(jié)構(gòu):
<?xml version="1.0?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
</mycat:schema>
1.1schema 標(biāo)簽
? ? ? ?schema 標(biāo)簽用于定義 MyCat 實(shí)例中的邏輯庫,MyCat 可以有多個(gè)邏輯庫,每個(gè)邏輯庫都有自己的相關(guān)配置,可以使用 schema 標(biāo)簽來劃分這些不同的邏輯庫。
ps:如果不配置 schema 標(biāo)簽,所有的表配置,會(huì)屬于同一個(gè)默認(rèn)的邏輯庫。
<schema name="USERDB checkSQLschema="false" sqlMaxLimit="100" datanode="dn3,dn4">
? ? ? ?<table name="eg_user" dataNode="dn1,dn2" rule="auto-sharing-long"></table>
</schema>
<schema name="ORDERDB checkSQLschema="false" sqlMaxLimit="100">
<table name="eg_order" dataNode="dn3,dn4" rule="auto-sharing-long"></table>
</schema>
如上所示的配置就配置了兩個(gè)不同的邏輯庫,邏輯庫的概念和 MYSQL 數(shù)據(jù)庫中 Database 的概念相同,我們?cè)诓樵冞@兩個(gè)不同的邏輯庫中表的時(shí)候需要切換到該邏輯庫下才可以查詢到所需要的表。
1.1.1schema標(biāo)簽屬性詳解

name屬性: 邏輯數(shù)據(jù)庫的名稱
dataNode屬性:
1.3版本,如果schema配置了datanode屬性,則不可以配置分片表
1.4版本后,schema配置了datanode屬性,也可以配置分片表
dataNode指定了邏輯數(shù)據(jù)庫對(duì)應(yīng)物理數(shù)據(jù)庫節(jié)點(diǎn),邏輯庫下的表默認(rèn)都走schema配置的database,但是如1.1中的eg_user表,在table標(biāo)簽中也配置dataNode屬性,則eg_user表不走schema默認(rèn)的dn3,dn4,而是走自己的dn1,dn2
checkSQLschema屬性:
當(dāng)該值設(shè)置為 true 時(shí),如果我們執(zhí)行語句(select * from USERDB.eg_user)則 MyCat 會(huì)把語句修改為(select * from eg_user)。即把表示 schema 的字符去掉,避免發(fā)送到后端數(shù)據(jù)庫執(zhí)行時(shí)報(bào)**(ERROR1146 (42S02): Table ‘ USERDB.eg_user’ doesn’ t exist)。?
不過,即使設(shè)置該值為 true ,如果語句所帶的是并非是 schema 指定的名字,例如:**select * from db1.eg_user;** 那么 MyCat 并不會(huì)刪除 db1 這個(gè)字段,如果沒有定義該庫的話則會(huì)報(bào)錯(cuò),所以在提供 SQL語句的最好是不帶這個(gè)字段
總結(jié): 該字段就是用戶執(zhí)行sql語句時(shí),是否檢查表明的schema,實(shí)際上與SQL語句語法是有重提的,強(qiáng)烈建議將該字段設(shè)置為false;
sqlMaxLimit屬性:
當(dāng)該值設(shè)置為某個(gè)數(shù)值時(shí)。每條執(zhí)行的 SQL 語句,如果沒有加上 limit 語句,MyCat 也會(huì)自動(dòng)的加上所對(duì)應(yīng)的值。例如設(shè)置值為 100,執(zhí)行**select * from USERDB.eg_user;**的效果為和執(zhí)行**select * from USERDB.eg_userlimit 100;**相同。
如果沒有設(shè)置該值的話,MyCat 默認(rèn)會(huì)把查詢到的信息全部都展示出來,造成過多的輸出。所以,在正常使用中,還是建議加上一個(gè)值,用于減少過多的數(shù)據(jù)返回。
當(dāng)然 SQL 語句中也顯式的指定 limit 的大小,不受該屬性的約束。
PS:需要注意的是,如果運(yùn)行的 schema 為非拆分庫的,那么該屬性不會(huì)生效。需要手動(dòng)添加 limit 語句。
1.2table 標(biāo)簽
<table name="eg_user" dataNode="dn1,dn2" rule="auto-sharing-long"></table>

name屬性:
定義邏輯表的表名,這個(gè)名字就如同我在數(shù)據(jù)庫中執(zhí)行 create table 命令指定的名字一樣,同個(gè) schema 標(biāo)簽中定義的名字必須唯一
dataNode 屬性:
定義這個(gè)邏輯表所屬的 dataNode, 該屬性的值需要和 dataNode 標(biāo)簽中 name 屬性的值相互對(duì)應(yīng)。如果需要定義的 dn 過多可以使用如下的方法減少配置
<table name="eg_user" dataNode="multipleDn$0-99,multipleDn2$100-199" rule="auto-shardinglong" >
<!--數(shù)據(jù)節(jié)點(diǎn)配置-->
<dataNode name="multipleDn" dataHost="localhost1" database="db$0-99" >
<dataNode name="multipleDn2" dataHost="localhost1" database=" db$0-199" >
這里需要注意的是 database 屬性所指定的真實(shí) database name 需要在后面添加一個(gè),例如上面的例子中,我需要在真實(shí)的 mysql 上建立名稱為 dbs0 到 dbs99 的 database。
rule 屬性:
該屬性用于指定邏輯表要使用的規(guī)則名字,規(guī)則名字在 rule.xml 中定義,必須與 tableRule 標(biāo)簽中 name 屬性屬性值一一對(duì)應(yīng)。
ruleRequired 屬性:
該屬性用于指定表是否綁定分片規(guī)則,如果配置為 true,但沒有配置具體 rule 的話,程序會(huì)報(bào)錯(cuò)。
primaryKey 屬性:
該邏輯表對(duì)應(yīng)真實(shí)表的主鍵,例如:分片的規(guī)則是使用非主鍵進(jìn)行分片的,那么在使用主鍵查詢的時(shí)候,就會(huì)發(fā)送查詢語句到所有配置的 DN 上,如果使用該屬性配置真實(shí)表的主鍵。那么 MyCat 會(huì)緩存主鍵與具體 DN 的信息,那么再次使用非主鍵進(jìn)行查詢的時(shí)候就不會(huì)進(jìn)行廣播式的查詢,就會(huì)直接發(fā)送語句給具體的 DN,但是盡管配置該屬性,如果緩存并沒有命中的話,還是會(huì)發(fā)送語句給所有的 DN,來獲得數(shù)據(jù)。
type 屬性:
該屬性定義了邏輯表的類型,目前邏輯表只有“全局表”和”普通表”兩種類型。對(duì)應(yīng)的配置:
?全局表:global
?普通表:不指定該值為 globla 的所有表。
autoIncrement 屬性:
mysql 對(duì)非自增長主鍵,使用 last_insert_id()是不會(huì)返回結(jié)果的,只會(huì)返回 0。所以,只有定義了自增長主鍵的表才可以用 last_insert_id()返回主鍵值。
mycat 目前提供了自增長主鍵功能,但是如果對(duì)應(yīng)的 mysql 節(jié)點(diǎn)上數(shù)據(jù)表,沒有定義 auto_increment,那么在 mycat 層調(diào)用 last_insert_id()也是不會(huì)返回結(jié)果的。
由于 insert 操作的時(shí)候沒有帶入分片鍵,mycat 會(huì)先取下這個(gè)表對(duì)應(yīng)的全局序列,然后賦值給分片鍵。這樣才能正常的插入到數(shù)據(jù)庫中,最后使用 last_insert_id()才會(huì)返回插入的分片鍵值。
如果要使用這個(gè)功能最好配合使用數(shù)據(jù)庫模式的全局序列。
使用 autoIncrement=“ true” 指定這個(gè)表有使用自增長主鍵,這樣 mycat 才會(huì)不拋出分片鍵找不到的異常。
使用 autoIncrement=“ false” 來禁用這個(gè)功能,當(dāng)然你也可以直接刪除掉這個(gè)屬性。默認(rèn)就是禁用的。
subTables屬性:
使用方式添加 subTables="t_order$1-2,t_order3"
目前分表 1.6 以后開始支持 并且 dataNode 在分表?xiàng)l件下只能配置一個(gè),分表?xiàng)l件下不支持各種條件的join 語句
needAddLimit 屬性:
指定表是否需要自動(dòng)的在每個(gè)語句后面加上 limit 限制。由于使用了分庫分表,數(shù)據(jù)量有時(shí)會(huì)特別巨大。這時(shí)候執(zhí)行查詢語句,如果恰巧又忘記了加上數(shù)量限制的話。那么查詢所有的數(shù)據(jù)出來,也夠等上一小會(huì)兒的。
所以,mycat 就自動(dòng)的為我們加上 LIMIT 100。當(dāng)然,如果語句中有 limit,就不會(huì)在次添加了。
這個(gè)屬性默認(rèn)為 true,你也可以設(shè)置成 false`禁用掉默認(rèn)行為
1.3childTable 標(biāo)簽
childTable 標(biāo)簽用于定義 E-R 分片的子表。通過標(biāo)簽上的屬性與父表進(jìn)行關(guān)聯(lián)

<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" primaryKey="ID" joinKey="order_id" parentKey="id" />
<childTable name="customer_addr" primaryKey="ID" joinKey="customer_id" parentKey="id" />
</table>
name 屬性:定義子表的表名;
joinKey 屬性:插入子表的時(shí)候會(huì)使用這個(gè)列的值查找父表存儲(chǔ)的數(shù)據(jù)節(jié)點(diǎn)。
parentKey 屬性:
屬性指定的值一般為與父表建立關(guān)聯(lián)關(guān)系的列名。程序首先獲取 joinkey 的值,再通過parentKey屬性指定的列名產(chǎn)生查詢語句,通過執(zhí)行該語句得到父表存儲(chǔ)在哪個(gè)分片上。從而確定子表存儲(chǔ)的位置
primaryKey 屬性:同 table 標(biāo)簽所描述的。
needAddLimit 屬性:同 table 標(biāo)簽所描述的。
1.4dataNode 標(biāo)簽:
<dataNode name="dn1" dataHost="lch3307" database="db1" />
dataNode標(biāo)簽定義了 MyCat 中的數(shù)據(jù)節(jié)點(diǎn),也就是我們通常說所的數(shù)據(jù)分片。一個(gè)dataNode標(biāo)簽就是一個(gè)獨(dú)立的數(shù)據(jù)分片。
例子中所表述的意思為:使用名字為 lch3307 數(shù)據(jù)庫實(shí)例上的 db1 物理數(shù)據(jù)庫,這就組成一個(gè)數(shù)據(jù)分片,最后,我們使用名字 dn1 標(biāo)識(shí)這個(gè)分

name 屬性:
定義數(shù)據(jù)節(jié)點(diǎn)的名字,這個(gè)名字需要是唯一的,我們需要在 table 標(biāo)簽上應(yīng)用這個(gè)名字,來建立表與分片對(duì)應(yīng)的關(guān)系。
dataHost 屬性:
該屬性用于定義該分片屬于哪個(gè)數(shù)據(jù)庫實(shí)例的,屬性值是引用 dataHost 標(biāo)簽上定義的 name 屬性。
database 屬性:
該屬性用于定義該分片屬性哪個(gè)具體數(shù)據(jù)庫實(shí)例上的具體庫,因?yàn)檫@里使用兩個(gè)維度來定義分片,就是:實(shí)例+具體的庫。因?yàn)槊總€(gè)庫上建立的表和表結(jié)構(gòu)是一樣的。所以這樣做就可以輕松的對(duì)表進(jìn)行水平拆分。
1.5dataHost 標(biāo)簽:
作為 Schema.xml 中最后的一個(gè)標(biāo)簽,該標(biāo)簽在 mycat 邏輯庫中也是作為最底層的標(biāo)簽存在,直接定義了具體的數(shù)據(jù)庫實(shí)例、讀寫分離配置和心跳語句?,F(xiàn)在我們就解析下這個(gè)標(biāo)簽。
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="localhost:3306" user="root" password="123456" />
<readHost host="hostS2" url="localhost:3306" user="root" password="123456"/>
</writeHost>
<writeHost host="hostS1" url="localhost:3316" user="root" password="123456" />
</dataHost> ?

name 屬性:唯一標(biāo)識(shí) dataHost 標(biāo)簽,供上層的標(biāo)簽使用。
maxCon 屬性:
指定每個(gè)讀寫實(shí)例連接池的最大連接。也就是說,標(biāo)簽內(nèi)嵌套的 writeHost、 readHost 標(biāo)簽都會(huì)使用這個(gè)屬性的值來實(shí)例化出連接池的最大連接數(shù)。
minCon 屬性:
指定每個(gè)讀寫實(shí)例連接池的最小連接,初始化連接池的大小。
balance 屬性:
負(fù)載均衡類型,目前的取值有 3 種:
1. balance="0", 不開啟讀寫分離機(jī)制,所有讀操作都發(fā)送到當(dāng)前可用的 writeHost 上。
2. balance="1",全部的 readHost 與 stand by writeHost 參與 select 語句的負(fù)載均衡,簡(jiǎn)單的說,當(dāng)雙主雙從模式(M1->S1,M2->S2,并且 M1 與 M2 互為主備),正常情況下,M2,S1,S2 都參與 select 語句的負(fù)載均衡。
3. balance="2",所有讀操作都隨機(jī)的在 writeHost、 readhost 上分發(fā)。
4. balance="3",所有讀請(qǐng)求隨機(jī)的分發(fā)到 wiriterHost 對(duì)應(yīng)的 readhost 執(zhí)行,writerHost 不負(fù)擔(dān)讀壓力,注意 balance=3 只在 1.4 及其以后版本有,1.3 沒有。
writeType 屬性:
負(fù)載均衡類型,目前的取值有 3 種:
1. writeType="0", 所有寫操作發(fā)送到配置的第一個(gè) writeHost,第一個(gè)掛了切到還生存的第二個(gè)
writeHost,重新啟動(dòng)后已切換后的為準(zhǔn),切換記錄在配置文件中:dnindex.properties .
2. writeType="1",所有寫操作都隨機(jī)的發(fā)送到配置的 writeHost,1.5 以后廢棄不推薦。
dbType 屬性:
指定后端連接的數(shù)據(jù)庫類型,目前支持二進(jìn)制的 mysql 協(xié)議,還有其他使用 JDBC 連接的數(shù)據(jù)庫。例如:mongodb、 oracle、 spark 等
dbDriver 屬性:
指定連接后端數(shù)據(jù)庫使用的 Driver,目前可選的值有 native 和 JDBC。使用 native 的話,因?yàn)檫@個(gè)值執(zhí)行的是二進(jìn)制的 mysql 協(xié)議,所以可以使用 mysql 和 maridb。其他類型的數(shù)據(jù)庫則需要使用 JDBC 驅(qū)動(dòng)來支持。
從 1.6 版本開始支持 postgresql 的 native 原始協(xié)議
如果使用 JDBC 的話需要將符合 JDBC 4 標(biāo)準(zhǔn)的驅(qū)動(dòng) JAR 包放到 MYCAT\lib 目錄下,并檢查驅(qū)動(dòng) JAR 包中包括如下目錄結(jié)構(gòu)的文件:META-INF\services\java.sql.Driver。在這個(gè)文件內(nèi)寫上具體的 Driver 類名,例如:com.mysql.jdbc.Driver
switchType 屬性:
-1 表示不自動(dòng)切換
1 默認(rèn)值,自動(dòng)切換
2 基于 MySQL 主從同步的狀態(tài)決定是否切換 ?
? ? ? 心跳語句為 show slave status
3 基于 MySQL galary cluster 的切換機(jī)制(適合集群)(1.4.1)
? ? ? 心跳語句為 show status like ‘wsrep%’.
tempReadHostAvailable 屬性:
如果配置了這個(gè)屬性 writeHost 下面的 readHost 仍舊可用,默認(rèn) 0 可配置(0、 1)
1.6heartbeat 標(biāo)簽
這個(gè)標(biāo)簽內(nèi)指明用于和后端數(shù)據(jù)庫進(jìn)行心跳檢查的語句。例如,MYSQL 可以使用 select user(),Oracle 可以使用 select 1 from dual 等。
這個(gè)標(biāo)簽還有一個(gè) connectionInitSql 屬性,主要是當(dāng)使用 Oracla 數(shù)據(jù)庫時(shí),需要執(zhí)行的初始化 SQL 語句就這個(gè)放到這里面來。例如:alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'
1.7writeHost 標(biāo)簽、 readHost 標(biāo)簽
這兩個(gè)標(biāo)簽都指定后端數(shù)據(jù)庫的相關(guān)配置給 mycat,用于實(shí)例化后端連接池。唯一不同的是,writeHost 指定寫實(shí)例、 readHost 指定讀實(shí)例,組著這些讀寫實(shí)例來滿足系統(tǒng)的要求。
在一個(gè) dataHost 內(nèi)可以定義多個(gè) writeHost 和 readHost。但是,如果 writeHost 指定的后端數(shù)據(jù)庫宕機(jī),那么這個(gè) writeHost 綁定的所有 readHost 都將不可用。另一方面,由于這個(gè) writeHost 宕機(jī)系統(tǒng)會(huì)自動(dòng)的檢測(cè)到,并切換到備用的 writeHost 上去。
這兩個(gè)標(biāo)簽的屬性相同,這里就一起介紹

host 屬性:用于標(biāo)識(shí)不同實(shí)例,一般 writeHost 我們使用*M1,readHost 我們用*S1。
url 屬性:
后端實(shí)例連接地址,如果是使用 native 的 dbDriver,則一般為 address:port 這種形式。用 JDBC 或其他的dbDriver,則需要特殊指定。當(dāng)使用 JDBC 時(shí)則可以這么寫:jdbc:mysql://localhost:3306/。
user 屬性:后端存儲(chǔ)實(shí)例需要的用戶名字
password 屬性:后端存儲(chǔ)實(shí)例需要的密碼
weight 屬性:權(quán)重 配置在 readhost 中作為讀節(jié)點(diǎn)的權(quán)重(1.4 以后)
usingDecrypt 屬性:
是否對(duì)密碼加密默認(rèn) 0 否 如需要開啟配置 1,同時(shí)使用加密程序?qū)γ艽a加密,加密命令為:
執(zhí)行 mycat jar 程序(1.4.1 以后):

本文摘抄于:mycat用戶指南