MyCAT ER分區的驗證
在這裡,構造了兩張表,熟悉Oracle的童鞋都知道,dept(部門表)和emp(員工表),其中dept中的deptno是emp表中dept_no的外鍵。
兩表的建表語句如下:
create table dept(deptno int,dname varchar(10),datanode varchar(10));
create table emp(empno int,dept_no int,datanode varchar(10));
注意:在這裡,最後一列都是datanode,通過插入database()函數可以很直觀的擷取插入的節點名,從而驗證分區的效果。
分別測試以下兩種情況:
1. 父表按照主鍵ID分區,子表的分區欄位與主表ID關聯,配置為ER分區
2. 父表的分區欄位為其他欄位,子表的分區欄位與主表ID關聯,配置為ER分區
首先測試第一種情況,在這裡,dept表作為父表,主鍵是deptno,empno為子表,關聯欄位為dept_no,分區欄位為deptno。
schema.xml中的配置如下:
<table name="dept" primaryKey="deptno" dataNode="dn1,dn2,dn3" rule="sharding-by-intfile"> <childTable name="emp" primaryKey="empno" joinKey="dept_no" parentKey="deptno"> </childTable> </table>
rule.xml中的配置如下:
<tableRule name="sharding-by-intfile"> <rule> <columns>deptno</columns> <algorithm>hash-int</algorithm> </rule> </tableRule>
修改很簡單,就是將原來的id修改為deptno,代表分區的欄位
partition-hash-int.txt的值修改為:
10=0
20=1
驗證如下:
插入父表的值,
datanode為db1,與partition-hash-int.txt中的配置相符
mysql> insert into dept(deptno,dname,datanode) values(10,'ACCOUNTING',database());Query OK, 1 row affected (0.05 sec)mysql> select * from dept;+--------+------------+----------+| deptno | dname | datanode |+--------+------------+----------+| 10 | ACCOUNTING | db1 |+--------+------------+----------+1 row in set (0.12 sec)
日誌輸出資訊如下:
接下來插入子表的值
mysql> insert into emp(empno,dept_no,datanode) values(7788,10,database());Query OK, 1 row affected (0.01 sec)
日誌輸出資訊如下:
關鍵點在於“using parent partion rule directly”。意思是直接使用父的分區規則。如果表本身並沒有指定外鍵約束。
則即便父並沒有相應的主索引值,子表依舊可以插入,只要分區規則中有所定義。
如下所示:
mysql> select * from emp;+-------+---------+----------+| empno | dept_no | datanode |+-------+---------+----------+| 7788 | 10 | db1 |+-------+---------+----------+1 row in set (0.52 sec)mysql> select * from dept;+--------+------------+----------+| deptno | dname | datanode |+--------+------------+----------+| 10 | ACCOUNTING | db1 |+--------+------------+----------+1 row in set (0.13 sec)mysql> insert into emp(empno,dept_no,datanode) values(1234,20,database());Query OK, 1 row affected (0.09 sec)
儘管dept中沒有deptno為20的行。
但emp還是能插入dept_no為20的值
日誌的輸出資訊如下:
所以,對於第一種情況,即父表按照主鍵分區,字表的分區欄位與主表關聯,結論就是,子表進行insert操作時,並不會檢查父表中是否有相關的主鍵(對於子表的外鍵),而是直接根據分區規則進行判斷。
如果分區規則中沒有定義,則會報如下錯誤:
mysql> insert into emp(empno,dept_no,datanode) values(1234,30,database());ERROR 1064 (HY000): can't find datanode for sharding column:DEPTNO val:30
2. 父表的分區欄位為其他欄位,子表的分區欄位與主表ID關聯,配置為ER分區
在這裡,打算用dname作為分區欄位,這樣的話,只需要修改route.xml和partition-hash-int.txt了。
首先,修改rule.xml
<tableRule name="sharding-by-intfile"> <rule> <columns>dname</columns> <algorithm>hash-int</algorithm> </rule> </tableRule>
<function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap"> <property name="mapFile">partition-hash-int.txt</property> <property name="type">1</property> </function>
因dname是字元類型,故將type設定為1。
接著,修改演算法設定檔的值
[root@mysql-server1 conf]# cat partition-hash-int.txt accounting,research=0sales=1operations=2
登入mycat管理連接埠,重新載入設定檔
[root@mysql-server1 conf]# mysql -h192.168.244.145 -utest -ptest -P9066
mysql> reload @@config;Query OK, 1 row affected (0.14 sec)Reload config success
現在進行測試:
mysql> insert into dept(deptno,dname,datanode) values(10,'accounting',database());Query OK, 1 row affected (0.14 sec)mysql> insert into emp(empno,dept_no,datanode) values(1234,10,database());Query OK, 1 row affected (0.29 sec)
日誌的輸出資訊如下:
插入第二個分區中的值
mysql> insert into dept(deptno,dname,datanode) values(20,'sales',database());Query OK, 1 row affected (0.01 sec)mysql> insert into emp(empno,dept_no,datanode) values(1234,20,database());Query OK, 1 row affected (0.41 sec)
日誌的輸出資訊如下:
這次是在兩個分區尋找子表的分區節點
插入第三個分區中的值
mysql> insert into dept(deptno,dname,datanode) values(30,'operations',database());Query OK, 1 row affected (0.00 sec)mysql> insert into emp(empno,dept_no,datanode) values(4567,30,database());Query OK, 1 row affected (0.62 sec)
日誌的輸出資訊如下:
在三個分區中尋找子表的分區節點
總結:在父表的分區欄位為其他欄位,子表的分區欄位與主表ID關聯這種情況下,子表的分區節點是順序尋找的,在該例中,依次從dn1,dn2和dn3中尋找,如果dn1中存在,就直接插入到dn1中,反之,則繼續尋找dn2節點,如果仍不存在,則繼續在dn3節點中尋找。
MyCAT實現MySQL讀寫分離實踐
MyCAT實現MySQL的讀寫分離
本文永久更新連結地址: