資料庫中間件mysql-proxy細節【mysql官方的中間件】

2022-01-23 架構師之路
一、mysql-proxy簡介

mysql-proxy是mysql官方提供的mysql中間件服務,上遊可接入若干個mysql-client,後端可連接若干個mysql-server,它使用mysql協議,任何連接mysql的上遊無需任何更改即可遷移至mysql-proxy上。

mysql-proxy最基本的用法,就是作為一個請求攔截,請求中轉的中間層:

進一步的,mysql-proxy可以分析與修改請求。攔截查詢和修改結果,需要通過編寫Lua腳本來完成。mysql-proxy允許用戶指定Lua腳本對請求進行攔截,對請求進行分析與修改,它還允許用戶指定Lua腳本對伺服器的返回結果進行修改,加入一些結果集或者去除一些結果集均可。

【SK畫外音:sql攔截與修改,性能分析與監控,讀寫分離,請求路由等各種功能都是通過編寫Lua腳本來完成的,mysql-proxy是個框架,具備很好的擴展性。這個框架提供了6個hook點,能夠讓用戶能夠動態的介入到client與server中的通訊中去。】

二、mysql-proxy命令參數

版本顯示

使用--version參數即可:

./mysql-proxy --version

從輸出可以看到mysql-proxy的版本,以及依賴的glib,libevent,lua的版本

1 mysql-proxy0.8.3

2 chassis: mysql-proxy 0.8.3

3 glib2: 2.16.6

4 libevent: 1.4.13-stable

5 LUA: Lua 5.1.4

8 -- modules

9 proxy: 0.8.3

簡單啟動

mysql-proxy啟動至少需要指定一個後端mysql的ip和埠號,此時帶上--proxy-backend-addresses參數即可:

./mysql-proxy --proxy-backend-addresses=127.0.0.1:3306

指定配置文件啟動

mysql-proxy亦可以指定配置文件啟動,此時帶上--defaults-file來指定配置文件即可:

./mysql-proxy --defaults-file=./mysql-proxy.cnf

mysql-proxy.cnf的格式如下:

1[mysql-proxy]

2proxy-backend-addresses = 127.0.0.1:3306

需要注意,在命令行中參數前需要加入「--」,而在配置文件中則不需要。

尋求幫助

可以使用--help,或者--help-all

./mysql-proxy --help

./mysql-proxy --help-all

Proxy常用選項

選項

說明

proxy-backend-addresses=$host:$port

後端mysql的ip和port,多個以逗號分隔

proxy-read-only-backend-addresses=$host:$port

後端只讀mysql的ip和port,多個以逗號分隔

proxy-skip-profiling=$bool

是否禁用查詢性能剖析

proxy-lua-script=$file_name

lua文件



注意:

如果設置了多個後端mysql,負載均衡策略為round-robin。例如設了A和B兩臺後端,第一個請求轉發到A,第二個請求轉發到B,第三個請求轉發到A,以此類推。

Proxy服務常用選項

選項

說明

proxy-address=$host:$port

mysql-proxy的ip和port,默認port是4040

daemon=$bool

是否使用daemon模式啟動

event-threads=$count

event-handing線程數,默認值是1

keep-alive=$bool

proxy服務崩潰後自動重啟

log-file=$file_name

日誌文件

log-level=$level

日誌級別:error|warning|info|message|debug

log-use-syslog=$bool

日誌使用syslog

max-open-files=$count

最大文件句柄數

pid-file=$file_name

pid文件



典型配置文件示例

1[mysql-proxy]

2

3proxy-address = 127.0.0.1:4040

4 daemon =true

5event-threads = 2

6 keep-alive= true

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

8 log-level= debug

9max-open-files = 1024

10 pid-file =./mysql-proxy.pid

11

12 proxy-lua-script= ./ro-balance.lua

13proxy-backend-addresses = 127.0.0.1:3306

14proxy-skip-profiling = false

