将MySQL(Percona Server)从5.7升级到8.0



进展不会停滞不前,因此升级到最新版本的MySQL的原因变得越来越重要。不久前,在我们的一个项目中,是时候将舒适的Percona Server 5.7群集升级到版本8了。所有这些都发生在Ubuntu Linux 16.04平台上。如何以最少的停机时间执行类似的操作,以及我们在升级过程中遇到了什么问题-请阅读本文。

训练


数据库服务器的任何更新最有可能与数据库的迁移有关:系统资源限制要求的更改和数据库配置的更正,必须清除过时的指令。

在更新之前,我们一定会转向官方文档:


并制定行动计划:

  1. 通过删除过时的指令来修复配置文件。
  2. 检查与实用程序的兼容性。
  3. 通过安装软件包来更新从数据库percona-server-server
  4. 通过放置相同的软件包来更新向导。

我们将分析计划中的每个项目,看看会出什么问题。

重要!基于Galera的MySQL群集升级过程具有其自身的精妙之处,本文中未进行介绍。在这种情况下,您不应使用此指令。

第1部分:检查配置


在版本8中,删除了MySQL query_cache实际上,它在5.7版中宣布作废,但现在已被完全删除因此,有必要删除相关指令。对于缓存查询,您现在可以使用外部工具,例如ProxySQL

在配置中还发现了过时的pro指令innodb_file_format如果在MySQL 5.7中可以选择InnoDB格式,则第8版仅适用于梭子鱼格式

我们的结果是删除了以下指令:

  • query_cache_typequery_cache_limitquery_cache_size;
  • innodb_file_formatinnodb_file_format_max

为了进行验证,我们将使用Percona Server的Docker映像。我们将服务器配置放在目录中mysql_config_test,然后创建用于数据和日志的目录。percona-server配置测试示例:

