Mysql Hunter
一、簡介
自動化實施的過程中,我們通常都面臨一個棘手的問題:數(shù)據(jù)的準備和恢復(fù)。即在成功執(zhí)行一個自動化用例時,我們可能需要一定的數(shù)據(jù)前提,而為了使得整個前提不至于被其他的用例破壞,以至于我們有時不得不在自動化用例編寫過程中手工的添加許多Insert、Update、Delete語句來保證數(shù)據(jù)被恢復(fù)到我們執(zhí)行用例前的狀態(tài)。?
使用phpunit等工具框架進行php自動化單元測試的過程中也同樣面臨數(shù)據(jù)準備和恢復(fù)的問題。單元測試開發(fā)人員開發(fā)過程中不得不編碼中顯示編寫數(shù)據(jù)準備,驗證,恢復(fù)的代碼,這樣會帶來以下幾個缺點:
1、用例閱讀性降低,難于辨別主要的測試邏輯?
2、用例可維護性降低,當數(shù)據(jù)庫的表結(jié)構(gòu)略微有變化或者業(yè)務(wù)底層邏輯有變動,數(shù)據(jù)的準備和恢復(fù)的代碼都將有可能面臨修改甚至重寫?
3、極大消耗開發(fā)人員開發(fā)成本,用例編寫過程中不得不額外花很多的時間去思考數(shù)據(jù)的準備和恢復(fù)。
基于以上三點,考慮設(shè)計實現(xiàn)一個mysql server及client的中間層,通過此中間層,可以將開發(fā)人員的數(shù)據(jù)恢復(fù)操作透明化,且在數(shù)據(jù)環(huán)境穩(wěn)定的前提下,適度的降低開發(fā)人員的數(shù)據(jù)準備工作。?
基于Hunter擴展,將來可能帶來:?
1、自定義Mysql樁(模擬、修改結(jié)果集)?
2、實時監(jiān)控Query(已經(jīng)實現(xiàn),目前可以監(jiān)控query性能)?
3、性能測試輔助,集成query性能瓶頸分析反饋
二、Amoeba和Hunter的角色
Amoeba for mysql位于Application與數(shù)據(jù)庫之間,為應(yīng)用提供透明的代理服務(wù)。Amoeba對外接口采用 mysql protocol,沒有定義自己的協(xié)議和接口,使得任何mysql的應(yīng)用都能方便的使用Amoeba,諸如php、java、c等等的cennector。Amoeba本身沒有Build 任何 SQL語句,而是直接接收client的SQL、命令等進行代理轉(zhuǎn)發(fā),Amoeba采用 SQL、命令等 mysql protocol規(guī)范作為統(tǒng)一的接口,完備性得到了保證,能夠完成mysql的所有功能操作。
三、 安裝
Mysql Hunter不需要編譯,僅需要Java運行環(huán)境(JRE1.5以上)。
先決條件 :
1、Java SE 1.5或以上Amoeba 框架是基于JDK1.5開發(fā)的,采用了JDK1.5的特性 支持Mysql協(xié)議版本10(mysql 4.1以后的版本)?
2、網(wǎng)絡(luò)環(huán)境至少運行有一個mysql 4.1以上的服務(wù)?
操作步驟 :
1、 設(shè)置環(huán)境變量,在~/.bashrc中加入JAVA_HOME=/JRE的安裝路徑 /?
2、 將程序目錄解壓或拷貝出來,直接運行mysql-hunter/bin/amoeba即可啟動?
參考參數(shù)配置進行配置后啟動amoeba,此時proxy應(yīng)連接到Mysql Server,同時對于client而言,mysql servers對于client是透明的,client認為proxy為mysql服務(wù)器直接連接proxy的ip和端口即可正常操作數(shù)據(jù)庫。
四、 功能介紹
4.1 Amoeba for mysql
Mysql-hunter是基于amoeba框架做的mysql代理擴展如圖。
amoeba for mysql本身實現(xiàn)的功能包括:
讀寫/分離;
失敗重連 ;
負載均衡 ;
連接池 ;
身份認證
4.2 Mysql hunter擴展
Mysql-Hunter的功能則主要在于SQL/SQL Result的inject、rewrite以及reverse,如圖:?
從上圖可以看出,mysql hunter可以實現(xiàn)如下功能:
Client連接server的階段進行自定義命令發(fā)送或返回?
Client發(fā)送query cmd至server的階段,進行query截取,修改?
同理,Server返回給Client的結(jié)果集也能被hunter監(jiān)控,修改甚至重寫?
特點:使用起來很簡單,只需要設(shè)置start點和end點,那么兩者之間所有執(zhí)行的sql query都可以被捕獲、并生成逆命令
?
4.3 基本擴展BasicMysqlHunter
BasicMysqlHunter?是一個基本且實用的擴展實現(xiàn),繼承自Hunter類,實現(xiàn)了Hunter的抽象方法 ,可以在client發(fā)送cmd至server前對query進行截獲處理,也可以對server返回的結(jié)果集進行修改。?
BasicMysqlHunter?下的basic handlers這里不再介紹,詳細請參考《Mysql Hunter總體設(shè)計》,BasicMysqlHunter目前定位于對DML query進行如下操作:?
分析識別?
逆向語句及序列生成?
逆向語句的回放,即顯示命令恢復(fù)數(shù)據(jù)庫數(shù)據(jù)
舉例說明?
Client通過mysql hunter向server發(fā)送了一條query:?
INSERT INTO tblLemma SET title = ‘北京’, content = ‘我愛北京天安門’;?
此時tblLemma表的自增字段ID變?yōu)榱?00?
Mysql Hunter將分析識別這條語句,最終生成逆向的恢復(fù)語句序列:?
Stack = (
‘DELETE FROM tblLemma WHERE title = ‘北京’ AND content = ‘我愛北京天安門’ AND ID = 100;’,
‘ALTER TABLE tblLemma SET AUTO_INCREMENT = 99;’,
)
通過順序執(zhí)行stack中的語句,數(shù)據(jù)庫中的數(shù)據(jù)就將恢復(fù)到insert命令之前的狀態(tài)。
4.4 Sql檢查擴展SqlCheckHunter
繼承自Hunter類,實現(xiàn)了Hunter的抽象方法,用來截獲SQL語句,并對sql語句進行分析,最終給出分析報告。?
主要用于Sql query的性能分析,極大省去人力的比對分析,配置簡單,對功能測試透明。?
支持SELECT、INSERT、UPDATE、DELETE語句的常規(guī)經(jīng)驗性檢查。?
規(guī)則主要包含:?
mapIssueReason.put(SELECT_REASON_1, "使用的索引為Null,建議檢查SQL涉及表的索引字段是否合理");
mapIssueReason.put(SELECT_REASON_2, "Filesort,所使用的索引對排序支持不好,如果檢索排序結(jié)果集大建議增強索引");
mapIssueReason.put(SELECT_REASON_3, "查詢結(jié)果集可能對應(yīng)超過50條記錄,而SQL非翻頁查詢語句");
mapIssueReason.put(SELECT_REASON_4, "備選索引數(shù)大于1,可以考慮采用force index優(yōu)化");
mapIssueReason.put(INSERT_REASON_1, "連續(xù)采用單語句插入相同的表大于100次,建議考慮:1. 寫合并;2. 采用LOAD DATA INFILE;3. 調(diào)節(jié)bulk_insert_buffer_size變量");
mapIssueReason.put(INSERT_REASON_2, "INSERT...SELECT...語句,請查看該語句的SELECT性能是否可接受");
mapIssueReason.put(UPDATE_REASON_1, "UPDATE語句,未包含where條件字段,進行全表更新操作效率低");
mapIssueReason.put(UPDATE_REASON_2, "UPDATE語句,WHERE字句不能使用索引找到被更新記錄或修改范圍過大");
mapIssueReason.put(UPDATE_REASON_3, "UPDATE語句連續(xù)更新相同表大于100次,建議考慮:1. 寫合并;2. 如果有索引,索引更新可能過于頻繁,適當修改縮減索引");
mapIssueReason.put(DELETE_REASON_1, "DELETE語句刪除全表,建議使用truncate語句");
mapIssueReason.put(DELETE_REASON_2, "DELETE語句,WHERE字句不能使用索引找到被更新記錄或修改范圍過大");
mapIssueReason.put(DELETE_REASON_3, "DELETE語句連續(xù)更新相同表大于100次");
4.5 參數(shù)配置
下面介紹conf文件中所有的配置項。
amoeba.xml :
1. <server> //Amoeba 代理server,即proxy server的配置
/* port: 綁定端口
* ipAddress: 綁定ip
* readThreadPoolSize: 網(wǎng)絡(luò)IO最大線程數(shù)
* user: amoeba 對外驗證所需用戶名
* password: amoeba 對外驗證所需密碼
*/
2. <connectionManagerList> 所使用的連接管理類,通常不需要修改
3. <dbServerList> 后端所連接的數(shù)據(jù)庫服務(wù)器配置,包括主從所有的DB服務(wù)器
* <dbServer>
/* port: 真實mysql數(shù)據(jù)庫端口
* ipAddress: 真實mysql數(shù)據(jù)庫ip
* schema: 默認的數(shù)據(jù)庫schema
* user: 連接該db所需的用戶名
* password: 連接該db所需的相應(yīng)用戶的密碼
*/
* <poolConfig>: 對象池,通常不需要修改
4. <dbServer name="multiPool" virtual="true"> 設(shè)定參與負載均衡的服務(wù)器
/* loadbalance: 負載均衡設(shè)定:1為輪詢 2為權(quán)重
* poolNames: 以逗號分隔如,server1,server2,server3…
*/
5. <queryRouter> 所用的query分發(fā)路由相關(guān)配置
/* writePool: 寫操作池包含的數(shù)據(jù)庫服務(wù)器
* readPool: 讀操作池包含的數(shù)據(jù)庫服務(wù)器
* needParse: 是否需要進行query parse
*/
高亮的配置項是重新部署DB環(huán)境的時候通常需要關(guān)注的配置項。<br>
// 擴展配置
<extension>
<hunter class="com.meidusa.amoeba.extend.BasicMySqlHunter"></hunter>
</extension>
設(shè)定使用的hunter擴展是BasicMysqlHunter。
?
log4j.xml?
日志打印的配置,通常不需要修改。如果需要額外的增加日志格式,或者修改日志格式,級別可以參考log4j的文檔,或者參考本配置文件的其他配置方法。
BasicMysqlHunter?目前提供三條自定制命令:?
1 select start:開始啟用擴展,擴展將開始監(jiān)控select start執(zhí)行之后流經(jīng)Hunter的DML命令并求逆;Hunter直接返回Ok packet?
2 select print_stack:打印當前Hunter上下文中的逆命令堆棧?
3 select end:結(jié)束擴展監(jiān)控,并將Hunter上下文中的逆向命令棧依順序pop出棧并發(fā)送Server恢復(fù)DB數(shù)據(jù);Hunter直接返回Ok packet
$link = mysql_connect('127.0.0.1:3307', 'mysql_user', 'mysql_password');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
// Case執(zhí)行前
$result = mysql_query("select start");
/*
* Case 執(zhí)行
* 執(zhí)行過程中可以自身或用其他客戶端發(fā)送select print_stack命令check當前逆命令棧
*/
// Case執(zhí)行后
$result = mysql_query("select end");
// 此時Case執(zhí)行過程中的所有DML操作將被還原
五、使用注意
5.1 Mysql Hunter不支持的操作
Mysql Hunter(確切的說是BasicMysqlHunter)已經(jīng)支持了絕大部分常用的DML語句,目前已知的不支持的query類型包括:?
DML語句的多表操作,例如一個query中同時修改update表A和表B的字段,暫時沒有實現(xiàn)逆語句生成,僅能轉(zhuǎn)發(fā)?
未實現(xiàn)UPDATE語句中包含order by limit的語句的逆語句生成,僅能轉(zhuǎn)發(fā)?
暫不支持改變表結(jié)構(gòu)和用戶屬性權(quán)限的語句,ALTER TABLE、TRUNCATE TABLE、CREATE TABLE、DROP TABLE、GRANT、ALTER USER等,僅能轉(zhuǎn)發(fā)?
不支持非DML語句,僅能轉(zhuǎn)發(fā)?
內(nèi)置函數(shù)支持有限,根據(jù)實際應(yīng)用過程中的使用情況增加對內(nèi)置函數(shù)的擴展并求逆(目前已支持now())
5.2 Mysql Hunter日志使用
Mysql Hunter運行時日志記錄在:?
log/hunter.log 正常日志?
log/hunter.log.wf 錯誤日志?
正常日志會打印所有流經(jīng)proxy層的query cmds,以及hunter的關(guān)鍵執(zhí)行步驟的log,通常不應(yīng)出現(xiàn)錯誤日志,如果出現(xiàn)了錯誤日志有兩種情況:?
hunter不支持的操作?
hunter自身的bug?
利用hunter.log有時可以輔助我們定位問題,甚至可以拋棄mysql的query.log
(作者:weichenxi)
?
【本文轉(zhuǎn)自百度測試技術(shù)空間】http://hi.baidu.com/baiduqa/blog/item/69fc0553d19d8f9b8c543004.html
【關(guān)注百度技術(shù)沙龍】本文轉(zhuǎn)自百度技術(shù)51CTO博客,原文鏈接:http://blog.51cto.com/baidutech/744475,如需轉(zhuǎn)載請自行聯(lián)系原作者
總結(jié)
以上是生活随笔為你收集整理的Mysql Hunter的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS prototype作用
- 下一篇: C语言 完数C语言 完数C语言 完数