我們知道MySQL 數據庫有自己的SQL注解(hint),比如 use index、force index、ignore index 等都是會經常用到的,Mycat 作為一個數據庫中間件,最重要的是 SQL 路由,所以 Mycat 中的注解基本上都是和路由功能相關。
主從路由注解
該注解用於解決MySQL 數據庫的主從同步延遲的問題,由於對於數據庫讀寫分離架構的系統,其 slave 可能會存在一定的復制延遲,在一些業務上不能接受任何延遲的 select 語句就可以使用該注解,強制其在 master 執行,主從路由注解的基本原理是根據注解的值是 master 還是 slave,分別獲取對應的 writeHost 或 readHost 的數據庫連接,來執行 SQL 語句,示例代碼如下:
mysql> /*!mycat:db_type=slave*/select * from tb_sharding_murmur where id= 199
通過查詢日志可以發現,其 hintSQLValue 值為 slave,getRunOnSlave() 為 true,表示路由到了 salve 數據庫,日志如下:
2018-02-14 00:10:32.077 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.route.handler.HintMasterDBHandler.route(HintMasterDBHandler.java:45)) - schema.rrs(): select * from tb_sharding_murmur where id= 199, route={
1 -> vmDB2-tempdb{select * from tb_sharding_murmur where id= 199}
}
2018-02-14 00:10:32.077 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.route.handler.HintMasterDBHandler.route(HintMasterDBHandler.java:48)) - hintSQLValue:::::::::slave
2018-02-14 00:10:32.078 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.route.handler.HintMasterDBHandler.route(HintMasterDBHandler.java:85)) - rrs.getRunOnSlave():true
修改查詢語句,指定從 master 查詢,示例代碼如下:
mysql> /*!mycat:db_type=master*/select * from tb_sharding_murmur where id= 199
通過查詢日志可以發現,其 hintSQLValue 值為 master,getRunOnSlave() 為 false,表示路由到了 salve 數據庫,日志如下:
2018-02-14 00:10:36.538 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.route.handler.HintMasterDBHandler.route(HintMasterDBHandler.java:45)) - schema.rrs(): select * from tb_sharding_murmur where id= 199, route={
1 -> vmDB2-tempdb{select * from tb_sharding_murmur where id= 199}
}
2018-02-14 00:10:36.538 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.route.handler.HintMasterDBHandler.route(HintMasterDBHandler.java:48)) - hintSQLValue:::::::::master
2018-02-14 00:10:36.538 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.route.handler.HintMasterDBHandler.route(HintMasterDBHandler.java:85)) - rrs.getRunOnSlave():false
2018-02-14 00:10:36.538 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.server.NonBlockingSession.execute(NonBlockingSession.java:110)) - ServerConnection [id=1, schema=TEMPDB, host=192.168.2.109, user=mycat,txIsolation=3, autocommit=true, schema=TEMPDB]select * from tb_sharding_murmur where id= 199, route={
1 -> vmDB2-tempdb{select * from tb_sharding_murmur where id= 199}
} rrs
2018-02-14 00:10:36.538 DEBUG [$_NIOREACTOR-0-RW] (io.mycat.backend.mysql.nio.handler.SingleNodeHandler.execute(SingleNodeHandler.java:166)) - rrs.getRunOnSlave() false
SQL 注解
SQL 注解部分是一條SQL語句,稱其為注解SQL;被注解的部分也是一條SQL語句,稱為原始SQL。其原理就是用解析注解SQL的路由結果,來執行被注解的SQL語句。其處理過程是先對注解中的SQL語句進行解析,得到路由結果,然后將被注解的SQL語句在該路由結果表示的數據庫分片上執行,因為注解SQL僅僅用於獲取路由結果,因此一般盡量使其為一條簡單的select 語句,使用分片鍵所在字段即可。而原始的SQL語句可以是 select、delete、update、insert、call 等
-
在指定dataNode中創建存儲過程示例
-
查詢指定的SQL分配到的 dataNode,通過在 SQL 語句前增加 explain 關鍵字,示例如下:
mysql> EXPLAIN select id from tb_sharding_murmur where id = 199;
查詢結果如下:
可以看到其 dataNode 為 vmDB2-tempdb
-
我們通過SQL注解在 vmDB2-tempdb 來創建一個存儲過程,示例如下:
mysql> set autocommit=0; /* 此處必須的,SQL注解的缺陷*/
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter //
mysql> /*!mycat:sql=select id from tb_sharding_murmur where id = 199*/
-> create procedure test_sql_hint_proc()
-> begin
-> select 1;
-> end;
-> //
Query OK, 0 rows affected (0.20 sec)
mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)d
-
我們直連 vmDB2-tempdb 的 MySQL,查詢該數據庫中是否有該存儲過程,示例如下:
mysql> select name from mysql.proc where db='tempdb' and type='PROCEDURE';
查詢結果如下:
-
-
使用 SQL 注解調用指定 dataNode 上的存儲過程
mysql> /*!mycat:sql=select id from tb_sharding_murmur where id = 199*/call test_sql_hint_proc();
執行結果如下:
-
使用SQL注解來支持 insert select 語句
Mycat 是不支持 insert select 語句的,原因是該語句需要在所以分片上執行,顯然對事物不好控制,例如,一個分片執行成功,而另一個分片執行失敗,那么該如何處理,通過SQL注解就可以實現某一個分片的 insert select 語句,示例如下:
-
創建相同表結構的表
mysql> create table tb_sharding_murmur_cp like tb_sharding_murmur;
-
在 mycat 中的 schema.xml 中,增加 tb_sharding_murmur_cp 的表配置,並重新加載配置
<table name="tb_sharding_murmur_cp" dataNode="vmDB1-tempdb,vmDB2-tempdb" primaryKey="id" rule="sharding-by-murmur"/>
-
連接 mycat 執行下面的命令
mysql> set autocommit=0;
Query OK, 0 rows affected (0.02 sec)
mysql> /*!mycat:sql=select id from tb_sharding_murmur where id=199*/insert into tb_sharding_murmur_cp select * from tb_sharding_murmur;
Query OK, 3276 rows affected (0.57 sec)
Records: 3276 Duplicates: 0 Warnings: 0
mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)
-