啟動過程中提示:

2013-12-28 15:15:49: (critical)mysql-proxy-cli.c:326: loading config from './mysql-proxy.cnf' failed:permissions of ./mysql-proxy.cnf aren't secure (0660 or stricter required)

由於安全要求,必須將配置文件權限設為660(創建人可讀寫,同組人可讀),否則不允許啟動。

三、mysql-proxy腳本編程

如「簡介」中所述,mysql-proxy向用戶提供了6個hook點,讓用戶實現Lua腳本來完成各種功能,這些hook點是以函數的形式提供的,用戶可以實現這些函數,在不同事件、不同操作發生時,做我們期望的事情。

connect_server()

mysql-client向proxy發起連接時,proxy會調用這個函數。用戶可以實現該函數,來做一些負載均衡的事情,例如選擇將要連向那個mysql-server。假設有多個mysql-server後端,而用戶又沒有實現這個函數,proxy默認採用輪詢(round-robin)策略。

read_handshake()

mysql-server向proxy返回「初始握手信息」時,proxy會調用這個函數。用戶可以實現這個函數,來做更多的權限驗證工作。

read_auth()

mysql-client向proxy發送認證報文(user_name, password,database)時,proxy會調用這個函數。

read_auth_result()

mysql-server向proxy返回認證結果時,proxy會調用這個函數。

read_query()

認證完成後,mysql-client每次經過proxy向mysql-server發送query報文時,proxy會調用這個函數。用戶如果要攔截請求,就可以模擬mysql-server直接返回了,當然用戶亦可以實現各種策略,修改請求,路由請求等各種不同的業務邏輯。

read_query_result()

認證完成後,mysql-server每次經過proxy向mysql-client返回query結果時,proxy會調用這個函數。需要注意,如果用戶沒有顯示實現read_query()函數,則read_query_result()函數是不會被調用的。用戶可以在此處實現各種合併策略,或者對結果集進行修改。

【SK畫外音:下圖是一個各hook函數的觸發圖(請注意請求方向)】

【SK繼續畫外音:可以發現,最重要的兩個函數其實是read_query()和read_query_result(),各種sql的改寫與結果集的改寫邏輯,都是在這兩個函數中實現的,更細節的query過程如下圖】

案例一: sql時間統計分析

不妨設mysql-client提交的原sql為:SELECT * FROM City;

proxy可以在read_query()裡將其改寫為:SELECT NOW(); SELECT *FROM City; SELECT NOW();

這樣在返回結果集時,就可以在應用層對sql時間進行記錄,以方便統計分析。

案例二:sql性能統計分析

不妨設mysql-client提交的原sql為:SELECT * FROM City;

proxy可以在read_query()裡將其改寫為: SELECT * FROM City; EXPLAIN SELECT * FROMCity;

這樣在返回結果集時,就可以在應用層對sql性能進行記錄,以方便統計分析。

需要強調的是,這兩個案例,由於proxy在read_query()時對sql進行了改寫,故在read_query_result()時,mysql-server其實返回了比原請求更多的信息,proxy一定要將多餘的信息去掉,再返回mysql-client。多說一句,可以加入一個唯一ID,來對請求sql和返回結果進行配對。

demo

需求:在業務層統計sql日誌

實現:tutorial-basic.lua

1 -- 如果是COM_QUERY,就將內容列印出來

2 functionread_query( packet )

3 if string.byte(packet) == proxy.COM_QUERYthen

4 print("we got a normal query:" .. string.sub(packet, 2))

5 end

6 end

修改配置並重啟proxy:

proxy-lua-script = tutorial-basic.lua

客戶端使用黑黑的窗口連接4040埠的proxy,並進行一系列sql操作,操作序列如下:

mysql -h127.0.0.1 -uroot -P4040

show databases;

use im;

show tables;

select * from user;

quit

通過tutorial-basic.lua,會將上述操作都記錄到日誌中,日誌序列如下:

