前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL中的2个小问题

MySQL中的2个小问题

作者头像
AsiaYe
发布2019-12-19 15:25:22
1.3K1
发布2019-12-19 15:25:22
举报
文章被收录于专栏:DBA随笔DBA随笔

MySQL中的2个小问题

今天晚上,在一个单机多实例的环境上,发生了一个错误,看着比较奇怪,之前也遇到过,但是没有留意,今天花了一点时间,搞了一下,问题得到了解决,跟大家分享一下。

01

错误信息无法显示

问题描述:

ERROR 1238 (HY000): Unknown error 1238

我们知道,当我们在MySQL中执行一个SQL命令的时候,如果我们的命令写错了,MySQL会给我们进行报错。我遇到的问题就是在单机多实例的环境下面,报错的信息缺失,如上所示,只有一个error code,以前碰到这个问题,都是从MySQL的官方文档中去查这个error code对应的错误是什么,(补充一下官网的error code链接)今天实在是受不了了,查了一下这个问题,先从错误日志入手吧,我发现日志中的内容都是这样的:

代码语言:javascript
复制
2019-12-17T12:47:14.815692Z 0 [Note]
2019-12-17T12:47:14.816961Z 0 [Note]
2019-12-17T12:47:14.816973Z 0 [Note]
2019-12-17T12:47:14.817727Z 0 [Note]
2019-12-17T12:47:14.867818Z 0 [Note]
2019-12-17T12:47:14.868658Z 0 [Note]
2019-12-17T12:47:14.869041Z 0 [Note]
2019-12-17T12:47:21.682618Z 0 [Note]

很明显,日志中也没有打出来错误信息,这应该是错误信息由于某种原因不能显示了。再查看了历史的err日志关键字,如下:

代码语言:javascript
复制
[root@ log]# cat mysql.err |grep err    
[Warning] The syntax '--log_warnings/-W' is deprecated and will be removed in a future release. Please use '--log_error_verbosity' instead.
[Warning] The syntax '--log_warnings/-W' is deprecated and will be removed in a future release. Please use '--log_error_verbosity' instead.
[ERROR] Can't read from messagefile '/usr/local/mysql-5.5.19-linux2.6-x86_64/share/english/errmsg.sys'

发现了一行比较关键的字样,就是messagefile无法从文件errmsg.sys中读取,因为路径是5.5.19版本的,这一点引起了我的注意,使用\s命令查看了一下线上的数据库版本:

代码语言:javascript
复制
/usr/local/mysql/bin/mysql  Ver 14.14 Distrib 5.5.19, for linux2.6 (x86_64) using readline 5.1

Connection id:          3525
Current database:
Current user:           dba_admin@127.0.0.1
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.7.16-10-log Percona Server (GPL), Release , Revision a0c7d0d
Protocol version:       

可以看到数据库的版本是5.7.16,但是客户端的版本是5.5.19,到这里,我开始怀疑是不是系统环境变量中配置的是5.5.19的客户端,连接5.7.16的MySQL不兼容导致的,于是使用了新版本的5.7.16的客户端来重新连接数据库,发现问题还是一样的,没有报错信息。很显然,跟客户端没有什么大的关系。

客户端排除了,那么服务器呢,是不是有些参数配置有问题?查了下这个errmsg的配置,发现是通过参数lc_messages_dir来控制的,该参数的解释如下:

The directory where error messages are located. The server uses the value together with the value of lc_messages to produce the location for the error message file.

其中,lc_message是本地的错误信息语言,默认的值是en_US,官网解释是:

The locale to use for error messages. The default is en_US. The server converts the argument to a language name and combines it with the value of lc_messages_dir to produce the location for the error message file

看到这里,可能问题就比较明显了,查看了一下当前MySQL Server的这俩值,发现果然有点问题,如下:

代码语言:javascript
复制
mysql  ::>>show variables like '%messages_dir%';
+-----------------------------------------+---------------------------------------------------------+
| Variable_name                           | Value                                                   |
+-----------------------------------------+---------------------------------------------------------+
| lc_messages_dir                         | /usr/local/mysql-5.5.19-linux2.6-x86_64/share/          |
+-----------------------------------------+---------------------------------------------------------+
 rows in set (. sec)

可以看到,服务器的版本是5.7.16,但是配置中的errmsg的文件路径是5.5.19版本的,于是我重新修改了一下路径,首先尝试了一发手动修改,结果如下:

