MyCat + PostgreSQL不支持二級子表分片


一、概述

最近開始學習Mycat,希望用它來實現多種數據庫的分片(Sharding)。但當數據庫為PostgreSQL時,卻發現二級子表始終無法數據分片。經分析Mycat源碼及簡單測試,基本確定Mycat目前版本尚不支持非Mysql的二級子表分片。

按Mycat的解釋,二級子表是指父表的父表不為空的表。

二、問題重現

測試環境為:Mycat 1.6.6.1,邏輯庫為MySql5.7,兩個PostgreSQL 10.6節點。

有三個表組成E-R分片:父表PERSON(主鍵ID),子表CARD(主鍵ID,外鍵PERSON_ID),二級子表CRAD_ITEM(主鍵CID,外鍵CID)。

具體配置見schema.xml: 

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

    <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
        <table name=PERSON" primaryKey="ID" dataNode="dn1,dn2" rule="mod-long">
            <childTable name="CARD" primaryKey="ID" joinKey="PERSON_ID" parentKey="ID">
                <childTable name="CARD_ITEM" joinKey="CID" parentKey="ID" />
            </childTable>
        </table>
    </schema>
    <dataNode name="dn1" dataHost="MyCat_PG_1" database="shard1" />
    <dataNode name="dn2" dataHost="MyCat_PG_2" database="shard2" />
    <dataHost name="MyCat_PG_1" maxCon="1000" minCon="10" balance="0"
              writeType="0" dbType="postgresql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
        <heartbeat>select 1</heartbeat>
        <writeHost host="hostM1" url="jdbc:postgresql://192.168.64.185:5432/shard1" user="shard1" password="123456">
        </writeHost>
    </dataHost>
    <dataHost name="MyCat_PG_2" maxCon="1000" minCon="10" balance="0"
              writeType="0" dbType="postgresql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
        <heartbeat>select 1</heartbeat>
        <writeHost host="hostM2" url="jdbc:postgresql://192.168.64.186:5432/shard2" user="shard2" password="123456">
        </writeHost>
    </dataHost>
</mycat:schema>

測試過程中,向父表PERSON插入數據成功,向子表CARD插入數據也成功,但向二級子表CARD_ITEM插入時報1064錯誤:

mysql> insert into person(id, num) values(5, '5555555');
Query OK, 1 row affected (0.14 sec)
 OK!

mysql> insert into card(id, person_id) values(52, 5);
Query OK, 1 row affected (0.03 sec)
 OK!

mysql> insert into card_item(cid, data) values(52, 'It is 52');
ERROR 1064 (HY000): can't find (root) parent sharding node for sql:insert into card_item(cid, data) values(52, 'It is 52')

三、分析

嘗試過不同配置幾次,始終報這個錯誤。無奈下只好去研究源碼,報錯的地方是io.mycat.route.util.RouterUtil的方法processERChildTable()。

在該方法中,如果要向二級子表中插入記錄,要判別對應的父表(根節點)在哪個dataNode,該語句是:

    final String findRootTBSql = tc.getLocateRTableKeySql().toLowerCase() + joinKeyVal;

跟蹤到該處時,變量findRootTBSql值為:

select `person`.id from `card`,`person` where `person`.id=`card`.person_id and  `card`.id=52;

到這里已基本知道原因,是Mycat將每個表名都以“`”引起來了。這種語法只有mysql支持,而PostgreSQL和Oracle均不支持,所以報錯。

進一步的嘗試是修改該方法,將變量findRootTBSql中的“`”強行去掉,但之后插入二級子表時仍然報錯,查看mycat.log,錯誤信息是:

2018-11-21 10:31:07.509  WARN [BusinessExecutor2] (io.mycat.backend.mysql.nio.handler.FetchStoreNodeOfChildTableHandler.executeException(FetchStoreNodeOfChildTableHandler.java:268)) - executeException   
java.io.UnsupportedEncodingException: unsupported yet

再一直跟蹤,錯誤是在類io.mycat.backend.jdbc.JDBCConnection的query(String)方法拋出的,估計開發人員也認為目前不能解決。代碼如下:

    @Override
    public void query(final String sql) throws UnsupportedEncodingException {
        if(respHandler instanceof ConnectionHeartBeatHandler)
        {
            justForHeartbeat(sql);
        }    else
        {
            throw new UnsupportedEncodingException("unsupported yet ");
        }
    }

只好期待MyCat以后的版本來解決了。

四、結論

目前的MyCat版本(1.6.6.1),在以JDBC連接非MySql數據庫(比如PostgreSQL)時,不支持二級子表的分片。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM