schema.xml 作爲 Mycat 中重要的配置文件之一,管理着 Mycat 的邏輯庫、表、分片規則、DataNode 以及 DataSource。弄懂這些配置,是正確使用 Mycat 的前提。
一、<schema> 標籤
schema 標籤用於定義 Mycat 實例中的邏輯庫。Mycat 可以有多個邏輯庫,每個邏輯庫都有自己的相關配置。可以使用 <schema> 來劃分這些不同的邏輯庫,在源碼的映射類爲 io.mycat.config.model.SchemaConfig
類。
<schema name="TESTDB"></schema>
schema 標籤的相關屬性:
屬性名 | 值類型 | 必需 | 默認值 | 說明 |
---|---|---|---|---|
name | string | 是 | 邏輯庫名稱 | |
checkSQLschema | boolean | false | 是否去掉 sql 中的默認邏輯庫名 | |
sqlMaxLimit | int | -1 | sql 的返回結果集的最大行數 | |
dataNode | string | 用於綁定邏輯庫到某個具體的 database 上 | ||
randomDataNode | string |
各屬性的具體說明:
-
checkSQLschema 屬性
當該值設置爲 true 時,如果我們的執行語句是 select * from TESTDB.travel_record,則 Mycat 會把語句寫改爲 select * from travel_record,即表示把 schema 名稱的字符去掉,避免發送到後端數據執行時報如下異常。ERROR 1146 (42S02): Table 'testdb.travelrecord' doesn't exist
不過,即使設置該值爲 true,如果語句所帶的並非是 schema 指定的名稱,例如:select * from db1.travel_record,那麼 Mycat並不會刪除 db1 這個字段,如果沒有定義該庫的話則會報錯,所以,在提供 SQL 語句時,最好是不帶 schema 名稱。
-
sqlMaxLimit 屬性
當該值爲自然數,且被執行的 SQL 語句中不含 limit 關鍵字時,Mycat 會自動加上所對應的值,例如此屬性的值是 100,則執行 select * from travel_record 的返回結果與執行 select * from travel_record limit 100 返回結果相同。如果不設置該值,Mycat 默認會把查詢到的信息全部都展示出來,造成過多的輸出。所以,在正常使用中,還是建議加上一個值,用於減少過多的數據返回。
當然,SQL 語句中也可以顯式的指定 limit 的大小,不受該屬性的約束。
注意:如果運行的 schema 爲非拆分庫,那麼該屬性不會生效。需要手動添加 limit 語句。
-
dataNode 屬性
表示與該邏輯庫默認綁定的數據節點(數據庫實例——database)。所有沒有通過 <table> 標籤綁定到其他數據節點的表都會走該數據節點。這裏注意沒有配置在分片裏面的表無法顯示在查看工具裏,但是可以正常使用。
<table> 標籤
<Table> 定義了 Mycat 中的邏輯表,所有需要拆分的表都需要在這個標籤中定義。如下代碼塊所示,同一個 schema 標籤內可定義個多個邏輯表,但邏輯表的名稱必須唯一,在源碼的映射類爲 io.mycat.config.model.TableConfig
類。
<schema name="TESTDB">
<table name="travel_record" dataNode="dn1,dn2,dn3" rule="auto-sharding-long"></table>
<table name="multipleDn1" dataNode="dn1,dn2,dn3" rule="auto-sharding-long"></table>
</schema>
table 標籤的相關屬性:
屬性名稱 | 值類型 | 必需 | 默認值 | 說明 |
---|---|---|---|---|
name | string | 是 | 邏輯表名稱 | |
nameSuffix | string | 邏輯表名前綴(1.6 版本新特性) | ||
dataNode | string | 是 | 本邏輯表分佈在哪些 dataNode 上 | |
rule | string | 分片規則名稱 | ||
ruleRequired | boolean | false | 是否綁定有分片規則 | |
primaryKey | string | null | 主鍵,用於之後路由分析,以及啓用自增長主鍵 | |
type | string | null | 是否爲global | |
autoIncrement | boolean | false | 是否主鍵自增 | |
subTables | string | |||
needAddLimit | boolean | true | 是否需要加返回結果集限制 |
- name 屬性
邏輯表的名稱,這個名稱就如同在數據庫中執行create table
命令指定的名稱一樣,同一個 schema 標籤中定義的邏輯表名稱必須唯一。 - dataNode 屬性
定義這個邏輯表所屬的 dataNode,該屬性的值需要和 <dataNode> 中 name 屬性的值相對應。如果需要定義的數據節點過多,可以使用如下的方法減少配置:
這裏需要注意的是 database 屬性所指定的真實 database name 需要在後面添加一個$符號,例如上面的例子中,表示需要在真實的 mysql 上建立名稱爲 db0 到 db199 的 database。<table name="travel_record" dataNode="multipleDn$0-99,multipleDn2$100-199" rule="auto-sharding-long"></table> <dataNode name="multipleDn$0-99" dataHost="localhost1" database="db$0-99"></dataNode> <dataNode name="multipleDn2$100-199" dataHost="localhost1" database=" db$100-199"></dataNode>
- rule 屬性
該屬性用於指定邏輯表要使用的分片規則名字,規則名字在 rule.xml 中定義,必須與 <tableRule> 中 name 屬性值對應。 - ruleRequired 屬性
該屬性用於指定表是否綁定分片規則,如果配置爲 true,但沒有配置具體 rule 的話,程序會報錯。 - primaryKey 屬性
邏輯表對應真實表的主鍵。例如:分片的規則是使用非主鍵進行分片的,那麼在使用主鍵查詢的時候,就會發送查詢語句到所有配置的數據節點上。如果使用該屬性配置真實表的主鍵,那麼 Mycat 會緩存主鍵與具體的數據節點信息,再次使用非主鍵進行查詢時,就不會進行廣播式的查詢,就只會接發送語句給具體的數據節點,但是儘管配置該屬性,如果緩存並沒有命中的話,還是會發送語句給具體的數據節點,來獲取數據。 - type 屬性
該屬性定義了邏輯表的類型,目前邏輯表只有“全局表”和“普通表”兩種類型。對應的配置:- 全局表:global。
- 普通表:非 global 即可。
- autoIncrement 屬性
是否自增長主鍵。MySQL 對非自增長主鍵,使用 last_insert_id() 是不會返回結果的,只會返回 0。所以,只有定義了自增長主鍵的表纔可以用 last_insert_id() 返回主鍵值。
Mycat 目前提供了增長主鍵功能,但是如果對應的 MySQL 節點上數據表,沒有定義 auto_increment,那麼在 Mycat 層調用 last_insert_id() 也是不會返回結果的。
由於 insert 操作的時候沒有帶入分片鍵,Mycat 會先取下這個表對應的全局序列,然後賦值給分片鍵。這樣才能正常的插入到數據庫中,最後使用 last_insert_id() 纔會返回插入的分片鍵值。
如果要使用這個功能最好配合使用數據庫模式的全局序列。
使用 autoIncrement=“true” 指定這個表有使用自增長主鍵,這樣 Mycat 纔會不拋出分片鍵找不到的異常。
使用 autoIncrement=“false” 來禁用這個功能,當然你也可以直接刪除掉這個屬性。默認就是禁用的。 - subTables 屬性
目前 1.6 版本開始支持分表,並且 dataNode 在分表條件下只能配置一個,分表條件下不支持各種條件的 join 語句。使用方式是添加 subTables=“t_order$1-2,t_order3” - needAddLimit 屬性
指定表是否需要自動的在每個語句後面加上 limit 限制。由於使用了分庫分表,數據量有時會特別巨大,這時候執行查詢語句,如果恰巧又忘記了加上數量限制的話,那麼將查詢出所有的數據出來。所以,Mycat 就自動的爲我們加上 LIMIT 100。當然,如果語句中有 limit,就不會再次添加了。
<childTable> 標籤
<childTable> 用於定義 E-R 分片的子表。通過標籤上的屬性與父表進行關聯。
<schema name="TESTDB">
<table name="travel_record" dataNode="dn$1-3">
<childTable name="company" joinKey="id" parentKey="parent_id"/>
</table>
</schema>
<childTable> 的相關屬性:
屬性名 | 值類型 | 必需 | 默認值 | 說明 |
---|---|---|---|---|
name | string | 是 | 子表的表名 | |
joinKey | string | 是 | 插入子表的時候會使用這個列的值查找父表存儲的數據節點 | |
parentKey | string | 是 | 與父表建立關聯關係的列名 | |
primaryKey | string | 該表對應的真實主鍵 | ||
needAddLimit | boolean | 是否需要爲 sql 自動添加 limit 關鍵字 | ||
autoIncrement | boolean | false | 是否主鍵自增 |
- parentKey 屬性
屬性指定的值一般爲與父表建立關聯關係的列名稱,程序首先獲取 joinKey 的值,再通過 parentKey 屬性指定的列名產生查詢語句,通過執行該語句得到父表存儲在哪個分片上,從而確定子表存儲的位置。
二、<dataNode> 標籤
<dataNode>定義了 Mycat 中的數據節點,也就是我們通常所說的數據分片。一個 <dataNode> 就是一個獨立的數據分片,在源碼的映射類爲 io.mycat.config.model.DataNodeConfig
類。
<dataNode name="dn1" dataHost="localhost1" database="db1"/>
將名爲 localhost1 節點上數據庫實例爲 db1 的物理庫標記成名爲 dn1 的獨立數據分片。
<dataNode> 的相關屬性:
屬性名 | 值類型 | 必需 | 說明 |
---|---|---|---|
name | string | 是 | 數據節點名稱,須保證唯一 |
dataHost | string | 是 | 該分片節點所屬的節點主機 |
database | string | 是 | 真實的 database 名稱 |
屬性釋義:
- name 屬性
定義數據節點的名字(須保證唯一),我們需要在 <table> 上引用這個名稱,來建立表與分片對應的關係。 - dataHost 屬性
該屬性用於定義該分片屬於哪個數據庫實例,屬性值是引用自 <dataHost> 上定義的 name 屬性。 - database 屬性
該屬性用於定義該分片屬於哪個具體數據庫實例上的具體庫。因爲這裏是用兩個維度來定義分片,就是:實例 + 具體的庫。因爲每個庫上建立的表和表結構是一樣的,所以這樣做就可以輕鬆的對錶進行水平拆分。
三、<dataHost> 標籤
作爲 schema.xml 中最後的一個標籤,該標籤在 Mycat 邏輯庫中也是作爲最底層的標籤存在,直接定義了具體的數據庫實例、讀寫分離配置和心跳語句,在源碼的映射類是 io.mycat.config.model.DataHostConfig
類。
<dataHost name="dn1" balance="0" dbDriver="native" dbType="mysql" maxCon="10" minCon="100">
<heartbeat>select 1 from dual</heartbeat>
<writeHost host="hostM1" url="master1:3306" user="root" password="123456">
<readHost host="hostS1" url="slave1:3306" user="root" password="123456"/>
</writeHost>
</dataHost>
<dataHost> 標籤的相關屬性:
屬性名 | 值類型 | 必需 | 默認值 | 說明 |
---|---|---|---|---|
name | string | 是 | 節點主機的唯一標識,供其他標籤使用 | |
maxCon | int | 是 | 128 | 讀寫連接池的最大連接數 |
minCon | int | 是 | 10 | 讀寫連接池的最小/初始連接數 |
balance | int | 是 | 0 | 負載均衡類型 |
balanceType | int | 0 | 負載均衡策略 | |
dbType | string | 是 | 後端數據庫類型 | |
dbDriver | string | 是 | 連接後端數據庫使用的驅動 | |
writeType | int | 0 | 寫類型 | |
switchType | int | -1 | 切換類型 | |
slaveThreshold | int | -1 | 從庫延遲界限 | |
tempReadHostAvailable | int | 0 | 寫節點宕機時,臨時讀節點是否可用 | |
notSwitch | string | 0 |
屬性釋義:
- balance 屬性
負載均衡類型,目前的取值有 4 中:- balance=“0”,不開啓讀寫分離機制,所有讀操作都發送到當前可用的 writeHost 上。
- balance=“1”,全部的 readHost 與 stand by writeHost 參與 select 語句的負載均衡,簡單地說,當說雙主從模式(M1 -> S1,M2 -> S2,並且 M1 與 M2 互爲主備),正常情況下,M2、S1、S2 都參與 select 語句的負載均衡。
- balance=“2”,所有讀操作都隨機的在 writeHost、readHost 上分發。
- balance=“3”,(1.4+ 版本特性)所有讀請求隨機的分發到 writeHost 對應的 readHost 執行,writeHost 不負擔讀壓力。
- balanceType 屬性
- 0 表示隨機。
- 1 表示加權輪詢。
- 2 表示最少活躍數。
- writeType 屬性
負載均衡類型,目前的取值有 2 種:- writeType=“0”,所有寫操作發送到配置的第一個 writeHost,第一個掛了切到還存活的第二個 writeHost,重新啓動後以切換後的爲準,切換信息記錄在 dnindex.properties 配置文件。
- writeType=“1”,所有寫操作都隨機的發送到配置的 writeHost。(1.5+ 廢棄,不推薦使用)
- switchType 屬性
- -1 表示不自動切換。
- 1 自動切換。
- 2 基於 MySQL 主從同步的狀態決定是否切換。心跳語句爲:show slave status
- 3 基於 MySQL galary cluster 的切換機制(適合集羣)(1.4.1+版本)。心跳語句爲:show status like ‘wsrep%’
- dbType 屬性
指定後端連接的數據庫類型,目前支持二進制的 mysql 協議,還有其他使用 JDBC 連接的數據庫。例如:mongodb、oracle、spark 等。 - dbDriver 屬性
指定連接後端數據庫使用的驅動,目前可選的值有 native 和 JDBC。使用 native 的話,因爲這個值執行的是二進制的 mysql 協議,所以可以使用 mysql 和 maridb。其他類型的數據庫則需要使用 JDBC 驅動來支持。從 1.6 版本開始支持 postgresql 的 native 原始協議。
如果使用 JDBC 的話,需要將符合 JDBC 4 標準的驅動 JAR 包放到 MYCAT\lib 目錄下,並檢查驅動 JAR 包中包括如下目錄結構的文件:META-INF\services\java.sql.Driver。在這個文件內寫上具體的 Driver 類名,例如:com.mysql.jdbc.Driver。 - tempReadHostAvailable 屬性
如果屬性值大於 0 則表示在寫節點宕機時,臨時的讀服務依然可用,即如果配置了這個屬性,<writeHost> 下面的 <readHost> 仍舊可用,默認 0 可配置(0、1)。
<heartbeat> 標籤
這個標籤內指明用於和後端數據庫進行心跳檢查的語句。例如,MySQL 可以使用 select user(),Oracle 可以使用 select 1 from dual 等。
<dataHost name="dn1" balance="0" dbDriver="native" dbType="mysql" maxCon="10" minCon="100">
<heartbeat>select user()</heartbeat>
</dataHost>
Mycat 1.4 版本的主從切換的心跳語句必須是:show slave status
<connectionInitSql> 標籤
當使用 Oracle 數據庫時,需要執行的初始化 SQL 語句就放到這裏面來。例如:
<dataHost name="dn1" balance="0" dbDriver="jdbc" dbType="oracle" maxCon="10" minCon="100">
<heartbeat>select 1 from dual</heartbeat>
<connectionInitSql>alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'</connectionInitSql>
</dataHost>
<writeHost> 標籤、<readHost> 標籤
這兩個標籤都是指定後端數據庫的相關配置給 Mycat,用於實例化後端連接池。唯一不同的是:<writeHost> 指定寫實例、<readHost> 指定讀實例,組合這些讀寫實例來滿足系統的要求。
<dataHost name="dn1" balance="0" dbDriver="native" dbType="mysql" maxCon="10" minCon="100">
<writeHost host="hostM1" url="master1:3306" user="root" password="123456">
<readHost host="hostS1" url="slave1:3306" user="root" password="123456"/>
</writeHost>
</dataHost>
在一個 <dataHost> 內可以定義多個 <writeHost> 和 <readHost>。但是,如果 <writeHost> 指定的後端數據庫宕機,那麼這個 <writeHost> 綁定的所有 <readHost> 都將不可用。另一方面,由於這個 <writeHost> 宕機系統會自動的檢測到,並切換到備用的 <writeHost> 上去。
<writeHost> 和 <readHost> 的屬性相同,這裏就一起介紹。
屬性名 | 值類型 | 必需 | 默認值 | 說明 |
---|---|---|---|---|
host | string | 是 | 用於標識不同實例,一般writeHost使用 M1;readHost 用 S1 | |
url | string | 是 | 後端實例連接地址,如果是使用 native 的 dbDriver,則一般爲 localhost:3306 形式; 在使用 jdbc 時,則可寫爲:jdbc:mysql://localhost:3306 |
|
user | string | 是 | 後端存儲實例需要的用戶名稱 | |
password | string | 是 | 後端存儲實例需要的密碼 | |
weight | string | 0 | 權重。配置在 <readhost> 中作爲讀節點的權重(1.4+ 版本生效) | |
usingDecrypt | string | 0 | 是否對密碼加密 |