we got a normal query: select @@version_comment limit1

we got a normal query: show databases

we got a normal query: SELECT DATABASE()

we got a normal query: show tables

we got a normal query: select * from user

【SK畫外音:咦,通過這個日誌我才知道,連上資料庫會默認發一個select @@version_comment limit 1的請求呢。use im;這個請求,為啥變成SELECT DATABASE()了呢?】

四、FAQ

(1)如何實現最簡單的讀寫分離?

shell> mysql-proxy \

--proxy-backend-addresses=10.0.1.2:3306 \

--proxy-read-only-backend-addresses=10.0.1.3:3306

(2)mysql proxy支持所有版本的mysql麼?

只支持mysql5.0+的mysql協議。

(3)如果開啟負載均衡,那事務怎麼辦?所有的query會發往同一臺mysql麼?

如果用戶不專門定製Lua腳本,會發往同一臺mysql,以保證其完整性。

(4)系統上下文切換代價大麼?Lua腳本引入的額外開銷有多大?

Lua很快,對於大部分應用來說,額外開銷很小,原始包(raw packet)開銷大概在400微秒左右。

【SK畫外音:這,,,我不太相信】

(5)Lua腳本可以動態加載麼?

升級了Lua腳本,連接建立後才會讀取新的喲。

(6)如果proxy和mysql部署在一臺機器上,有什麼需要建議的呢?

proxy單獨部署也可以,和mysql部署在同一臺機器上也可以。相比mysql而言,proxy不怎麼佔CPU和內存,其性能損耗可以忽略不計。

【SK畫外音:這,,,性能損耗可以忽略,這我也不信】

(7)Lua腳本是預讀到內存裡的吧?還是說每次都要到文件系統裡讀?

客戶端連接過來時,或者腳本更新時會讀取,其他的時候都讀內存喲。

(8)加入客戶端連上來,出發了connect_server()函數,Lua腳本能連接多個mysql麼?

可以,使用指引裡有樣例代碼喲。

(9)proxy可以處理SSL連接麼?

不可以,作為中間人,不能處理加密信息。

(10)proxy不會獲取和保存我的明文密碼吧?

不會,也獲取不到。mysql協議不允許密碼以明文傳輸,傳輸的都是加密後的密文。

(11)有隔離問題,調試問題的工具麼?如果請求出錯了,我怎麼知道錯誤發生在mysql客戶端,還是mysql服務端,還是proxy呢?

你可以自己在proxy裡設置debug腳本進行調試,例如設置斷點什麼的。

(12)瞧你官網吹的,有哪個大網站用了mysql-proxy麼?請求量是什麼級別?

