1.版本

1)操作系统

 cat /etc/issue
cat /etc/issue
CentOS release 6.6 (Final)
Kernel \r on an \m

 cat /proc/version
cat /proc/version
Linux version 2.6.32-504.el6.x86_64 (mockbuild@c6b9.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC) ) #1 SMP Wed Oct 15 04:27:16 UTC 2014

2)mysql数据库版本

mysql --version
mysql  Ver 14.14 Distrib 5.6.26, for linux-glibc2.5 (x86_64) using  EditLine wrapper


2.问题描述

2.1 发现问题

  今天监控报突然某套mysql数据库备份失败(mysql架构为一主,一从,从库上部署了mysqldump及meb两种备份),在备份日志中看到如下报错:

Warning: Using a password on the command line interface can be insecure.
mysqldump: Got error: 1862: Your password has expired. To log in you must change it using a client that supports expired passwords. when trying to connect
##备份脚本已经用了很长时间了,之前备份一直是正常的。  

备份脚本中的主要语句类似如下:

mysqldump -uroot -p -h127.0.0.1 --all-databases --events --routines --triggers --single-transaction --default-character-set=utf8 --complete-insert --flush-privileges --hex-blob --dump-slave=2 >database_3307.sql

3. 问题分析

   从上面的报错我们知道是用户过期了,虽然mysql 5.6已经有了使用户过期的功能,但是只能通过ALTER USER account PASSWORD EXPIRE语句才能使用户过期 ,用户是不会自动过期的(比如说用户使用一段时间以后自动过期,5.6暂时没有这个功能)

  但是公司就我一个dba,其他人也没有数据库的super权限,那么用户为什么过期呢?接下来我们慢慢分析

1) 查看127.0.0.1对应的root用户是否过期

mysql -uroot -p -S /tmp/3306.sock

mysql> select user();
+----------------+
| user()         |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

mysql> select user,host,password,password_expired from mysql.user where user = 'root';
+------+---------------------+-------------------------------------------+------------------+
| user | host                | password                                  | password_expired |
+------+---------------------+-------------------------------------------+------------------+
| root | localhost           | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B | N                |
| root | all-middle-mysql-10 | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B | Y                |
| root | 127.0.0.1           | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B | Y                |
| root | ::1                 | *81F5E21E35407D884A6CD4A731AEBFB6AF209E1B | Y                |
+------+---------------------+-------------------------------------------+------------------+
4 rows in set (0.00 sec)

##这里我们我们看到除了'root'@'localhost'用户没有过期以外,其他的三个root用户都已经过期(至于这些用户为什么会过期,这边博客中我就不展开讲了,有兴趣的可以看我的另一篇博客)

2) 尝试使用 'root'@'127.0.0.1' 用户登录数据库

mysql -uroot -h127.0.0.1 -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.6.26-log

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select user,host,password,password_expired from mysql.user;
ERROR 1820 (HY000): You must SET PASSWORD before executing this statement
mysql> 
##注意我们看到在命令行中使用 'root'@'127.0.0.1'能够登录数据库,但是进行任何操作都会提示你先修改密码

3) 手动执行备份脚本

 ./mysqlbak3306.sh
Warning: Using a password on the command line interface can be insecure.
mysqldump: Got error: 1862: Your password has expired. To log in you must change it using a client that supports expired passwords. when trying to connect
##调用备份脚本的时候就报我们在2.1中给出的错误

4) 数据库最近做过的变动

   因为之前备份脚本是能够正常工作的,但是突然就报错了(并且我确定我没有对'root'@'127.0.0.1'用户进行过过期操作)。那么我们需要考虑的就是在上一次正常备份发生后,和这一次失败备份之间我们对数据库进行过什么操作。经过排查发现最有可能导致问题的就是为数据库设置了 skip_name_resolve = 1参数并重启了数据库。

##其实分析到这,对于mysql登录的原理比较熟悉的朋友应该已经知道问题所在了。是这样的,如果我们不设置skip_name_resolve = 1,那么我们使用'root'@'127.0.0.1'登录时,其实通过反解析以后我们是用'root'@'localhost'登录的数据库(因为/etc/hosts文件中 127.0.0.1 对应的是localhost),上面我们已经看到了,这个用户是没有过期的,所以此时备份能够正常进行。

  如果我们指定了skip_name_resolve = 1,那么登录时就没有反解析这一步了,那么此时我们就是用'root'@'127.0.0.1'这个用户登录,但是这个用户已经过期,所以备份报错。下面来看一下 设置和不设置skip_name_resolve时使用'root'@'127.0.01'登录的区别

....................................................................................................................................................................................................................................

如果我们不设置skip_name_resolve = 1,那么我们使用'root'@'127.0.01'用户登录上数据库以后应该看到的应该是如下的用户信息:

mysql> select user();
+----------------+
| user()         |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
<pre name="code" class="html">mysql> select user();
+----------------+
| user()         |
+----------------+
| root@127.0.0.1 |
+----------------+
1 row in set (0.00 sec)

   如果我们设置了skip_name_resolve = 1后使用'root'@'127.0.0.1'登录数据库后看到的用户信息如下: 

mysql> select user();
+----------------+
| user()         |
+----------------+
| root@127.0.0.1 |
+----------------+
1 row in set (0.00 sec)
mysql> select current_user();
+----------------+
| current_user() |
+----------------+
| root@127.0.0.1 |
+----------------+
1 row in set (0.00 sec)


4. 解决方案

   其实这个问题的解决方案是很简单的,只要重置一下过期用户的密码就行(注意不能使用 update mysql.user方法来重置密码)

mysql -uroot -p -h127.0.0.1
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 12
Server version: 5.6.26-log

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select user();
ERROR 1820 (HY000): You must SET PASSWORD before executing this statement
mysql> set password for 'root'@'127.0.0.1' = password('root');
Query OK, 0 rows affected (0.05 sec)

##问题解决方法很简单,但是我觉得找到问题的原因往往比仅仅解决问题更重要。






GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