设为首页 收藏本站
查看: 626|回复: 0

[经验分享] 一个支持主从,事务以及连接池功能的mysql-proxy脚本

[复制链接]

尚未签到

发表于 2016-10-24 01:03:25 | 显示全部楼层 |阅读模式
  看了点例子,根据mysql-proxy里的keepalive例子修改了一个支持主从分离,事务到主库,非事务查询到从库,以及连接断开时自动回滚的脚本,分享一下。
  
  --[[ $%BEGINLICENSE%$Copyright (C) 2007-2008 MySQL AB, 2008 Sun Microsystems, IncThis program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; version 2 of the License.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA$%ENDLICENSE%$ --]]--[[--]]----- a flexible statement based load balancer with connection pooling---- * build a connection pool of min_idle_connections for each backend and --   maintain its size-- * reusing a server-side connection when it is idling-- --- config---- connection poollocal min_idle_connections = 4local max_idle_connections = 8-- debuglocal is_debug = true--- end of config----- read/write splitting sends all non-transactional SELECTs to the slaves---- is_in_transaction tracks the state of the transactionslocal is_in_transaction = 0--- -- get a connection to a backend---- as long as we don't have enough connections in the pool, create new connections--function connect_server() -- make sure that we connect to each backend at least ones to -- keep the connections to the servers alive---- on read_query we can switch the backends again to another backendif is_debug thenprint()print("[connect_server] ")endlocal least_idle_conns_ndx = 0local least_idle_conns = 0for i = 1, #proxy.global.backends dolocal s = proxy.global.backendslocal pool     = s.pool -- we don't have a username yet, try to find a connections which is idlinglocal cur_idle = pool.users[""].cur_idle_connectionsif cur_idle == nil thencur_idle = 0endif is_debug thenprint("  [".. i .."].connected_clients = " .. s.connected_clients)print("  [".. i .."].idling_connections = " .. cur_idle)print("  [".. i .."].type = " .. s.type)print("  [".. i .."].state = " .. s.state)endif s.state ~= proxy.BACKEND_STATE_DOWN then-- try to connect to each backend once at leastif cur_idle == 0 thenproxy.connection.backend_ndx = iif is_debug thenprint("  [".. i .."] open new connection")endreturnend-- try to open at least min_idle_connectionsif least_idle_conns_ndx == 0 or( cur_idle < min_idle_connections and cur_idle < least_idle_conns ) thenleast_idle_conns_ndx = ileast_idle_conns = s.idling_connectionsif least_idle_conns == nil thenleast_idle_conns = 0endendendendif least_idle_conns_ndx > 0 thenproxy.connection.backend_ndx = least_idle_conns_ndxendif proxy.connection.backend_ndx > 0 then local s = proxy.global.backends[proxy.connection.backend_ndx]local pool     = s.pool -- we don't have a username yet, try to find a connections which is idlinglocal cur_idle = pool.users[""].cur_idle_connectionsif cur_idle >= min_idle_connections then-- we have 4 idling connections in the pool, that's good enoughif is_debug thenprint("  using pooled connection from: " .. proxy.connection.backend_ndx)endreturn proxy.PROXY_IGNORE_RESULTendendif is_debug thenprint("  opening new connection on: " .. proxy.connection.backend_ndx)end-- open a new connection end--- -- put the successfully authed connection into the connection pool---- @param auth the context information for the auth---- auth.packet is the packetfunction read_auth_result( auth )if auth.packet:byte() == proxy.MYSQLD_PACKET_OK then-- auth was fine, disconnect from the serverproxy.connection.backend_ndx = 0elseif auth.packet:byte() == proxy.MYSQLD_PACKET_EOF then-- we received either a -- -- * MYSQLD_PACKET_ERR and the auth failed or-- * MYSQLD_PACKET_EOF which means a OLD PASSWORD (4.0) was sentprint("(read_auth_result) ... not ok yet");elseif auth.packet:byte() == proxy.MYSQLD_PACKET_ERR then-- auth failedendend--- -- read/write splittingfunction read_query( packet ) if is_debug thenprint("[read_query]")print("  authed backend = " .. proxy.connection.backend_ndx)print("  used db = " .. proxy.connection.client.default_db)endif packet:byte() == proxy.COM_QUIT then-- don't send COM_QUIT to the backend. We manage the connection-- in all aspects.proxy.response = {type = proxy.MYSQLD_PACKET_OK,}if is_in_transaction thenprint("  transaction on, rollback now")proxy.queries.append(1, string:char(proxy.COM_QUERY) .. "ROLLBACK", { resultset_is_needed = false}) endreturn proxy.PROXY_SEND_RESULTendif proxy.connection.backend_ndx == 0 thenif is_debug thenprint("  no connection, select now")endis_master = trueif packet:byte() == proxy.COM_QUERY thencommand = packet:sub(2, 7)print("  command:" .. command)if string.lower(command) == "select" thenprint("  session not in transaction, select go to slave")is_master = falseendend-- we don't have a backend right now-- -- let's pick a master as a good defaultfor i = 1, #proxy.global.backends dolocal s = proxy.global.backendslocal pool     = s.pool -- we don't have a username yet, try to find a connections which is idlinglocal cur_idle = pool.users[proxy.connection.client.username].cur_idle_connectionsif cur_idle > 0 and s.state ~= proxy.BACKEND_STATE_DOWN thenif s.type == proxy.BACKEND_TYPE_RW and is_master == true thenproxy.connection.backend_ndx = ibreakelseif s.type == proxy.BACKEND_TYPE_RO and is_master == false thenproxy.connection.backend_ndx = ibreakendendendendif is_debug thenprint("  connection:" .. proxy.connection.backend_ndx)endif true or proxy.connection.client.default_db and proxy.connection.client.default_db ~= proxy.connection.server.default_db then-- sync the client-side default_db with the server-side default_dbproxy.queries:append(2, string.char(proxy.COM_INIT_DB) .. proxy.connection.client.default_db,  { resultset_is_needed = true })endproxy.queries:append(1, packet,  { resultset_is_needed = true })return proxy.PROXY_SEND_QUERYend----- as long as we are in a transaction keep the connection-- otherwise release it so another client can use itfunction read_query_result( inj ) local res      = assert(inj.resultset)local flags    = res.flagsif inj.id ~= 1 then-- ignore the result of the USE <default_db>return proxy.PROXY_IGNORE_RESULTendis_in_transaction = flags.in_transif not is_in_transaction then-- release the backendproxy.connection.backend_ndx = 0endend--- -- close the connections if we have enough connections in the pool---- @return nil - close connection --         IGNORE_RESULT - store connection in the poolfunction disconnect_client()if is_debug thenprint("[disconnect_client]")endif proxy.connection.backend_ndx == 0 then-- currently we don't have a server backend assigned---- pick a server which has too many idling connections and close onefor i = 1, #proxy.global.backends dolocal s = proxy.global.backendslocal pool     = s.pool -- we don't have a username yet, try to find a connections which is idlinglocal cur_idle = pool.users[proxy.connection.client.username].cur_idle_connectionsif s.state ~= proxy.BACKEND_STATE_DOWN andcur_idle > max_idle_connections then-- try to disconnect a backendproxy.connection.backend_ndx = iif is_debug thenprint("  [".. i .."] closing connection, idling: " .. cur_idle)endreturnendendendend

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-290245-1-1.html 上篇帖子: Apache+php+mysql在windows下的安装与配置图解(最新版)1/3 下篇帖子: MySQL查询优化系列讲座之数据类型与效率 (转)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表