MySQL 8.0 引入了很多令人振奋的新特性,跟账户认证相关的新特性包括:新增caching_sha2_password身份认证插件,支持角色,区分系统账户和普通账户,维护密码历史信息限制重复使用以前的密码和密码过期等,双重密码,生成随机密码,登录失败跟踪和临时锁定账户。
MySQL 8.0 最令人眼前一亮的特性:双重密码
。这个特性在数据库领域应该也是第一次引入,为线上DB变更带来了极大的便利。
MySQL 8.0.14之后,账户允许拥有双重密码,一个主密码,一个备密码。客户端通过主密码或者备密码都可以正常连接到数据库,这个特性为我们线上DB的账户变更带来了极大的便利。即使在使用大量服务器或多个应用程序连接到不同 MySQL服务器的情况下,也可以无缝地执行数据库账户密码更改,而不影响业务连续性。
在此之前,数据库账户只允许有一个密码,修改数据库账户密码之后,如果应用程序仍然以旧密码连接MySQL数据库,应用程序会一直报错。双重密码的出现完美地解决了这个问题。
适用场景
验证一下MySQL8.0双重密码的功效。作为对比,使用同一段python小程序分别循环连接MySQL 8.0 和 MySQL 5.7实例,期间修改数据库密码,查看程序是否报错。
测试连接程序:mysql_connection.py
# -*- code: utf-8 -*-
'''
连接mysql操作数据库
'''
import pymysql
import time
class MysqlOperate(object):
def __init__(self, **db_info):
self.host = db_info.get('host')
self.port = db_info.get('port')
self.db = db_info.get('db')
self.user = db_info.get('user')
self.password = db_info.get('password')
self.charset = 'utf8mb4' if not db_info.get('charset') else db_info.get('charset')
self.connection = pymysql.connect(host=self.host,
port=self.port,
db=self.db,
user=self.user,
password=self.password,
charset=self.charset,
read_timeout=None)
def close(self):
self.connection.close()
# main
if __name__ == "__main__":
mysql_info = {'host': '127.0.0.1', 'port': 3306, 'db': 'information_schema', 'user': 'user8', 'password': 'user8user8', 'charset': 'utf8'}
i = 0
while True:
i += 1
try:
MysqlDb = MysqlOperate(**mysql_info)
time.sleep(1)
print('Retry ' + str(i) + ': user8 Connection succeeded.')
MysqlDb.close()
except:
print('Retry ' + str(i) + ': user8 Connection failed.')
finally:
if i > 100:
break
# 分别在MySQL8.0和5.7新建测试账户
[root@mysql.sock][(none)]> create user user8@'127.0.0.1' identified by 'user8user8';
[root@mysql.sock][(none)]> grant select on *.* to user8@'127.0.0.1';
# MySQL 5.7 一旦修改账户user8的密码,python程序连接MySQL失败,程序报错。
[root@mysql.sock][(none)]> ALTER USER 'user8'@'127.0.0.1' IDENTIFIED BY 'newpassword8';
# 日志信息:
Retry 21: user8 Connection succeeded.
Retry 22: user8 Connection succeeded.
Retry 23: user8 Connection failed.
Retry 24: user8 Connection failed.
Retry 25: user8 Connection failed.
Retry 26: user8 Connection failed.
# MySQL 8.0 修改账户user8的密码,新密码设置为主密码,旧密码降级为备密码,python程序连接MySQL正常,程序没有报错。
[root@mysql.sock][(none)]> ALTER USER 'user8'@'127.0.0.1' IDENTIFIED BY 'newpassword8' RETAIN CURRENT PASSWORD;
# 日志信息:
Retry 21: user8 Connection succeeded.
Retry 22: user8 Connection succeeded.
Retry 23: user8 Connection succeeded.
Retry 24: user8 Connection succeeded.
Retry 25: user8 Connection succeeded.
Retry 26: user8 Connection succeeded.
# MySQL 8.0 废弃备密码之后,python程序连接MySQL失败,程序报错。
[root@mysql.sock][(none)]> ALTER USER 'user8'@'127.0.0.1' DISCARD OLD PASSWORD;
# 日志信息:
Retry 30: user8 Connection succeeded.
Retry 31: user8 Connection succeeded.
Retry 32: user8 Connection failed.
Retry 33: user8 Connection failed.
Retry 34: user8 Connection failed.
Retry 35: user8 Connection failed.
Retry 36: user8 Connection failed.
以上,双重密码可以完美解决线上DB的密码变更过程中可能出现的连接失败风险
,尤其是针对多个应用程序连接同一套MySQL实例或者同一套程序连接多个MySQL实例的场景。