MySQL

  • 随着企业规模增长,或者,企业原本就在监管非常严格的行业或环境,所面临合规要求也会逐步增多,密码的定期轮换通常也是众多要求中的一个基础项。MySQL 8.0 提供的“双密码”管理机制,可以让大规模数据库密码轮换变得更平滑,而无需任何的停机时间。

    100台MySQL、1000台应用服务

    考虑这样的场景,你是一个 DBA ,生产环境有 100 台 MySQL 实例,运行在这些数据库上约有 1000 台应用服务器。如果需要对,这些 MySQL 的应用账号密码统一做一次更新,如何实现不停机的迁移。

    在 MySQL 之前(8.0.14版本之前)的单密码机制下,更换密码通常会遇到以下问题:无论是先更新数据库服务器上的密码,还是新调整应用服务器上的密码,这个先后顺序都会带来一定的服务不可用时间。通常,为了降低这个服务不可用时间,应用变更人员和 DBA 则需要非常密切的配合。

    双密码机制(dual password)

    从 MySQL 8.0.14 起,开始支持了双密码策略。在密码更换时,可以保留旧密码依旧可用:

    ALTER USER 'appuser1'@'host1.example.com'
      IDENTIFIED BY 'password_b'
      RETAIN CURRENT PASSWORD;

    在一段时间后,可以删除旧密码:

    ALTER USER 'appuser1'@'host1.example.com'
      DISCARD OLD PASSWORD;

    构建批量密码轮换流程

    有了该功能,就可以使用上述的命令,更加平滑的实现大规模数据库场景下的密码更换。

    1. 给变更数据库服务器上账号的密码,同时将原密码作为备用密码保留(使用“RETAIN CURRENT PASSWORD”)
    2. 变更应用服务器上的访问数据库的密码
    3. 检查并观察一段时间,删除数据库中的原密码(使用“DISCARD OLD PASSWORD ”)

    这是一个简化的过程,实际的操作还需要考虑:

    • 严格遵循企业内部的变更规范
    • 灰度的进行发布,而不是一次性操作所有的实例/服务器
    • 做好检查,需要确保诸如密码已经变更完成、应用服务器密码均已经更新
    • 做好回滚方案,避免过程中操作失误导致的问题
    • 在业务低峰时间进行操作

    参考阅读

  • 关闭 InnoDB 的 redo log

    ·

    在 MySQL 实例恢复时(尤其是逻辑备份的恢复),为了获得更快的恢复速度,通常会关闭二进制日志(Binary Log),并且将 InnoDB 的日志持久化级别调整到最低。从 MySQL 8.0.21起[1],更进一步的,可以彻底的关闭 InnoDB redo 从而获得更好导入速度。后续的 8.4 / 9.0 / 9.1 可以使用该特性。

    在本文的测试中,可以看到关闭 InnoDB redo log 导入速度可以提升约 26%

    使用场景

    最为常见的就是在进行大量数据导入时,希望能够加速数据导入的过程。

    管理命令

    可以使用如下的命令关闭/或打开 InnoDB redo log:

     ALTER INSTANCE {ENABLE|DISABLE} INNODB REDO_LOG

    关闭 InnoDB redo log

    mysql>  ALTER INSTANCE DISABLE INNODB REDO_LOG;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> SHOW STATUS LIKE '%Innodb_redo_log_enabled%';
    +-------------------------+-------+
    | Variable_name           | Value |
    +-------------------------+-------+
    | Innodb_redo_log_enabled | OFF   |
    +-------------------------+-------+
    1 row in set (0.02 sec)
    
    

    打开 InnoDB redo log

    mysql> ALTER INSTANCE ENABLE INNODB REDO_LOG;
    Query OK, 0 rows affected (1.02 sec)
    
    mysql> SHOW STATUS LIKE '%Innodb_redo_log_enabled%';
    +-------------------------+-------+
    | Variable_name           | Value |
    +-------------------------+-------+
    | Innodb_redo_log_enabled | ON    |
    +-------------------------+-------+
    1 row in set (0.00 sec)

    执行该命令的权限

    因为该命令对数据库影响巨大,所以也引入独立的权限 INNODB_REDO_LOG_ENABLE来管理该命令的执行权限。具体参考:

    mysql> GRANT INNODB_REDO_LOG_ENABLE ON *.* to 'data_load_admin';

    性能对比

    这里做应该简单的性能对比,看看关闭 InnoDB Redo Log 导入速度会提升多少。

    # mysql -uroot test -e "show status like 'Innodb_redo_log_enabled'"
    +-------------------------+-------+
    | Variable_name           | Value |
    +-------------------------+-------+
    | Innodb_redo_log_enabled | ON    |
    +-------------------------+-------+
    #  mysql -uroot test -e "truncate table passenger"
    # time mysql -uroot test < passenger.1000.sql > /dev/null
    
    real	0m3.109s
    user	0m0.017s
    sys	0m0.013s
    # mysql -uroot test -e "truncate table passenger"
    # mysql -uroot test -e "ALTER INSTANCE DISABLE INNODB REDO_LOG"
    # time mysql -uroot test < passenger.1000.sql > /dev/null
    
    real	0m2.286s
    user	0m0.022s
    sys	0m0.009s

    在这个初步测试中,可以观察到,在关闭 InnoDB Redo 之后,到如时间从 3.109s 降低到了 2.286s,在该导入中,节省时间约 26%的时间。

    参考文档

  • Oracle Cloud 是所有云平台最先支持 9.0 版本的。这里,我们来看看该版本的“标准性能”表现如何。

    测试实例与环境说明

    这里使用的实例类型是:MySQL.4,单个节点为4 ecpu 32gb,测试区域选择的是“东京”(ap-tokyo-1),多可用区(FAULT DOMAIN)的版本,测试实例存储空间大小为 100 gb。即:

    instance_type=MySQL.4
    vcpu_per_node=4
    memory_size_per_node=32
    region=tokyo
    availability=multi-az
    storage_size=100
    db_version=8.0.39/8.4.2/9.0.1

    性能对比

    本次测试分别测试了 8.0.39/8.4.2/9.0.1 这三个版本。详细的性能对比如下:

    dataMySQL80MySQL84MySQL90
    4355136063360
    8593653785256
    16805481867287
    32831780297817
    48813082047911
    64783879818060
    96850484308172
    128819882868000
    192804380538112
    256790780347536
    384820980558151
    512838680307872

    性能概述

    从该“标准”测试来看,9.0.1的性能较为稳定。从上述数据中来看,似乎略微低于 8.0和8.4 版本,但经过调查,主要原因是由于云平台 CPU 资源多少所导致的,而并不是数据库本身的问题。

    此外,在今年5月份观察到的8.4性能退化问题(参考),目前也已经解决。

  • 在不同的云厂商,购买相同规格的MySQL实例(如4vCPU-16GB),获得的性能相同吗?

    dataaliyun_202409_hangzhou->stdbenchtencent_202409_beijing_exclusive->stdbenchhwcloud_202409_beijing_x86->stdbenchbaiducloud_202409_beijing->stdbenchaws_202409_tokyo_m6i->stdbenchazure_202409_east_asia_4c16g->stdbenchgcp_202409_tokyo_80_enterprise->stdbenchoci_202409_tokyo_8039->mysql_on_4_ecpu
    47102559225572206163920257233551
    897029936467441013313365413415936
    161466016141822972986427654825028054
    3222155223361352012022121571036348578317
    4827905247701784916448165161197367458130
    6432704264952011418187181181276180717838
    9636846290772088321007207821330096758504
    128396972991820128210292244613388106208198
    192389993061020521220912259013478115078043
    256383563105221187216652232312985118727907
    384396793122421729211672190212904121318209
    512403333180522647216272159112930121068386
    cpu_capacity80.493.3163.673.9110.956.349.9114.7

    测试结果概述

    在本次测试中:阿里云RDS MySQL性能表现最好,极限的QPS达到了4万;其次是腾讯云,达到了3.2万;第二梯队是华为云、百度云和AWS,极限的QPS约2.2万;之后是Azure、Google云,极限QPS约1.2万;最后是Oracle云,极限QPS约8500。详细的数据和趋势图,可以参考以上的图、表,这里不再详述。

    (more…)
  • 在不同的云厂商,购买相同规格的MySQL实例(如4vCPU-16GB),获得的性能相同吗?

    为了回答上面的疑问,于是就开启了我的数据库性能测试之旅。这是第二次测试,上一次是在2023年12月(参考:云数据库(RDS MySQL)性能深度测评与对比)。

    性能测试结果与概述

    (more…)
  • 原本我一直是使用各个YUM仓库中默认的sysbench版本的,主要是考虑安装部署方便,而一直以来这个版本似乎都没有遇到什么问题,直到…尝试自动化的对Azure上的MySQL进行压测。

    默认的sysbench版本是1.0.17版(Mar 15, 2019),首先,是遇到了如下的报错信息:

    sysbench 1.0.17 (using system LuaJIT 2.0.4)
    
    FATAL: unable to connect to MySQL server on host 'xxx.mysql.database.azure.com', port 3306, aborting...
    FATAL: error 3159: Connections using insecure transport are prohibited while --require_secure_transport=ON

    在该版本中,sysbench提供了参数--mysql-ssl=[on|off]以尝试解决这个问题,但对于最新版本的MySQL,该参数很多时候都无法正常工作,如果你也尝试了该参数,那么会报如下错误:

    FATAL: unable to connect to MySQL server on host 'xxx.mysql.database.azure.com', port 3306, aborting...
    FATAL: error 2026: SSL connection error: SSL_CTX_set_default_verify_paths failed

    如果,恰好,你注意上面的报错可能是CA证书的问题,于是你也像我一样尝试通过 下载证书的方式去解决,并通过GitHub上的issue,成功将CA证书改名成cacert.pem,并放在当前的路径下,那么你还会遇到如下报错:

    SSL error: Unable to get certificate from 'client-cert.pem'
    FATAL: unable to connect to MySQL server on host 'xxx.mysql.database.azure.com', port 3306, aborting...
    FATAL: error 2026: SSL connection error: Unable to get certificate

    好了,也许你再成功生成client-cert.pemclient-key.pem的话,也许你真的能够运行成功。不过,再向后,我就没有尝试了,原因是,如果每一次测试都去获得各一个身份认证的密钥对,那么实在是太复杂了。

    最终,我根据AWS上这篇文章(Running sysbench on RDS MySQL… via SSL/TLS)的建议,尝试自己编译安装了最新版本的sysbench,也就是1.1.0版本。然后简单的使用参数--mysql-ssl=preferred--mysql-ssl=required彻底的解决了这个问题。

    参考文档