mkdir -p {mysql_config_test,mysql_data,mysql_logs}
cp -r /etc/mysql/conf.d/* mysql_config_test/
docker run  --name some-percona -v $(pwd)/mysql_config_test:/etc/my.cnf.d/  -v $(pwd)/mysql_data/:/var/lib/mysql/ -v $(pwd)/mysql_logs/:/var/log/mysql/ -e MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD} -d percona:8-centos

结果:在Docker日志中,或在包含日志的目录中-根据您的配置-将出现一个文件,其中将描述问题指令。

这是我们所拥有的:

2020-04-03T12:44:19.670831Z 0 [Warning] [MY-011068] [Server] The syntax 'expire-logs-days' is deprecated and will be removed in a future release. Please use binlog_expire_logs_seconds instead.
2020-04-03T12:44:19.671678Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.
2020-04-03T12:44:19.671682Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead.

因此,我们仍然需要处理编码并替换过时的指令expire-logs-days

第2部分:验证正在运行的安装


更新文档中有2个实用程序,用于检查数据库的兼容性。它们的使用有助于管理员验证现有数据结构的兼容性。

让我们从经典的mysqlcheck实用程序开始。只需运行:

mysqlcheck -u root -p --all-databases --check-upgrade

如果未检测到问题,则该实用程序将以代码0退出:



此外,mysql-shell实用程序在现代版本的MySQL中可用(在Percona的情况下,这是一个软件包percona-mysql-shell)。它是经典mysql客户端的替代,并结合了客户端,SQL编辑器和MySQL管理工具的功能。要在更新之前检查服务器,可以通过它运行以下命令:

mysqlsh -- util check-for-server-upgrade { --user=root --host=1.1.1.1 --port=3306 } --config-path=/etc/mysql/my.cnf

以下是我们收到的评论:



总的来说,没有什么重要的-只是有关编码的警告(请参阅下文)实施的总体结果:



我们决定更新应该没有问题。

上面警告中的注释表示编码问题。事实上,直到最近,MySQL中的UTF-8才不是真正的UTF-8,因为它仅存储3个字节而不是4个字节。在MySQL 8中,他们最终决定对其进行修复:别名utf8将很快导致编码utf8mb4,而旧的将导致编码。表中的列将变为utf8mb3将来,该编码utf8mb3将被删除,但在此版本中不会删除。因此,我们决定在更新DBMS后将其编码固定在可以正常工作的DBMS安装上。

第3部分:服务器更新


如果有这样一个别致的计划,可能会出什么问题?..意识到细微差别总是会发生的,我们在MySQL开发集群上进行了第一个实验。

如前所述,官方文档强调了使用副本更新MySQL服务器的问题。最重要的是,起初值得更新所有副本(从属),因为MySQL 8可以从5.7版向导进行复制。某些困难在于,当远程主机处于只读模式时,我们使用主机<->主机模式。也就是说,实际上,战斗流量进入一个数据中心,第二个进入备份中心。 拓扑如下: 升级应从mysql副本dc 2副本开始





mysql master dc 2mysql replica dc 1mysql master dc 1服务器,并最终以mysql master dc 1.服务器结束STOP SLAVE更新的其余部分如下所示:

  1. 每个副本重启,增加配置选项3: ,skip-networkingskip-slave-start skip-log-bin事实是,更新数据库会生成带有更新系统表的二进制日志。这些指令确保数据库中的应用程序数据不会发生任何更改,并且有关更新系统表的信息也不会进入二进制日志中。这将避免恢复复制时出现问题。
  2. 安装软件包percona-server-server需要注意的是在MySQL 8,你是很重要的并不需要运行命令mysqlupgrade更新服务器后。
  3. 成功启动后,请重新启动服务器-已经没有第一段中添加的参数。
  4. 我们确保复制成功进行:检查SHOW SLAVE STATUS并查看应用程序数据库中带有计数器的表是否已更新。

所有这些看起来都很简单:开发人员更新成功。好的,您可以安全地计划生产的通宵升级。

没有悲伤-我们更新了产品


但是,将成功的开发经验移植到生产中并非没有意外。

幸运的是,更新过程本身始于副本,因此遇到困难后,我们停止了工作,并从快照中恢复了副本。第二天早上重新安排了问题研究的时间。以下条目出现在日志中:

2020-01-14T21:43:21.500563Z 2 [ERROR] [MY-012069] [InnoDB] table: t1 has 19 columns but InnoDB dictionary has 20 columns
2020-01-14T21:43:21.500722Z 2 [ERROR] [MY-010767] [Server] Error in fixing SE data for db1.t1
2020-01-14T21:43:24.208365Z 0 [ERROR] [MY-010022] [Server] Failed to Populate DD tables.
2020-01-14T21:43:24.208658Z 0 [ERROR] [MY-010119] [Server] Aborting

对Google上各种邮件列表的档案的研究导致人们认识到这样的问题是由于MySQL错误而引起的。尽管它甚至是一个实用程序错误mysqlcheckmysqlsh

事实证明,MySQL更改了十进制字段(int,tinyint等)的数据表示方式,因此另一种存储它们的方法是在mysql-server内部使用。如果您的数据库最初是5.5或5.1版本,然后又升级到5.7,则可能需要生成OPTIMIZE一些表。然后,MySQL将更新数据文件,并将其传输为当前的存储格式。

您也可以使用实用程序进行检查mysqlfrm

mysqlfrm --diagnostic -vv /var/lib/mysql/db/table.frm
...
 'field_length': 8,
  'field_type': 246, #  
  'field_type_name': 'decimal',
  'flags': 3,
  'flags_extra': 67,
  'interval_nr': 0,
 'name': 'you_deciaml_column',
...

如果field_type您有0,那么表中将使用旧类型-必须完成OPTIMIZE。但是,如果值是246,则您已经有一个新类型。有关类型的更多信息,请参见代码

此外,此错误考虑了绕过我们的第二个可能原因- INNODB_SYS_TABLESPACES如果系统表是在5.1版中创建的,则系统表中缺少InnoDB表。为避免升级期间出现问题,您可以使用随附的SQL脚本

为什么我们在开发人员上没有这样的问题?从生产中定期复制该库-因此,重新创建了这些

不幸的是,在一个真正有效的大型数据库上,仅采用并执行无处不在的数据库是行不通的OPTIMIZEPercona工具包将在这里提供帮助:pt-online-schema-change实用程序非常适合在线OPTIMIZE操作。

更新后的计划如下:

  1. 优化所有表。
  2. 执行数据库升级。

要检查它并同时找出更新时间,我们禁用了其中一个副本,并且对于所有表,我们运行以下命令:

pt-online-schema-change --critical-load Threads_running=150 --alter "ENGINE=InnoDB" --execute --chunk-size 100 --quiet --alter-foreign-keys-method auto h=127.0.0.1,u=root,p=${MYSQL_PASSWORD},D=db1,t=t1

由于该实用程序会创建一个新的临时表并将其从主表中复制数据,因此无需长时间锁定即可更新这些表。当两个表相同时,原始表将被锁定并被一个新表替换。在我们的案例中,测试运行表明更新所有表大约需要一天的时间,但是复制数据会导致磁盘上的负载过多。

为了避免这种情况,在生产时,我们在命令中添加了--sleep一个值为10 参数-该参数控制将数据包传输到新表后的等待时间。这样,如果真正运行的应用程序需要响应时间,则可以减少负载。

执行优化后,更新成功。

...但不完全是!


更新后半小时,客户端提出了一个问题。该基地的工作非常奇怪:定期地,连接中断开始了监视中的样子:



锯齿图在屏幕截图中可见,这是由于MySQL服务器的部分线程定期由于错误而掉线的事实。应用程序中出现错误:

[PDOException] SQLSTATE[HY000] [2002] Connection refused

对日志的快速检查显示,mysqld守护程序无法从操作系统获取所需的资源。处理错误时,我们在系统“孤立的” apparmor策略文件中找到了

# dpkg -S /etc/apparmor.d/cache/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/cache/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/local/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/local/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/usr.sbin.mysqld
mysql-server-5.7: /etc/apparmor.d/usr.sbin.mysqld
# dpkg -l mysql-server-5.7
rc  mysql-server-5.7 5.7.23-0ubuntu0.16.04.1      amd64

这些文件是几年前升级到MySQL 5.7时形成的,属于远程软件包。删除文件并重新启动apparmor服务可以解决此问题:

systemctl stop apparmor
rm /etc/apparmor.d/cache/usr.sbin.mysqld
rm /etc/apparmor.d/local/usr.sbin.mysqld
rm /etc/apparmor.d/usr.sbin.mysqld
systemctl start apparmor

最后


任何操作,即使是最简单的操作,都可能导致意外问题。而且,即使有一个经过深思熟虑的计划也不能总是保证预期的结果。现在,在任何更新计划中,我们的团队还包括强制清除可能由于最近的操作而出现的多余文件。

借助这项非专业的图形作品,我要感谢Percona的出色产品!



聚苯乙烯


另请参阅我们的博客:


All Articles