使用MySQL-Proxy读写分离时的注意事项

在阅读本文前最好先安装好MySQL-Proxy,并配置好MySQL主从服务器

密码

MySQL-Proxy不支持老的密码加密方式,所以如果你使用的是老版本的MySQL,或者启用了old_passwords选项的话,则可能会出现错误:

Error 2013: lost connection to MySQL server during query

此时最好的修复方法就是使用密码加密方式,如果你的用户表也是老式的,可能需要先运行源代码里scripts目录下的mysql_fix_privilege_tables脚本升级表结构。有时候客观情况可能不允许立刻进行升级操作,此时可以为MySQL-Proxy专门建立一个密码为空的用户(通过主机限制访问),因为不管是新的密码加密方式还是旧的密码加密方式,空密码都同样是一个空字符串,这样就规避了密码加密的问题。

字符

连接上MySQL-Proxy后,执行查询时,随机出现乱码。出现此问题的原因是当我们使用MySQL-Proxy读写分离时,通常会有多个后端服务器,客户端发出查询请求时,一般会先发出一条类似”SET NAME gbk”的语句来声明客户端编码,然后再发出实际查询的SQL语句,但MySQL-Proxy可能会把这两条语句分发给不同的后端服务器,于是就出现了乱码。

解决方法是强行指定后端服务器的字符编码:

init-connect=’SET NAME gbk’
skip-character-set-client-handshake

如果使用init-connect,则需要注意操作用户不能有SUPER权限,否则此选项无效。

即便做好了以上的设置后,还有可能会出现乱码,比如说数据库是gbk的,当我们用PHPMyAdmin连接MySQL-Proxy时,查询还是会出现乱码,不过这是正常的!因为PHPMyAdmin使用的是utf8编码,它发出的“SET NAMES utf8”语句被skip-character-set-client-handshake屏蔽了,所以出现乱码。

进程

MySQL-Proxy偶尔会出现进程崩溃的情况,具体原因不明。

新版的MySQL-Proxy为了应付这个问题加入了一个keepalive选项(try to restart the proxy if it crashed),不过现在很多人用的还是旧版的MySQL-Proxy,此时可以利用init来实现类似keepalive的效果:

编写脚本/usr/local/sbin/mysql-proxy.sh,加入以下内容(具体写法视安装情况而定):

LUA_PATH=”/usr/local/mysql-proxy/share/mysql-proxy/?.lua” \
/usr/local/mysql-proxy/sbin/mysql-proxy \
–proxy-backend-addresses=192.168.0.1:3306 \
–proxy-read-only-backend-addresses=192.168.0.2:3306 \
–proxy-lua-script=/usr/local/mysql-proxy/share/mysql-proxy/rw-splitting.lua

修改inittab:

vi /etc/inittab

加入以下内容:

mp:12345:respawn:/usr/local/sbin/mysql-proxy.sh

然后让init重新读取inittab内容:

kill -HUP 1

系统会自动检测/usr/local/sbin/mysql-proxy.sh是否正在运行,如果没有就自动运行。

需要注意的是在编写mysql-proxy.sh脚本的时候,不要加入–daemon选项,否则/usr/local/sbin/mysql-proxy.sh一运行就结束了,系统会不停的尝试运行脚本,从而在/var/log/message里留下大量的错误信息(init: Id “mp” respawning too fast: disabled for 5 minutes)。

脚本

MySQL-Proxy读写分离的功能是通过lua脚本(rw-splitting.lua)实现的,但是这个脚本年久失修,问题多多,比如说使用时可能会出现:

ERROR 1105: can’t change DB to on slave rw-splitting.lua。

出现这个问题的原因在于当客户端发出查询时,MySQL-Proxy会比较当前客户端所处数据库和服务器所处数据库是否一致,如果不一致则会在服务端尝试执行一个类似”USE 数据库”的操作,一个可能性是主从服务器的数据库结构不同,在USE一个不存在的数据库的时候自然会出错,还有一个原因有些查询操作并没有所处数据库这个上下文,比如说SHOW DATABASES这个查询,并不需要事先“USE 数据库”,只要连上服务器就可以执行,这时候如果还尝试通过客户端和服务端所处的数据库,出错就再所难免。

rw-splitting.lua恰恰没有屏蔽后者说描述的情况,修复方法如下,在合适的位置加入粗体代码,

    276         if cmd.type ~= proxy.COM_INIT_DB and
    277            c.default_db and c.default_db ~= “” and c.default_db ~= s.default_db then
    278                 print(“    server default db: ” .. s.default_db)
    279                 print(“    client default db: ” .. c.default_db)
    280                 print(“    syncronizing”)
    281                 proxy.queries:prepend(2, string.char(proxy.COM_INIT_DB) .. c.default_db)
    282         end

在lua中,~=是不等于的意思,另外,单纯的空字符串”"用在if里是true,所以单靠 c.default_db不够。

另外需要注意的是,新版MySQL-Proxy里数据结构发生了变化,但是rw-splitting.lua还没有做出相应的调整,需要按照数据结构的变化做出适当的修改,可以参考作者的描述操作。值得期待的是现在有了专门的MySQL-Proxy-Lua-Scripts项目,希望开发进度能跟上来。

觉得文章有用?立即: 和朋友一起 共学习 共进步!

猜您喜欢

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>