代码语言:javascript
复制
mysql  ::>>set global lc_messages_dir='/usr/local/Percona-Server-5.7.16-10-Linux.x86_64.ssl101/share/';
ERROR  (HY000): Unknown error 

很明显,不让直接修改,而且报错信息依旧只有个Unknow error 1238,于是我在配置文件中添加了一个记录:

代码语言:javascript
复制
lc-messages-dir=/usr/local/Percona-Server-5.7.--Linux.x86_64.ssl101/share

再次重启数据库,问题得到了解决,错误信息也出来了。

代码语言:javascript
复制
mysq  ::>>set global lc_messages_dir='/usr/local/Percona-Server-5.7.16-10-Linux.x86_64.ssl101/share/';
ERROR  (HY000): Variable 'lc_messages_dir' is a read only variable

02

字符串截取的一个小方法

上面是错误信息的问题,再来看第二个问题,今天遇到了一个需求,是把一个表中的最末尾的数字记录都给取出来,每行记录的是由字母和数字组成的varchar字符串,如下:

代码语言:javascript
复制
mysql  ::>>select * from aaa;
+-----------+
| name      |
+-----------+
| t8        |
| number129 |
| abc0111   |
+-----------+
 rows in set (. sec)

结果想要的是:

8

129

0111

这个问题,使用字符串的reverse函数和运算符中的"-"符号组合解决的,具体的方法如下,大家可以看看有没有更好的方法:

1、使用reverse函数翻转字符串,将数字反向放在前面

2、使用-符号对数字+字符的结构进行截断,变成一个负的数字

3、将负的数字变为正

4、将正的数字翻转即可

SQL如下:

代码语言:javascript
复制
mysql  ::>>select reverse(name) from aaa;
+---------------+
| reverse(name) |
+---------------+
| 8t            |
| 921rebmun     |
| 1110cba       |
+---------------+
 rows in set (. sec)

mysql  ::>>select -reverse(name) from aaa;
+----------------+
| -reverse(name) |
+----------------+
|             -8 |
|           -921 |
|          -1110 |
+----------------+
 rows in set (. sec)

mysql  ::>>select -(-reverse(name)) from aaa;
+-------------------+
| -(-reverse(name)) |
+-------------------+
|                 8 |
|               921 |
|              1110 |
+-------------------+
 rows in set (. sec)

mysql  ::>>select reverse(-(-reverse(name))) from aaa;
+----------------------------+
| reverse(-(-reverse(name))) |
+----------------------------+
| 8                          |
| 129                        |
| 0111                       |
+----------------------------+
 rows in set (. sec)

mysql  ::>>select reverse(-(-reverse(name))) as name from aaa;    
+------+
| name |
+------+
| 8    |
| 129  |
| 0111 |
+------+
 rows in set (. sec)

最后,抛一个还没有解决的问题,如下:

首先我们创建一个表name,name是varchar(10)类型,如下:

代码语言:javascript
复制
mysql  22:24:49>>show create table aaa\G
*************************** 1. row ***************************
       Table: aaa
Create Table: CREATE TABLE `aaa` (
  `name` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

然后插入一组数据,进行update的演示

代码语言:javascript
复制
mysql  ::>>select * from aaa;
+------+
| name |
+------+
| t8   |
| 9    |
| 10   |
+------+
 rows in set (. sec)
#隐式类型转换
mysql  ::>>update aaa set name = 'number129' where name=;
Query OK,  row affected (. sec)
Rows matched:   Changed:   Warnings: 

mysql  :08:>>select * from aaa;                             
+-----------+
| name      |
+-----------+
| t8        |
| number129 |
| 10        |
+-----------+
 rows in set (. sec)
#第二次隐式类型转换出错
mysql  ::>>update aaa set name='abc0111' where name=; 
ERROR  (): Truncated incorrect DOUBLE value: 'number129'

我们可以看到,当我们更新name='9'的时候,我们故意写成了name=9,可以发现,执行成功了,但是当我们使用同样的方法去更新name=10的记录的时候,执行就会报错,提示name='number129'的列发生了不正确的截断,事实上,我们没有更新这一行记录。

从报错信息来看,mysql在处理隐式转换的时候,是将表中的varchar数据转换成整数来跟where条件进行匹配的,但是这样似乎又解释不通为什么第一个update name=9的语法是正确的,因为name='t8'的列也需要进行转换,但是没有报错。。。

这个细节还有待研究。。。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档