概念html
原理前端
解決問題java
註解規範mysql
/*#mycat:db_type=master*/ select * from travelrecord /*!mycat:db_type=slave*/ select * from travelrecord /**mycat:db_type=master*/ select * from travelrecord
/*!mycat: sql=select 1 from test */ CREATE PROCEDURE `test_proc`() BEGIN END ;
/*!mycat: sql=select 1 from test */create table test2(id int);
/*!mycat: sql=select 1 from test */insert into t_user(id,name) select id,name from t_user2;
a. 事務內的 SQL,默認走寫節點,以註解/*balance*/開頭,則會根據 schema.xml 的 dataHost 標籤屬性的 balance=「1」或「2」去獲取節點 b. 非事務內的 SQL,開啓讀寫分離默認根據 balance=「1」或「2」去獲取,以註解/*balance*/開頭則會走寫節 點解決部分已經開啓讀寫分離,可是須要強一致性數據實時獲取的場景走寫節點 /*balance*/ select a.* from customer a where a.company_id=1;
/*!mycat:catlet=demo.catlets.ShareJoin */ select a.*,b.id, b.name as tit from customer a,company b on a.company_id=b.id;
/*!mycat:db_type=master*/ select * from travelrecord /*!mycat:db_type=slave*/ select * from travelrecord /*#mycat:db_type=master*/ select * from travelrecord
/*#mycat:db_type=slave*/ select * from travelrecord
/*!mycat : schema = test_01 */ sql ;
所謂的兩個階段是指準備 prepare 階段和提交 commit 階段。web
第一階段分爲兩個步驟:sql
一、事務管理器通知參與該事務的各個資源管理器,通知他們開始準備事務。數據庫
二、資源管理器接收到消息後開始準備階段,寫好事務日誌(redo undo)並執行事務,但不提交,而後將是否就緒的消息返回給事務管理器(此時已經將事務的大部分事情作完,之後的操做耗時極小)。編程
第二階段也分爲兩個步驟:後端
一、事務管理器在接受各個消息後,開始分析,若是有任意數據庫失敗,則發送回滾命令,不然發送提交命令。性能優化
二、各個資源管理器接收到命令後,執行(耗時不多),並將提交消息返回給事務管理器。
事務管理器接受消息後,事務結束,應用程序繼續執行。
至於爲何要分兩步執行,一是由於分兩步,就有了事務管理器統一管理的機會;二儘量晚地提交事務,讓事務在提交前儘量地完成全部能完成的工做,這樣,最後的提交階段將是耗時極短,耗時極短意味着操做失敗的可能性也就下降。
在 XA 的分佈式事務處理模型裏面涉及到三個角色 AP(應用程序)、RM(數據庫)、TM(事務管理器)。AP 定義事務的開始和結束,訪問事務內的資源。RM 除了數據庫以外,還能夠是其餘的系統資源,好比文件系統,打印機服務器。 TM 負責管理全局事務,分配事務惟一標識,監控事務的執行進度,並負責事務的提交、回滾、失敗恢復等,是一個協調者的角色,多是程序或者中間件。XA 協議主要規定了了 TM 與 RM 之間的交互。注意:經過實現 XA 的接口,只是提供了對 XA 分佈式事務的支持,並非說數據庫自己有分佈式事務的能力。
XA 是一種兩階段提交的實現。數據庫自己必需要提供被協調的接口,好比事務開啓,準備,事務結束,事務提交,事務回滾。https://dev.mysql.com/doc/refman/5.7/en/xa.html
MySQL 單節點運行 XA 事務演示:
use ljxmycat; --開啓 XA 事務 xa start 'xid'; --插入數據
INSERT INTO `delivery_mod` (id,name) VALUES (22222, '張三');
5結束一個 XA 事務
xa end 'xid';
6準備提交
xa prepare'xid';
--列出全部處於 PREPARE 階段的 XA 事務
xa recover;
- 提交
xa commit 'xid';
配置: <system> <property name="sqlInterceptor">io.mycat.interceptor.impl.DefaultSqlInterceptor</property> </system> 源碼: /** * escape mysql escape letter */ @Override public String interceptSQL(String sql, int sqlType) { if (sqlType == ServerParse.UPDATE || sqlType == ServerParse.INSERT||sqlType == ServerParse.SELECT||sqlType == ServerParse.DELETE) { return sql.replace("\\'", "''"); } else { return sql; } }
<system> <property name="sqlInterceptor">io.mycat.interceptor.impl.StatisticsSqlInterceptor</property> <property name="sqlInterceptorType">select,update,insert,delete</property> <property name="sqlInterceptorFile">E:/mycat/sql.txt</property> </system>
1.定義自定義類 implements SQLInterceptor ,而後改寫 sql 後返回。 2.將本身實現的類放入 catlet 目錄,能夠爲 class 或 jar。 3.配置配置文件: <system> <property name="sqlInterceptor">io.mycat.interceptor.impl.自定義 class</property> <!--其餘配置--> </system>
官網的架構圖:
啓動
一、MycatServer 啓動,解析配置文件,包括服務器、分片規則等
二、建立工做線程,創建前端鏈接和後端鏈接
執行 SQL
一、前端鏈接接收 MySQL 命令
二、解析 MySQL,Mycat 用的是 Druid 的 DruidParser
三、獲取路由
四、改寫 MySQL,例如兩個條件在兩個節點上,則變成兩條單獨的 SQL
例如 select * from text where id in(5000001, 10000001);
改寫成:
select * from text where id = 5000001;(dn2 執行)
select * from text where id = 10000001;(dn3 執行)
又好比多表關聯查詢,先到各個分片上去獲取結果,而後在內存中計算
五、與後端數據庫創建鏈接
六、發送 SQL 語句到 MySQL 執行
七、獲取返回結果
八、處理返回結果,例如排序、計算等等
九、返回給客戶端
目前 Mycat 沒有實現對多 Mycat 集羣的支持。集羣以前最麻煩的是數據同步和選舉。能夠暫時使用 HAProxy+Keepalived 實現。