一、MySQL-Proxy基礎
MySQL Proxy是一個處於你的Client端和MySQL server端之間的簡單程序,它可以監測、分析或改變它們的通信。它使用靈活,沒有限制,常見的用途包括:負載平衡,故障、查詢分析,查詢過濾和修改等等。
(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 language Lua. 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數據庫客戶和服務端之間的程序,它還支持嵌入性腳本語言Lua。這個代理可以用來分析、監控和變換(transform)通信數據,它支持非常廣泛的使用場景:
- 負載平衡和故障轉移處理
- 查詢分析和日志
- SQL宏(SQL macros)
- 查詢重寫(query rewriting)
- 執行shell命令
MySQL Proxy更強大的一項功能是實現“讀寫分離(Read/Write Splitting)”。基本的原理是讓主數據庫處理事務性查詢,而從數據庫處理SELECT查詢。數據庫復制被用來把事務性查詢導致的變更同步到集群中的從數據庫。
二、實戰過程
測試環境:Ubuntu 10.04.2 LTS + MySQL5.1.41-3ubuntu12.10-log
192.168.1.147 proxy 代理 入口
192.168.1.126 master 主機 只寫
192.168.1.145 slaver 從機 只讀
程序上只需要鏈接到192.168.1.147,而192.168.1.126和192.168.1.145對於程序來說是透明的,你完全不需要理會,也不需要知道192.168.1.126和192.168.1.145,你對數據庫的所有操作都只對192.168.1.147進行操作。
1. 安裝腳本lua
#apt-get install lua5.1
MySQL-Proxy的讀寫分離主要是通過rw-splitting.lua腳本實現的,因此需要安裝lua。
2. 安裝配置MySQL-Proxy
#apt-get mysql-proxy
當前獲取到的版本是:mysql-proxy 0.8.0(查看版本命令:#mysql-proxy -V)
3. 修改rw-splitting.lua
#vim /usr/share/mysql-proxy/rw-splitting.lua
配置並使用rw-splitting.lua讀寫分離腳本,腳本目錄是 /usr/share/mysql-proxy,修改讀寫分離腳本rw-splitting.lua,修改默認連接數,進行快速測試,如果不修改連接數的話要達到連接數為4時才會啟用讀寫分離。
-- connection pool
if not proxy.global.config.rwsplit then
proxy.global.config.rwsplit = {
min_idle_connections = 1, //默認為4
max_idle_connections = 1, //默認為8
is_debug = false
}
end
這是因為mysql-proxy會檢測客戶端連接,當連接沒有超過min_idle_connections預設值時, 不會進行讀寫分離, 即查詢操作會發生到Master上。
4. 新建文件夾/var/log/mysql-proxy/和文件mysql-proxy.log
#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 &
參數說明:
192.168.1.147 proxy 代理 入口
192.168.1.126 master 主機 只寫
192.168.1.145 slaver 從機 只讀
當運行sudo mysql-proxy 上面語句后,查詢進程沒有4040的時候,需要重啟mysql ( sudo /etc/init.d/mysql restart) 之后再輸入proxy設置。
6. 查看進程端口
#netstat -ant
#netstat –ntl
(Figure2:端口)
tcp 0 0 0.0.0.0:4040 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:4041 0.0.0.0:* LISTEN
7. 查看數據庫鏈接
mysql> show processlist\G;
(Figure3:進程)
可以看到,產生了一個新連接。如果想殺掉某個鏈接,可以使用mysql>help kill查看kill的幫助信息,殺掉36進程的命令:mysql>kill 36;
8. 測試讀寫分離
1) 在mysql-proxy機子進入MySQL
#mysql -u gaizai -p -P4040 -h 192.168.1.147
必須指定-h參數,不然報下面錯誤:
(Figure4:出錯)
2) 顯示數據庫列表:
mysql> show databases;
如果你是搭建MySQL-Proxy成功的話,你上面查看到的數據庫列表應該是192.168.1.145服務器上的數據庫列表。(可以在145和126分別創建不同的數據庫進行測試)
3) 進入測試數據庫:
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;
對比兩次查詢表的記錄,看記錄是否有變化,我們插入了數據(確認插入成功),但兩次的數據是沒有變化的,這就對了,這就是讀寫分離了(我們讀的是145的數據庫,插入的是126的數據庫,而我們的145與126又沒有設置Replication;如果之前設置了,請先停止后進行測試)
注:有時候mysql_proxy(38)庫里會顯示出數據,重啟系統系統,重新啟動mysql后就沒有此現象了。
7) 進入主寫服務器(192.168.1.126) 查看數據
#mysql -u gaizai -p -h 192.168.1.126
mysql> use weibo;
mysql>select * from blog;
可以查看已經寫入了一條記錄。
8) 進入從讀服務器(192.168.1.145)
#mysql -u gaizai -p -h 192.168.1.145
mysql> use weibo;
mysql>select * from blog;
因為沒有數據顯示,說明只能讀,不能寫。
在使用工具SQLyog執行查詢時,在Proxy服務器上會自動顯示下面的信息:
(Figure5:信息)
9. MySQL-Proxy+Replication
上面的測試只是測試了插入數據后,在沒有進行Master與Slave的Replication設置的情況下,讀取Master與Slave的數據是不同,如果想達到Figure1的效果,我們還需要設置Master與Slave之間的數據復制(Replication),詳情請參考:Ubuntu10下MySQL搭建Master Slave
三、MySQL-Proxy命令
幫助命令:$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權限, 否則無法啟動. 如果有多個Slave的話, proxy-read-only-backend-addresses參數可以配置多個以逗號分隔的IP:Port從庫列表。
殺掉mysql-proxy進程:# killall mysql-proxy
新建一個文件:# vi /etc/mysql-proxy.cnf
在文件中輸入兩個分隔符中間的內容:
------------------------------------------------------
[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
------------------------------------------------------
設置權限:# chmod 660 /etc/mysql-proxy.cnf
或者#chmod +x /etc/init.d/mysql-proxy
設置啟動文件:# mysql-proxy --defaults-file=/etc/mysql-proxy.cnf
查看信息:# ps -ef | grep mysql-proxy | grep -v grep
root 1869 1 0 18:16 ? 00:00:00 /usr/local/mysql-proxy/libexec/mysql-proxy --defaults-file=/etc/mysql-proxy.cnf
root 1870 1869 0 18: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參數
--admin-address=host:port 指定一個mysqo-proxy的管理端口, 缺省是4041;
-P, --proxy-address=<host:port> 是mysql-proxy 服務器端的監聽端口, 缺省是4040;
-r, --proxy-read-only-backend-addresses=<host:port> 只讀Slave的地址和端口, 缺省為不設置;
-b, --proxy-backend-addresses=<host:port> 遠程Master地址和端口, 可設置多個做failover和load balance, 缺省是127.0.0.1:3306;
--defaults-file=<file>配置文件, 可以把mysql-proxy的參數信息置入一個配置文件里;
--daemon mysql-proxy以守護進程方式運行
--keepalive try to restart the proxy if it crashed, 保持連接啟動進程會有2個, 一號進程用來監視二號進程, 如果二號進程死掉自動重啟proxy。
–log-level=debug定義log日志級別,由高到低分別有
(error|warning|info|message|debug)
--proxy-lua-script=file指定一個Lua腳本程序來控制mysql-proxy的運行和設置,這個腳本在每次新建連接和腳本發生修改的的時候將重新調用。
--max-open-files:指定最大檔案開啟數為1024,否則會有【could not raise RLIMIT_NOFILE to 8192, Invalid argument (22). Current limit still 1024.】的log訊息出現。
3. 當MySQL主從復制在 show slave status\G 時出現Slave_IO_Running或Slave_SQL_Running 的值不為YES時,,需要首先通過 stop slave 來停止從服務器,然后再進行測試讀寫分離。
4. MySQL-Proxy的rw-splitting.lua腳本在網上有很多版本,但是最准確無誤的版本仍然是源碼包中所附帶的lib/rw-splitting.lua腳本,如果有lua腳本編程基礎的話,可以在這個腳本的基礎上再進行優化;
5. MySQL-Proxy實際上非常不穩定,在高並發或有錯誤連接的情況下,進程很容易自動關閉,因此打開–keepalive參數讓進程自動恢復是個比較好的辦法,但還是不能從根本上解決問題,因此通常最穩妥的做法是在每個從服務器上安裝一個MySQL-Proxy供自身使用,雖然比較低效但卻能保證穩定性;
6. 一主多從的架構並不是最好的架構,通常比較優的做法是通過程序代碼和中間件等方面,來規划,比如單雙server-id號分開寫入等方式來實現兩個或多個主服務器;
7. MySQL-Cluster 的穩定性也不是太好;
8. Amoeba for MySQL 是一款優秀的中間件軟件,同樣可以實現讀寫分離,負載均衡等功能,並且穩定性要大大超過MySQL-Proxy,建議大家用來替代MySQL-Proxy,甚至MySQL-Cluster。
9. mysql proxy不支持old_password。另外也可以通過查看密碼長度的方式來判斷:select length(password) from mysql.user如果長度為16位則是old_password無疑。
10. 安裝了mysql-proxy實現讀寫分離,有master x 1, slave x 2。為了測試failover,停掉了一個slave,然后mysql-proxy會一直報錯,提示無法連接。這個情況比單點的mysql還糟糕,掛掉一個就全掛掉!mysql的工程師給提供了一段代碼,替換掉:
src/network-mysqld-proxy.c的NETWORK_MYSQLD_PLUGIN_PROTO函數可以解決這個問題。network-mysqld-proxy-function.c文件。
(經過測試:我停止掉slave數據庫,proxy的查詢就會轉移到master上,當把slave啟動后,proxy依然在讀master,當有新的鏈接進來的時候才會去讀取slave的數據)
11. 如果在mysql-proxy的機器上也安裝了mysql的話,新手就會在這個時候混亂了,到底要如何進行測試和鏈接呢?比如使用命令:#mysql -u gaizai -p -P4040 -h 192.168.1.147是表示登陸本機的4040端口,使用gaizai帳號,這個帳號可以不是本地mysql的帳號,這樣就比較容易區分了。
12. 在上述環境中,mysql-proxy、mysql-master、mysql-slave三台服務器均存在單點故障。為了避免mysql-proxy單點隱患有兩種方法:一種方法是mysql-proxy配合keepalived做雙機,另一種方法是將mysql-proxy和應用服務安裝到同一台服務器上;為了避免mysql-master單點故障可以使用DRBD+heartbear做雙機;為了避免mysql-slave單點故障可以添加多台mysql-slave,mysql-proxy會自動屏蔽后端發生故障的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. 關於mysql-proxy的啟動和關閉的shell腳本的編寫:
15. 讀寫分離不能回避的問題之一就是延遲,可以考慮Google提供的SemiSyncReplicationDesign補丁。
16. MySQL-Proxy缺省使用的是4040端口,如果你想透明的把3306端口的請求轉發給4040的話,那么可以:iptables -t nat -I PREROUTING -s ! 127.0.0.1 -p tcp --dport 3306 -j REDIRECT --to-ports 4040如果想刪除這條規則,可以把上面例子中的-I換成-D。參考鏈接
17. 當使用bigint 時,mysql_insert_id()存在問題,詳情見手冊,不過對於大多數人而言,bigint基本不會遇到,所以你可以無視這個問題)注:對於這兩個問題,官方BUG庫里有人給出了相應的補丁。
五、錯誤
在執行命令的時候出現了下面的錯誤:
(Figure6:錯誤信息)
could not raise RLIMIT_NOFILE to 8192
這個一個警告級別的錯誤,意思是MySQL Proxy在你的系統上不能把open files limit提升到8192,不過沒關系的,MySQL Proxy依然好好的運行在你的電腦上。
可以通過設置啟動--max-open-files參數解決。
mysql proxy master and slave test
加入--max-open-files=8192后報下面的錯誤:
(Figure7:錯誤信息)
六、疑問與解答
1. 當slave宕機后,mysql-proxy是如何讀取的?(經過測試:我停止掉slave數據庫,proxy的查詢就會轉移到master上,當把slave啟動后,proxy依然在讀master,當有新的鏈接進來的時候才會重新去讀取slave的數據。有時可能需要重啟下mysql-proxy)
2. 如何知道mysql-proxy當前執行的select是在哪台機器上執行的?
3. 當slave宕機一段時間后,如果再次同步master的缺失的數據?
4. 當配置中設置了proxy-read-only-backend-addresses=192.168.1.145:3306
,192.168.1.147:3306類似這樣的兩個slave,如果兩個slave的數據不同步,那么是怎么讀取數據的?# tail -50f /var/tmp/mysql-proxy.log測試
5. 生產環境中除了進行程序調試外,其它不要開啟mysql查詢日志,因為查詢日志記錄了客戶端的所有語句,頻繁的IO操作將會導致mysql整體性能下降。如何設置呢?
6. mysql-proxy.cnf文件中的管理員帳號和密碼有什么用?使用命令進入管理
mysql -u viajarchen -p -P 4041 -h 192.168.1.147 密碼是123123
mysql> select * from proxy_connections;
mysql> select * from proxy_config;
(Figure8:信息)
7. 關於mysql-proxy的啟動和關閉的shell腳本的編寫?測試
8. 對於/usr/share/mysql-proxy/rw-splitting.lua腳本中的
local min_idle_connections = 4 local max_idle_connections = 8應該如何理解?min的話就是要達到這個值的時候才會讀寫分離,那么max的是什么意思呢?最大能有8個鏈接?
9. mysqld是什么意思?是mysql的守護進程!
10. HAProxy和keepalived怎么一起搭建使用?能解決什么問題?
七、參考文獻
ubuntu10.0.4上配置MYSQL主從復制與讀寫分離(MySQL-Proxy)
[MySQL管理] mysql主從復制,讀寫分離 (MySQL Proxy)
MySQL Proxy(官網)
Getting Started with MySQL Proxy(LUA文件介紹)
Read/Write Splitting with MySQL-Proxy(LUA)
MySQL Proxy learns R/W Splitting(牛人)
MySQL-Proxy負載平衡測試遇到的問題及其分析 && MySQL-Proxy工作機制(Lua)
MySQL Proxy(常用命令)
mysql-proxy讀寫分離技術文檔整理【原創】(sysbench測試)
用sysbench(或者super-smack)測試mysql性能
mysql-proxy讀寫分離設置(新建啟動文件mysql-proxy.cnf +log)
MySQL主從復制(Master-Slave)與讀寫分離(MySQL-Proxy)實踐(主從復制數據+經驗分享)
使用MySQL-Proxy讀寫分離時的注意事項(查詢亂碼)
MySQL Proxy快速實現讀寫分離以及負載均衡(啟動腳本)
Mysql-proxy主從搭建讀寫分離全過程(shell腳本啟動)
MYSQL-PROXY測試實例(Lua腳本構建自己的輪詢連接算法+管理MySQL Proxy )