MyCat 作為開源數據庫中間件,提供了豐富的分片算法。其中「應用指定分區」屬於離散分片的一種,允許應用程式在運行時根據業務邏輯顯式決定數據路由到哪個分片。本文詳細記錄該分片規則的配置、建表、數據驗證與路由日誌分析全流程。
<function name="sharding-by-substring-040302"
class="org.opencloudb.route.function.PartitionDirectBySubString">
<property name="startIndex">0</property> <!-- 截取起始位置 -->
<property name="size">1</property> <!-- 截取長度 -->
<property name="partitionCount">8</property> <!-- 總分片數 -->
<property name="defaultPartition">0</property> <!-- 預設分片 -->
</function>
<tablerule name="tr-sharding-substr-mc040302">
<rule>
<columns>CODE</columns> <!-- 分片字段 -->
<algorithm>sharding-by-substring-040302</algorithm>
</rule>
</tablerule>
規則解讀:以 CODE='0-10000020' 為例,startIndex=0, size=1 截取首字符 '0',路由至分片 0(即 dn21);若首字符為 '1' 則路由至分片 1(dn22)。未匹配則走 defaultPartition=0。
在 <table name="ORDER040302" rule="tr-sharding-substr-mc040302"/> 中引用上述 tablerule。
CREATE TABLE ORDER040302(
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
CODE VARCHAR(64),
SN VARCHAR(64),
CREATE_TIME DATETIME
);
-- 首字符 0 → dn21
INSERT INTO ORDER040302(ID,CODE,SN,CREATE_TIME)
VALUES(1,'0-10000020','beijing_03-10000020',NOW());
-- 首字符 1 → dn22
INSERT INTO ORDER040302(ID,CODE,SN,CREATE_TIME)
VALUES(2,'1-10000020','shanghai_10-10000020',NOW());
mysql> EXPLAIN INSERT ... VALUES(1,'0-10000020',...);
+-----------+--------------------------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------------------------+
| dn21 | INSERT ... VALUES(1,'0-10000020',...) |
+-----------+--------------------------------------------------+
mysql> EXPLAIN INSERT ... VALUES(2,'1-10000020',...);
+-----------+--------------------------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------------------------+
| dn22 | INSERT ... VALUES(2,'1-10000020',...) |
+-----------+--------------------------------------------------+
以下為 mycat.log 關鍵節點(以 ID=2 插入為例):
ServerConnection[id=1, schema=TESTDB] INSERT ...route={ 1 -> dn22{INSERT ...} } 直接命中單節點。NonBlockingSession release connection MySQLConnection[id=17, host=10.254.1.11, port=3327, attachment=dn22{...}]PhysicalDatasource release channel ... modifiedSQLExecuted=false整個過程無緩存構建、無多節點廣播,屬於典型的單點直連路由。
mysql> EXPLAIN SELECT * FROM ORDER040302 WHERE CODE='0-10000020';
+-----------+--------------------------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------------------------+
| dn21 | SELECT * FROM ORDER040302 WHERE CODE='0-10000020' LIMIT 100 |
+-----------+--------------------------------------------------+
日誌顯示:SQLRouteCache add cache ... route={ 1 -> dn21{...} }
mysql> EXPLAIN SELECT * FROM ORDER040302 WHERE CODE LIKE '0-1%';
+-----------+--------------------------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------------------------+
| dn21 | SELECT * FROM ORDER040302 WHERE CODE LIKE '0-1%' LIMIT 100 |
| dn22 | SELECT * FROM ORDER040302 WHERE CODE LIKE '0-1%' LIMIT 100 |
+-----------+--------------------------------------------------+
即使數據僅存在 dn21,MyCat 仍廣播至所有分片,因為無法從 LIKE 確定具體分片。
mysql> EXPLAIN SELECT * FROM ORDER040302 WHERE SN='beijing_03-10000020';
+-----------+--------------------------------------------------+
| DATA_NODE | SQL |
+-----------+--------------------------------------------------+
| dn21 | SELECT * FROM ORDER040302 WHERE SN='beijing_03-10000020' LIMIT 100 |
| dn22 | SELECT * FROM ORDER040302 WHERE SN='beijing_03-10000020' LIMIT 100 |
+-----------+--------------------------------------------------+
結論:只有精確匹配分片字段才能享受單點路由優勢,其他場景均退化為全表掃描。
startIndex/size 穩定截取。partitionCount 需與物理節點數一致,擴容需重新規劃映射規則。