MySQL 8.0新特性专栏目录
双重密码,MySQL 8.0创新特性
前言:
MySQL 8.0 引入了很多令人振奋的新特性,跟账户认证相关的新特性包括:新增caching_sha2_password身份认证插件,支持角色,区分系统账户和普通账户,维护密码历史信息限制重复使用以前的密码和密码过期等,双重密码,生成随机密码,登录失败跟踪和临时锁定账户。
MySQL 8.0 最令人眼前一亮的特性:双重密码
。这个特性在数据库领域应该也是第一次引入,为线上DB变更带来了极大的便利。
1. 双重密码 Dual Password
MySQL 8.0.14之后,账户允许拥有双重密码,一个主密码,一个备密码。客户端通过主密码或者备密码都可以正常连接到数据库,这个特性为我们线上DB的账户变更带来了极大的便利。即使在使用大量服务器或多个应用程序连接到不同 MySQL服务器的情况下,也可以无缝地执行数据库账户密码更改,而不影响业务连续性。
在此之前,数据库账户只允许有一个密码,修改数据库账户密码之后,如果应用程序仍然以旧密码连接MySQL数据库,应用程序会一直报错。双重密码的出现完美地解决了这个问题。
1.1 适用场景
适用场景
- 同一个服务使用相同账户密码连接了多个不同的数据库实例,其中某个数据库实例需要修改密码,修改密码前后服务访问不中断。
- 多个不同服务使用相同账户密码连接了同一个数据库实例,其中某个服务需要修改数据库账户密码,修改密码前后服务访问不中断。
1.2 不停机修改数据库账户密码的具体过程
- 对于要更改的账户,建立一个新的主密码,原密码作为备密码。此时,MySQL
Server会同时承认主密码和备密码,所有应用都可以继续用老的密码连进来。 - 一旦在数据库完成更新密码,应用可以使用新的密码连进来。
- 等所有应用迁移到新的主密码,备密码就可以去掉了(discard)。一旦被discard,就只能用新的密码连接数据库。
1.3 对比验证不停机修改密码(MySQL 8.0 vs MySQL 5.7)
验证一下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
1.3.1 分别在MySQL8.0和5.7新建测试账户
# 分别在MySQL8.0和5.7新建测试账户
[[email protected]][(none)]> create user user8@'127.0.0.1' identified by 'user8user8';
[[email protected]][(none)]> grant select on *.* to user8@'127.0.0.1';
1.3.2 连接MySQL 5.7的python程序,DB端修改账户user8的密码之后,连接MySQL失败,程序报错。
# MySQL 5.7 一旦修改账户user8的密码,python程序连接MySQL失败,程序报错。
[[email protected]][(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.
1.3.3 MySQL 8.0 修改账户user8的密码,新密码设置为主密码,旧密码降级为备密码,python程序连接MySQL正常,程序自始至终没有报错!
# MySQL 8.0 修改账户user8的密码,新密码设置为主密码,旧密码降级为备密码,python程序连接MySQL正常,程序没有报错。
[[email protected]][(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.
1.3.4 MySQL 8.0 废弃备密码之后,python程序连接MySQL失败,程序开始报错。
# MySQL 8.0 废弃备密码之后,python程序连接MySQL失败,程序报错。
[[email protected]][(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实例的场景。