mysql_proxy工作原理和配置引數

myownstars發表於2015-02-10
 

Mysql伺服器和客戶端建立連線過程如下

認證透過,客戶端發起查詢請求,伺服器可能返回3種結果;


圖片來源http://blog.sina.com.cn/s/blog_98cb2d960100zs0e.html

Mysql-proxy作為一個代理,工作於mysql客戶端和伺服器之間(對兩者皆透明)


http://dev.mysql.com/doc/mysql-proxy/en/mysql-proxy-scripting-injection.html

 

首先MySQL Proxy以伺服器的身份接受客戶端請求,根據配置對這些請求進行分析處理,然後以客戶端的身份轉發給相應的後端資料庫伺服器,再接受伺服器的資訊,返回給客戶端,所以MySQL Proxy
要同時實現客戶端和伺服器的協議。

由於要對客戶端傳送過來的SQL語句進行分析,還需要包含一個SQL解析器。可以說MySQL Proxy相當於一個輕量級的MySQL了,實際上,MySQL Proxyadmin server是可以接受SQL來查詢狀態資訊的。


MySQL Proxy透過lua指令碼來控制連線轉發,主要的函式都是配合MySQL Protocol各個過程的:

    * connect_server()     // 接收到Client的連線請求時呼叫

    * read_handshake()   // 讀取server發起的handshake資訊時呼叫

    * read_auth()               // 讀取Client的認證資訊時呼叫

    * read_auth_result() // 讀取認證結果時呼叫

    * read_query()            // 讀取Clientquery請求時呼叫

  * read_query_result()   //讀取query結果時呼叫



具體功能

   1.資料連線的故障轉移

   2.資料連線的負載均衡

   3.攔截查詢(取通訊包,實現關鍵字替換)

   4.重寫查詢(例如,強制密碼度等規則)

   5.新增額外的查詢(附)

   6.刪除,修改或者新增返回到客戶端的 SQL結果集



配置檔案

mysql-proxy.cnf(許可權設為660)

 [mysql-proxy]

    admin-username=root

    admin-password=123456

    admin-lua-script=/usr/local/lib/admin.lua

    proxy-read-only-backend-addresses=192.168.2.115

    proxy-backend-addresses=192.168.2.117

    proxy-lua-script=/usr/local/lib/rw-splitting.lua

    log-file=/var/log/mysql-proxy.log

    log-level=debug

    daemon=true

keepalive=true

proxy-lua-script,指定一個Lua指令碼來控制mysql-proxy的執行和設定,這個指令碼在每次新建連線和指令碼發生修改的的時候將重新呼叫

keepalive,額外建立一個程式專門監控mysql_proxy程式,當mysql_proxy crash予以重新啟動;


啟動

/usr/local/mysql-proxy/bin/mysql-proxy -P 192.168.2.112:3306 --defaults-file=/etc/mysql-proxy.cnf



讀寫分離

proxy-lua-script指定為rw-splitting.lua時,mysql_proxy會對客戶端傳入的sql執行讀寫分離;

同一個事務,DML傳輸給backendselect則被傳到read-only-backend

Lua指令碼預設最小4個最大8個以上的客戶端連線才會實現讀寫分離(這是因為mysql-proxy會檢測客戶端連線當連線沒有超過min_idle_connections預設值時,不會進行讀寫分離,即查詢操作會發生到Master上),現改為最小1個最大2個,我們用vim修改/usr/local/lib/rw-splitting.lua指令碼,改動內容如下所示:

    if not proxy.global.config.rwsplit then

            proxy.global.config.rwsplit = {

                    min_idle_connections = 1,

                    max_idle_connections = 2,

   

                    is_debug = false

            }

    end

 

read_query()函式內有這麼一個判斷

if stmt.token_name == "TK_SQL_SELECT" then 

這個語句的作用就是判斷sql語句是不是以SELECT開始的,如果是查詢的話,接下來會有這麼個語句

local backend_ndx = lb.idle_ro() 

lb.idle_ro() 是透過 local lb = require("proxy.balance") 引入的balance.lua檔案

這個函式的作用就是選擇使用哪個讀伺服器,並返回伺服器的index:max_conns_ndx

如何選擇伺服器呢? 它透過迴圈遍歷所有伺服器,然後選出一個客戶端連線(s.connected_clients)最少的伺服器,這樣在一定程度上實現負載均衡

    function idle_ro()  

        local max_conns = -1 

        local max_conns_ndx = 0 

     

        for i = 1, #proxy.global.backends do 

            local s = proxy.global.backends[i] 

            local conns = s.pool.users[proxy.connection.client.username] 

            -- pick a slave which has some idling connections 

            if s.type == proxy.BACKEND_TYPE_RO and s.state ~= proxy.BACKEND_STATE_DOWN and conns.cur_idle_connections > 0 then 

                if max_conns == -1 or s.connected_clients < max_conns then 

                    max_conns = s.connected_clients 

                    max_conns_ndx = i 

                end 

            end

        end 

     

        return max_conns_ndx 

    end

http://blog.csdn.net/clh604/article/details/8906022




failover

利用mysql_proxy實現failover

缺點:mysql_proxy單點故障;

原理:預設連線A,如果A宕掉則連線BA啟動後再連線到A

編寫failover指令碼

vi $mysql-proxy_path/share/doc/mysql-proxy/mysql_failover.lua

function connect_server()

    for i = 1, #proxy.backends do

        local s = proxy.backends[i]

        print ("s.state:" + s.state)

        if s.state ~= proxy.BACKEND_STATE_DOWN then

            proxy.connection.backend_ndx = i

            print ("connecting to " .. i)

            return

        end

    end

end

function read_query(packet)

    for i = 1, #proxy.backends do

        local s = proxy.backends[i]

        print ("s.state:" + s.state)

        if s.state ~= proxy.BACKEND_STATE_DOWN then

            proxy.connection.backend_ndx = i

            print ("connecting to " .. i)

            return

        end

    end

end

啟動mysql-proxy

$mysql-proxy_path/bin/mysql-proxy --proxy-address=:4040 --proxy-lua-script=$mysql-proxy_path/share/doc/mysql-proxy/mysql_failover.lua --proxy-backend-addresses=$A:3306 --proxy-backend-addresses=$B:3306 --log-level=error  --log-file=$mysql-proxy_path/mysql-proxy.log --keepalive --proxy-fix-bug-25371

此時客戶端直接連線mysql-proxy即可;

http://www.cnblogs.com/lenolix/archive/2013/04/06/3003226.html


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15480802/viewspace-1432659/,如需轉載,請註明出處,否則將追究法律責任。

相關文章