一、
MySQL Proxy是一個處于你的Client端和MySQL server端之間的簡單程序,它可以監(jiān)測、分析或改變它們的通信。它使用靈活,沒有限制,常見的用途包括:負(fù)載平衡,故障、查詢分析,查詢過濾和修改等等。
(Figure1:MySQL Proxy)
MySQL-Proxy,announced in June, is a binary application that sits between your MySQL client and server, and supports the embedded scripting languageLua. The proxy can be used to analyze, monitor and transform communication, and supports a wide range of scenarios including:
load balancing and fail over handling query analysis and logging SQL macros query rewriting executing shell commands
One of the more powerful features of MySQL Proxy is the ability to do "Read/Write Splitting". The basic concept is to have a master database handle transactional queries while slaves handle SELECT queries. Replication is used to synchronize the changes due to transactional queries with the slaves in the cluster.
MySQL-Proxy是處在你的MySQL數(shù)據(jù)庫客戶和服務(wù)端之間的程序,它還支持嵌入性腳本語言Lua。這個代理可以用來分析、監(jiān)控和變換(transform)通信數(shù)據(jù),它支持非常廣泛的使用場景:
負(fù)載平衡和故障轉(zhuǎn)移處理 查詢分析和日志 SQL宏(SQL macros) 查詢重寫(query rewriting) 執(zhí)行shell命令
MySQL Proxy更強(qiáng)大的一項功能是實現(xiàn)“讀寫分離(Read/Write Splitting)”。基本的原理是讓主數(shù)據(jù)庫處理事務(wù)性查詢,而從數(shù)據(jù)庫處理SELECT查詢。數(shù)據(jù)庫復(fù)制被用來把事務(wù)性查詢導(dǎo)致的變更同步到集群中的從數(shù)據(jù)庫。
二、
測試環(huán)境:Ubuntu 10.04.2 LTS + MySQL5.1.41-3ubuntu12.10-log
192.168.1.147proxy 代理 入口
192.168.1.126master主機(jī) 只寫
192.168.1.145slaver從機(jī) 只讀
程序上只需要鏈接到192.168.1.147,而192.168.1.126和192.168.1.145對于程序來說是透明的,你完全不需要理會,也不需要知道192.168.1.126和192.168.1.145,你對數(shù)據(jù)庫的所有操作都只對192.168.1.147進(jìn)行操作。
1.
#apt-get install lua5.1
MySQL-Proxy的讀寫分離主要是通過rw-splitting.lua腳本實現(xiàn)的,因此需要安裝lua。
2.
#apt-getmysql-proxy
當(dāng)前獲取到的版本是:mysql-proxy 0.8.0(查看版本命令:#mysql-proxy -V)
3.
#vim /usr/share/mysql-proxy/rw-splitting.lua
配置并使用rw-splitting.lua讀寫分離腳本,腳本目錄是 /usr/share/mysql-proxy,修改讀寫分離腳本rw-splitting.lua,修改默認(rèn)連接數(shù),進(jìn)行快速測試,如果不修改連接數(shù)的話要達(dá)到連接數(shù)為4時才會啟用讀寫分離。
-- connection pool
if not proxy.global.config.rwsplit then
proxy.global.config.rwsplit = {
1, //
min_idle_connections =
1, //
max_idle_connections =
is_debug = false
}
end
沒有超過
這是因為mysql-proxy會檢測客戶端連接,當(dāng)連接min_idle_connections預(yù)設(shè)值時, 不會進(jìn)行讀寫分離, 即查詢操作會發(fā)生到Master上。
4.
#mkdir /var/log/mysql-proxy
#vi mysql-proxy.log
5.
#sudo mysql-proxy --proxy-read-only-backend-addresses=192.168.1.145:3306 --proxy-backend-addresses=192.168.1.126:3306 --proxy-lua-script=/usr/share/mysql-proxy/rw-splitting.lua >/var/log/mysql-proxy/mysql-proxy.log &
參數(shù)說明:
192.168.1.147proxy 代理 入口
192.168.1.126master主機(jī) 只寫
192.168.1.145slaver從機(jī) 只讀
當(dāng)運行sudo mysql-proxy 上面語句后,查詢進(jìn)程沒有4040的時候,需要重啟mysql ( sudo /etc/init.d/mysql restart) 之后再輸入proxy設(shè)置。
6.
#netstat -ant
#netstat –ntl
(Figure2:端口)
tcp00 0.0.0.0:40400.0.0.0:*LISTEN
tcp00 0.0.0.0:40410.0.0.0:*LISTEN
7.
mysql> show processlist\G;
(Figure3:進(jìn)程)
可以看到,產(chǎn)生了一個新連接。如果想殺掉某個鏈接,可以使用mysql>help kill查看kill的幫助信息,殺掉36進(jìn)程的命令:mysql>kill 36;
8.
1)在mysql-proxy機(jī)子進(jìn)入MySQL
#mysql -u gaizai -p -P4040 -h 192.168.1.147
必須指定-h參數(shù),不然報下面錯誤:
(Figure4:出錯)
2)顯示數(shù)據(jù)庫列表:
mysql> show databases;
如果你是搭建MySQL-Proxy成功的話,你上面查看到的數(shù)據(jù)庫列表應(yīng)該是192.168.1.145服務(wù)器上的數(shù)據(jù)庫列表。(可以在145和126分別創(chuàng)建不同的數(shù)據(jù)庫進(jìn)行測試)
3)進(jìn)入測試數(shù)據(jù)庫:
mysql> use weibo;
4)查詢表記錄:
mysql>select * from blog;
5)插入一條記錄:
mysql> INSERT INTO `blog` (`TaskID`, `Content`, `Quote`, `Author`, `Time`, `Url`, `ImageUrl`, `Transmits`, `Comments`, `Hash`, `AddOn`) VALUES('10','fefef','fefef','efef',NOW(),'http://www.cnblogs.com/zgx/archive/2011/09/13/2174823.html',NULL,'0','0','33333333',NOW());
6)查詢表記錄:
mysql>select * from blog;
對比兩次查詢表的記錄,看記錄是否有變化,我們插入了數(shù)據(jù)(確認(rèn)插入成功),但兩次的數(shù)據(jù)是沒有變化的,這就對了,這就是讀寫分離了(我們讀的是145的數(shù)據(jù)庫,插入的是126的數(shù)據(jù)庫,而我們的145與126又沒有設(shè)置Replication;如果之前設(shè)置了,請先停止后進(jìn)行測試)
注:有時候mysql_proxy(38)庫里會顯示出數(shù)據(jù),重啟系統(tǒng)系統(tǒng),重新啟動mysql后就沒有此現(xiàn)象了。
7)進(jìn)入主寫服務(wù)器(192.168.1.126) 查看數(shù)據(jù)
#mysql-u gaizai -p -h 192.168.1.126
mysql> use weibo;
mysql>select * from blog;
可以查看已經(jīng)寫入了一條記錄。
8)進(jìn)入從讀服務(wù)器(192.168.1.145)
#mysql-u gaizai -p -h 192.168.1.145
mysql> use weibo;
mysql>select * from blog;
因為沒有數(shù)據(jù)顯示,說明只能讀,不能寫。
在使用工具SQLyog執(zhí)行查詢時,在Proxy服務(wù)器上會自動顯示下面的信息:
(Figure5:信息)
9.
上面的測試只是測試了插入數(shù)據(jù)后,在沒有進(jìn)行Master與Slave的Replication設(shè)置的情況下,讀取Master與Slave的數(shù)據(jù)是不同,如果想達(dá)到Figure1的效果,我們還需要設(shè)置Master與Slave之間的數(shù)據(jù)復(fù)制(Replication),詳情請參考:Ubuntu10下MySQL搭建Master Slave
三、
幫助命令:$mysql-proxy --help-all
查看下MySQL Proxy的版本:$mysql-proxy -V
編譯啟動腳本:$vi /etc/init.d/mysql-proxy
啟動命令:$ /etc/init.d/mysql-proxy start
停止命令:$ /etc/init.d/mysql-proxy stop
重啟命令:$ /etc/init.d/mysql-proxy restart
四、
1.在啟動mysql-proxy的時候,可以把啟動命令保存為文件:
建議使用配置文件的形式啟動,注意配置文件必須是660權(quán)限,否則無法啟動.如果有多個Slave的話,proxy-read-only-backend-addresses參數(shù)可以配置多個以逗號分隔的IP:Port從庫列表。
殺掉mysql-proxy進(jìn)程:#killallmysql-proxy
新建一個文件:#vi/etc/mysql-proxy.cnf
在文件中輸入兩個分隔符中間的內(nèi)容:
------------------------------------------------------
[mysql-proxy]
admin-username=viajarchen
admin-password=123123
admin-lua-script=/usr/share/mysql-proxy//admin-sql.lua
proxy-backend-addresses=192.168.1.126:3306
proxy-read-only-backend-addresses=192.168.1.145:3306
proxy-lua-script=/usr/share/mysql-proxy/rw-splitting.lua
log-file=/var/tmp/mysql-proxy.log
log-level=debug
daemon=true
keepalive=true
max-open-files=1024
------------------------------------------------------
設(shè)置權(quán)限:#chmod660/etc/mysql-proxy.cnf
或者#chmod +x /etc/init.d/mysql-proxy
設(shè)置啟動文件:#mysql-proxy--defaults-file=/etc/mysql-proxy.cnf
查看信息:#ps-ef|grepmysql-proxy|grep-vgrep
root18691018:16?00:00:00/usr/local/mysql-proxy/libexec/mysql-proxy--defaults-file=/etc/mysql-proxy.cnf
root18701869018:16?00:00:00/usr/local/mysql-proxy/libexec/mysql-proxy--defaults-file=/etc/mysql-proxy.cnf
查看日志:#tail-50f/var/tmp/mysql-proxy.log
2.mysql-proxy參數(shù)
--admin-address=host:port指定一個mysqo-proxy的管理端口,缺省是4041;
-P,--proxy-address=是mysql-proxy服務(wù)器端的監(jiān)聽端口,缺省是4040;
-r,--proxy-read-only-backend-addresses=只讀Slave的地址和端口,缺省為不設(shè)置;
-b,--proxy-backend-addresses=遠(yuǎn)程Master地址和端口,可設(shè)置多個做failover和loadbalance,缺省是127.0.0.1:3306;
--defaults-file=配置文件,可以把mysql-proxy的參數(shù)信息置入一個配置文件里;
--daemonmysql-proxy以守護(hù)進(jìn)程方式運行
--keepalivetrytorestarttheproxyifitcrashed,保持連接啟動進(jìn)程會有2個,一號進(jìn)程用來監(jiān)視二號進(jìn)程,如果二號進(jìn)程死掉自動重啟proxy。
–log-level=debug定義log日志級別,由高到低分別有
(error|warning|info|message|debug)
--proxy-lua-script=file指定一個Lua腳本程序來控制mysql-proxy的運行和設(shè)置,這個腳本在每次新建連接和腳本發(fā)生修改的的時候?qū)⒅匦抡{(diào)用。
--max-open-files:指定最大檔案開啟數(shù)為1024,否則會有【could not raise RLIMIT_NOFILE to 8192, Invalid argument (22). Current limit still 1024.】的log訊息出現(xiàn)。
3.當(dāng)MySQL主從復(fù)制在 show slave status\G 時出現(xiàn)Slave_IO_Running或Slave_SQL_Running 的值不為YES時,,需要首先通過 stop slave 來停止從服務(wù)器,然后再進(jìn)行測試讀寫分離。
4.MySQL-Proxy的rw-splitting.lua腳本在網(wǎng)上有很多版本,但是最準(zhǔn)確無誤的版本仍然是源碼包中所附帶的lib/rw-splitting.lua腳本,如果有l(wèi)ua腳本編程基礎(chǔ)的話,可以在這個腳本的基礎(chǔ)上再進(jìn)行優(yōu)化;
5.MySQL-Proxy實際上非常不穩(wěn)定,在高并發(fā)或有錯誤連接的情況下,進(jìn)程很容易自動關(guān)閉,因此打開–keepalive參數(shù)讓進(jìn)程自動恢復(fù)是個比較好的辦法,但還是不能從根本上解決問題,因此通常最穩(wěn)妥的做法是在每個從服務(wù)器上安裝一個MySQL-Proxy供自身使用,雖然比較低效但卻能保證穩(wěn)定性;
6.一主多從的架構(gòu)并不是最好的架構(gòu),通常比較優(yōu)的做法是通過程序代碼和中間件等方面,來規(guī)劃,比如單雙server-id號分開寫入等方式來實現(xiàn)兩個或多個主服務(wù)器;
7.MySQL-Cluster 的穩(wěn)定性也不是太好;
8.Amoeba for MySQL 是一款優(yōu)秀的中間件軟件,同樣可以實現(xiàn)讀寫分離,負(fù)載均衡等功能,并且穩(wěn)定性要大大超過MySQL-Proxy,建議大家用來替代MySQL-Proxy,甚至MySQL-Cluster。
9.mysql proxy不支持old_password。另外也可以通過查看密碼長度的方式來判斷:select length(password) from mysql.user如果長度為16位則是old_password無疑。
10. 安裝了mysql-proxy實現(xiàn)讀寫分離,有master x 1, slave x 2。為了測試failover,停掉了一個slave,然后mysql-proxy會一直報錯,提示無法連接。這個情況比單點的mysql還糟糕,掛掉一個就全掛掉!mysql的工程師給提供了一段代碼,替換掉:
src/network-mysqld-proxy.c的NETWORK_MYSQLD_PLUGIN_PROTO函數(shù)可以解決這個問題。network-mysqld-proxy-function.c文件。
(經(jīng)過測試:我停止掉slave數(shù)據(jù)庫,proxy的查詢就會轉(zhuǎn)移到master上,當(dāng)把slave啟動后,proxy依然在讀master,當(dāng)有新的鏈接進(jìn)來的時候才會去讀取slave的數(shù)據(jù))
11. 如果在mysql-proxy的機(jī)器上也安裝了mysql的話,新手就會在這個時候混亂了,到底要如何進(jìn)行測試和鏈接呢?比如使用命令:#mysql -u gaizai -p -P4040 -h 192.168.1.147是表示登陸本機(jī)的4040端口,使用gaizai帳號,這個帳號可以不是本地mysql的帳號,這樣就比較容易區(qū)分了。
12. 在上述環(huán)境中,mysql-proxy、mysql-master、mysql-slave三臺服務(wù)器均存在單點故障。為了避免mysql-proxy單點隱患有兩種方法:一種方法是mysql-proxy配合keepalived做雙機(jī),另一種方法是將mysql-proxy和應(yīng)用服務(wù)安裝到同一臺服務(wù)器上;為了避免mysql-master單點故障可以使用DRBD+heartbear做雙機(jī);為了避免mysql-slave單點故障可以添加多臺mysql-slave,mysql-proxy會自動屏蔽后端發(fā)生故障的mysql-slave。
13. 用sysbench (或者super-smack)測試mysql性能:
#sysbench --test=oltp --mysql-table-engine=innodb --oltp-table-size=1000 --mysql-socket=/tmp/mysql.sock --mysql-password=123456 --mysql-user=gaizai --mysql-host=192.168.1.126 --mysql-db=weibo --num-threads=15 prepare
#sysbench --test=oltp --mysql-table-engine=innodb --oltp-table-size=1000 --mysql-socket=/tmp/mysql.sock --mysql-password=123456 --mysql-user=gaizai --mysql-host=192.168.1.126 --mysql-db=weibo --oltp-test-mode=complex run
14. 關(guān)于mysql-proxy的啟動和關(guān)閉的shell腳本的編寫:
15. 讀寫分離不能回避的問題之一就是延遲,可以考慮Google提供的SemiSyncReplicationDesign補(bǔ)丁。
16. MySQL-Proxy缺省使用的是4040端口,如果你想透明的把3306端口的請求轉(zhuǎn)發(fā)給4040的話,那么可以:iptables -t nat -I PREROUTING -s ! 127.0.0.1 -p tcp --dport 3306 -j REDIRECT --to-ports 4040如果想刪除這條規(guī)則,可以把上面例子中的-I換成-D。參考鏈接
17. 當(dāng)使用bigint 時,mysql_insert_id()存在問題,詳情見手冊,不過對于大多數(shù)人而言,bigint基本不會遇到,所以你可以無視這個問題)注:對于這兩個問題,官方BUG庫里有人給出了相應(yīng)的補(bǔ)丁。
五、
在執(zhí)行命令的時候出現(xiàn)了下面的錯誤:
(Figure6:錯誤信息)
could not raise RLIMIT_NOFILE to 8192
這個一個警告級別的錯誤,意思是MySQL Proxy在你的系統(tǒng)上不能把open files limit提升到8192,不過沒關(guān)系的,MySQL Proxy依然好好的運行在你的電腦上。
可以通過設(shè)置啟動--max-open-files參數(shù)解決。
MySQL Proxy
mysql proxy master and slave test
加入--max-open-files=8192后報下面的錯誤:
(Figure7:錯誤信息)
六、
(經(jīng)過測試:我停止掉slave數(shù)據(jù)庫,proxy的查詢就會轉(zhuǎn)移到master上,當(dāng)把slave啟動后,proxy依然在讀master,當(dāng)有新的鏈接進(jìn)來的時候才會重新去讀取slave的數(shù)據(jù)。有時可能需要重啟下mysql-proxy)
1.當(dāng)slave宕機(jī)后,mysql-proxy是如何讀取的?
2.如何知道m(xù)ysql-proxy當(dāng)前執(zhí)行的select是在哪臺機(jī)器上執(zhí)行的?
3.當(dāng)slave宕機(jī)一段時間后,如果再次同步master的缺失的數(shù)據(jù)?
4.當(dāng)配置中設(shè)置了proxy-read-only-backend-addresses=192.168.1.145:3306
#tail-50f/var/tmp/mysql-proxy.log
,192.168.1.147:3306類似這樣的兩個slave,如果兩個slave的數(shù)據(jù)不同步,那么是怎么讀取數(shù)據(jù)的?測試
5.生產(chǎn)環(huán)境中除了進(jìn)行程序調(diào)試外,其它不要開啟mysql查詢?nèi)罩荆驗椴樵內(nèi)罩居涗浟丝蛻舳说乃姓Z句,頻繁的IO操作將會導(dǎo)致mysql整體性能下降。如何設(shè)置呢?
6.mysql-proxy.cnf文件中的管理員帳號和密碼有什么用?使用命令進(jìn)入管理
mysql -u viajarchen -p -P 4041 -h 192.168.1.147 密碼是123123
mysql> select * from proxy_connections;
mysql> select * from proxy_config;
(Figure8:信息)
7.關(guān)于mysql-proxy的啟動和關(guān)閉的shell腳本的編寫?測試
8.對于/usr/share/mysql-proxy/rw-splitting.lua腳本中的
local min_idle_connections = 4 local max_idle_connections = 8應(yīng)該如何理解?min的話就是要達(dá)到這個值的時候才會讀寫分離,那么max的是什么意思呢?最大能有8個鏈接?
9.mysqld是什么意思?是mysql的守護(hù)進(jìn)程!
10.HAProxy和keepalived怎么一起搭建使用?能解決什么問題?