這問題問的,作為官網我,,,蓋亞在線(http://www.gaiaonline.com/) 就是用的mysql-proxy喲,qps可以到2400。

【SK畫外音:這是個外國的遊戲網站,頁面好醜啊。】

(13)如果我在Lua腳本用使用LuaSocket可以麼?

大哥,這可能引起阻塞的,強烈不建議這樣。

都讀到這了,幫忙隨手轉發一個唄,原創不易。

下一期,將介紹阿里的資料庫中間件。

回復大於10的隨機整數,自動獲取隨機好文。

相關焦點

  • 中間件mysql-proxy的一些細節
    mysql的中間件有mysql-proxy\Atlas等。
  • MySQL-ProxySQL中間件(一)
    ProxySQLProxySQL作為一款強大的中間件為MySQL的架構提供了有力的支持。目前可以很好的支持 Master Slave\ MGR \ PXC等,並提供連接池、讀寫分離、日誌記錄等功能,當然還有很多其他實用功能,這裡不一一列舉了。
  • 運維日記|ADO.NET訪問MySQL資料庫
    動手之前,你肯定要首先準備工具,你要有個Visual Studio作為開發工具吧,沒有的童鞋,這裡這裡:https://msdn.itellyou.cn/然後,既然要訪問MySQL資料庫,你肯定要有個MySQL資料庫吧,沒有的童鞋,這裡這裡:https://dev.mysql.com/downloads/mysql/最後,作為訪問資料庫所需要的引用組件,我們需要安裝
  • 詳解MySQL|MySQL中間件DBLE-第五章 後端資料庫相關特性-愛可生
    本期推送的內容為DBLE的高級特性:後端資料庫的相關特性。本節提綱本節內容是對後端的資料庫相關特性重點解析。後端資料庫的相關特性主要從讀寫分離、連接管理、上下文同步以及高可用故障切換四個方面拆分講解;讀寫分離與高可用故障切換是社區同學反饋中需求最大的部分,本節內容十分詳盡的講解了大家關注的關鍵技術點及相關處理細節,有助於增進對分布式應用的相關理解。
  • PHP資料庫編程之MySQL優化策略概述
    2、如果我們們經對資料庫中的數據行進行增刪,那麼會出現數據ID過大的情況,用ALTER TABLE tablename AUTO_INCREMENT=N,使自增ID從N開始計數。3、對int類型添加 ZEROFILL 屬性可以對數據進行自動補04、導入大量數據時最好先刪除索引再插入數據,再加入索引,不然,mysql會花費大量時間在更新索引上。
  • SpringBoot + MyBatis + MySQL讀寫分離實踐!
    引言讀寫分離要做的事情就是對於一條SQL該選擇哪個資料庫去執行,至於誰來做選擇資料庫這件事兒,無非兩個,要麼中間件幫我們做,要麼程序自己做。因此,一般來講,讀寫分離有兩種實現方式。第一種是依靠中間件(比如:MyCat),也就是說應用程式連接到中間件,中間件幫我們做SQL分離;第二種是應用程式自己去做分離。
  • 技術分享 | MySQL 8.0 代理用戶使用
    我給了一個大家都很討厭的答案:去看 MySQL8.0 官方手冊吧。正文其實 MySQL 版本發展到 8.0 ,已經完全沒有必要使用 proxy  用戶這個功能了,可以用角色完美替代。[mysqld] check_proxy_users=ON mysql_native_password_proxy_users=ON使用 proxy 用戶功能之前,需要安裝 mysql_no_login 插件,阻止隱藏在 proxy 用戶下的真實用戶登錄
  • MySQL教程之MySQL定時備份資料庫
    一、MySQL數據備份1.1、 mysqldump命令備份數據在MySQL中提供了命令行導出資料庫數據以及文件的一種方便的工具mysqldump,我們可以通過命令行直接實現資料庫內容的導出dump,首先我們簡單了解一下mysqldump命令用法:
  • SpringBoot+MyBatis+MySQL讀寫分離(實例)
    引言讀寫分離要做的事情就是對於一條SQL該選擇哪個資料庫去執行,至於誰來做選擇資料庫這件事兒,無非兩個,要麼中間件幫我們做,要麼程序自己做。因此,一般來講,讀寫分離有兩種實現方式。第一種是依靠中間件(比如:MyCat),也就是說應用程式連接到中間件,中間件幫我們做SQL分離;第二種是應用程式自己去做分離。
  • PHP MySQL資料庫編程
    1.1 mysql擴展連接允許PHP應用與MySQL資料庫交互的早期擴展。mysql擴展提供了一個面向過程 的接口;並且是針對MySQL4.1.3或更早版本設計的。因此,這個擴展雖然可以與MySQL4.1.3或更新的資料庫服務端 進行交互,但並不支持後期MySQL服務端提供的一些特性。
  • Mysql資料庫的使用方法
    你們讚賞就是對小編的鼓勵,都是你們的心意,小編收到了,在這邊感謝你們,謝謝    現在看軟體測試的招聘要求,基本都是要求會資料庫這一塊的,薪水越高所具備的技能也要越多,而資料庫知識則是一項必備技能了,所以今天小編就好好的普及下資料庫知識方面的基本使用方法!
  • ubuntu mysql 服務管理以及資料庫操作
    MySQL是一種關係型資料庫管理系統(數據保存在不同的表中而不是將所有數據放在同一個大倉庫內,訪問速度以及靈活性有明顯提高 ),支持標準的sql語言,並且mysql是開源的,不需要支付額外的費用,所以當下非常流行 本文介紹 ubuntu下 mysql 服務的安裝與管理以及mysql資料庫的簡單使用
  • MYSQL資料庫操作案例
    MySQL 創建資料庫CREATE DATABASE 資料庫名;以下命令簡單的演示了創建資料庫的過程,數據名為 RUNOOB:[root@host]# mysql -u root -p >Enter password:****** # 登錄後進入終端mysql> create DATABASE RUNOOB;MySQL 刪除資料庫drop database <資料庫名>;
  • 詳解PHP操作MySQL資料庫
    ('資料庫連接失敗,錯誤信息:'.mysql_error()); echo $connect;//Resource id #2? $connect = mysql_connect(DB_HOST,DB_USER,DB_PWD) or die('資料庫連接失敗,錯誤信息:'.mysql_error()); //選擇指定資料庫 mysql_select_db(DB_NAME,$connect) or die('資料庫連接錯誤,錯誤信息:'.mysql_error());//將表名字故意寫錯
  • ProxySQL + MySQL MGR讀寫分離架構的Sysbench只讀壓測報告
    在大量並發讀請求、讀多寫少的業務場景下,本文利用 Sysbench 性能測試工具,調研基於【負載均衡 + ProxySQL Cluster + MySQL MGR 的讀寫分離架構】能否有效利用橫向擴展的 MySQL 實例的讀能力,並最終提高應用系統 QPS。
  • python對mysql資料庫的操作(一)
    本文章介紹python對mysql資料庫的基本操作,以及編寫一個模擬用戶的註冊。
  • 「資料庫分享」MySQL資料庫優化
    「主從分離」(用什麼中間件?)並沒有從細化到定量的層面去分析.如qps提高了%N? 有沒有減少文件排序?語句的掃描行數減少了多少?ps:QPS一般指每秒查詢率。調用存儲過程可以簡化應用程式開發人員的工作,減少與資料庫伺服器之間的通信,對於提升數據操作的性能是有幫助的/數據分區MySQL支持做數據分區,通過分區可以存儲更多的數據、優化查詢,獲得更大的吞吐量並快速刪除過期的數據。關於這個知識點建議大家看看MySQL的官方文檔。
  • 基於MySQL的高性能資料庫應用開發
    在NT的控制臺窗口中,進入MySQL的執行目錄(c:\mysql\bin),執行 ---- C:\mysql\bin\mysqld-shareware --standalone ---- 則MySQL的資料庫引擎啟動。
  • mysql外鍵怎麼用?Mysql資料庫外鍵的使用介紹
    在之前的文章中,已經給大家介紹了mysql外鍵的基礎定義以及外鍵創建的方法,需要的朋友可以先閱讀上篇文章。想必大家應該對mysql外鍵都有一定的了解了。下面我們就舉個簡單例子給大家介紹Navicat(資料庫管理工具)中關於mysql外鍵的基本使用操作。Navicat是一套快速、可靠並價格相當便宜的資料庫管理工具,專為簡化資料庫的管理及降低系統管理成本而設。
  • 如何使用MySQL資料庫
    一、訪問MySQL資料庫1.登錄到MySQL伺服器經過安裝後的初始化,MySQL資料庫默認管理員用戶名為root,密碼為空。若要以未設置密碼的root用戶登錄本機的MySQL資料庫,可執行以下操作:上面是沒密碼登錄,那麼如何設置資料庫用戶的密碼呢?在linux命令環境中,一般使用mysqladmin工具來設置密碼。