Mysql自动超时重连导致的中文乱码问题

Mysql自动超时重连导致的中文乱码问题

     今天有客户反应从自选股服务器获取的自定义板块中文名称乱码,之前一直都是正常的。看到乱码两字,头脑中首先冒出来的就是查看mysql数据库中的编码集,输入SHOW VARIABLES LIKE ‘char%’;命令查看编码全部都是utf编码,没有问题。
在这里插入图片描述
     再查看服务器日志:
在这里插入图片描述
     服务器运行过程中没有进行重启,也没有错误日志,但是日志中显示有长达八个多小时(日志打印的是0时区的,把这个时间加上8小时就是我们的北京时间)没有进行过数据流的交互,因为我们是股票行情软件,在凌晨到早上9点开市前基本不会有活跃的用户,看到这,立马想到了mysql的自动超时重连导致之前的编码设置无效。

     使用mysql C API时,由于数据库中的编码都是utf8的,因此我们也需要在调用api时指定连接字符集,而这个是通过SET NAMES来实现的。由于我们的服务器连接数据库时通过mysql_options指定了MYSQL_OPT_RECONNECT超时重连选项,在每次执行sql语句之前先执行一次mysql_ping,来自动检查重连。当开启了自动重连,连接断开时,会尝试重新连接数据库,重新连接虽然好用,但是也会存在以下问题:

  • 任何活动的交易都被回滚,autocommit模式被置为reset。
  • 所有表锁都释放
  • 所有临时表是关闭(撤消)
  • Session variables are reinitialized to the values of the corresponding variables.会话变量被重新初始化为相应的变量。 这也影响那些隐式声明的变量,比如使用SET NAMES。This also affects variables that are set implicitly by statements such as SET NAMES.
  • 用户变量设置都将丢失。
  • 编制报表释放。
  • 句柄变量被关闭。
  • LAST_INSERT_ID()被重置为0 。
  • 使用GET_LOCK()获得的锁被释放

     第四点和第五点可以一起理解,即当mysql的连接进行自动重连时,之前针对一个连接进行的用户设置都将失效,比如使用SET NAMES。而我们服务器恰好是通过mysql_query(pSqlCon, “SET NAMES UTF8”);实现的。

     那如何解决重连之后的编码设置问题呢?mysql c api还提供了另一种方式:MYSQL_SET_CHARSET_NAM。初始化数据库句柄后马上用mysql_options设定MYSQL_SET_CHARSET_NAME属性为utf8,这样就不用显式地用 SET NAMES语句指定连接字符集,且用mysql_ping重连断开的长连接时也会把连接字符集重置为utf8。代码如下:
在这里插入图片描述
     问题解决了,虽然是一个较常见的坑,但还是被自己踩到了。针对mysql的自动重连和mysql的字符集做以下几点总结:
1, my.cnf中的default_character_set设置只影响mysql命令连接服务器时的连接字符集,不会对使用libmysqlclient库的应用程序产生任何作用,因此我们在调用MySQL c api时还需要指定连接字符集。

2, mysql的默认连接超时时间是28800s,也就是八小时,通过命令show variables like ‘%timeout%’;可以查看wait_timeout字段。也可以通过修改/etc/my.cnf中的wait_timeout值来解决这个问题,但是不能根治。

3, mysql默认编码是latin1,当数据库和连接字符集都使用latin1时,大部分情况下都可以解决乱码问题,但是却无法以字符为单位来进行SQL操作,一般情况下将数据库和连接字符集都置为utf8是较好的选择

4, 通过设置MYSQL_OPT_RECONNECT开启mysql的自动重连功能后,针对mysql的相关变量尽可能都使用mysql_options结合mysql_option枚举进行设置,避免重连后的设置无效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MySQL_错误代码以及出错信息对照: 0101 属于其他进程的专用标志。 0102 标志已经设置,无法关闭。 0103 无法再次设置该标志。 0104 中断时无法请求专用标志。 0105 此标志先前的所有权已终止。 0106 请将软盘插入驱动器 %1。 0107 后续软盘尚未插入,程序停止。 0108 磁盘正在使用或已由其他进程锁定。 0109 管道已经结束。 0110 系统无法打开指定的设备或文件。 0111 文件名太长。 0112 磁盘空间不足。 0113 没有其他可用的内部文件标识符。 0114 目标内部文件标识符不正确。 0117 该应用程序所运行的 IOCTL 调用不正确。 0118 校验写入的开关参数值不正确。 0119 系统不支持所请求的命令。 0120 该系统上不支持此功能。 0121 标记已超时。 0123 文件名、目录名或卷标语法错误。 0124 系统调用层不正确。 0125 磁盘没有卷标。 0126 找不到指定的模块。 0127 找不到指定的过程。 0128 没有要等候的子进程。 0129 模式下运行。 0130 试图使用操作(而非原始磁盘I/O)的已打开磁盘分区的文件句柄。 0131 试图将文件指针移至文件开头之前。 0132 无法在指定的设备或文件中设置文件指针。 0133 对于包含已连接驱动器的驱动器,不能使用 JOIN 或 SUBST 命令。 0134 试图在已经连接的驱动器上使用 JOIN 或 SUBST 命令。 0135 试图在已经替换的驱动器上使用 JOIN 或 SUBST 命令。 0136 系统试图删除尚未连接的驱动器的 JOIN。 0137 系统试图删除尚未替换的驱动器的替换项。 0138 系统试图将驱动器连接到已连接的驱动器下的目录。 ... ...

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Simple Simple

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值