如何准备 MySQL 5.7 升级

来自Oracle的MySQL团队的一篇文章(http://www.oracle.com/us/products/mysql/mysqlcommunityserver/overview/index.html)

介绍

MySQL 5.7 是流行的开源数据库中最新的版本候选人,它提供了新的可扩展性功能,您应该渴望做出改变。

在高端,MySQL 5.7在48核服务器上线性地扩展,在低端,MySQL 5.7在512 MB的DigitalOceanDroplet上也运行(没有MySQL 5.6中的配置更改是不可能的)。

MySQL 服务器的新高性能为每秒超过 640K 查询,而直接与 InnoDB 存储引擎交谈的 memcached API 能够支持 每秒超过 1.1 万个查询

MySQL 5.7 Performance using the Memcached NoSQL API

然而,在你赶紧运行mysql_upgrade,你应该确保你准备好了。

<$>[注] 注: 截至 2022 年 7 月 1 日,DigitalOcean 不再支持通过控制面板或 API 创建新的 FreeBSD Droplets。

数据完整性变化,以示例

MySQL 5.7 的一个主要变化是,数据完整性已被改进,以更符合老年开发人员和 DBA 所期望的内容。

以下是五个需要修改以在MySQL 5.7中工作的查询示例,您的应用程序是否使用这些行为?

1)在未签名的列中插入负值

创建具有未签名的列的表:

1CREATE TABLE test (  
2 id int unsigned  
3);

输入负值。

以前的行为:

1INSERT INTO test VALUES (-1);
2Query OK, 1 row affected, 1 warning (0.01 sec)

第570章:

1INSERT INTO test VALUES (-1);  
2ERROR 1264 (22003): Out of range value for column 'a' at row 1

(二)分为零

创建一个测试表:

1CREATE TABLE test2 (  
2 id int unsigned  
3);

试着用零来分割。

以前的行为:

1INSERT INTO test2 VALUES (0/0);  
2Query OK, 1 row affected (0.01 sec)

第570章:

1INSERT INTO test2 VALUES (0/0);  
2ERROR 1365 (22012): Division by 0

3)将20个字符串插入10个字符列

创建一个包含 10 个字符的列表:

1CREATE TABLE test3 (  
2a varchar(10)  
3);

尝试插入更长的弦。

以前的行为:

1INSERT INTO test3 VALUES ('abcdefghijklmnopqrstuvwxyz'); 
2Query OK, 1 row affected, 1 warning (0.00 sec)

第570章:

1INSERT INTO test3 VALUES ('abcdefghijklmnopqrstuvwxyz');  
2ERROR 1406 (22001): Data too long for column 'a' at row 1

4)将非标准零日期插入到日期列中

创建一个具有日期列的表:

1CREATE TABLE test3 (  
2a datetime  
3);

点击00000000000000

以前的行为:

1INSERT INTO test3 VALUES ('0000-00-00 00:00:00');  
2Query OK, 1 row affected, 1 warning (0.00 sec)

第570章:

1INSERT INTO test3 VALUES ('0000-00-00 00:00:00');  
2ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'a' at row 1

5)使用GROUP BY并选择一个模糊的列

当描述不是GROUP BY的一部分时,并且没有汇总函数(如MINMAX)应用于其时,会发生这种情况。

以前的行为:

1SELECT id, invoice_id, description FROM invoice_line_items GROUP BY invoice_id;  
2+----+------------+-------------+  
3| id | invoice_id | description |  
4+----+------------+-------------+  
5| 1 | 1 | New socks             |  
6| 3 | 2 | Shoes                 |  
7| 5 | 3 | Tie                   |  
8+----+------------+-------------+  
93 rows in set (0.00 sec)

第570章:

1SELECT id, invoice_id, description FROM invoice_line_items GROUP BY invoice_id;  
2ERROR 1055 (42000): Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'invoice_line_items.description' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

理解行为 通过 sql_mode 设置

在MySQL中,上一节所示的每个行为都受所谓的sql_mode的影响。

该功能在MySQL 4.1(2004年)上首次亮相,但尚未默认编译,MySQL 5.7具有以下默认启用模式:

模式 STRICT_TRANS_TABLES也变得更加严格,并允许在模式 ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATENO_ZERO_IN_DATE下先前指定的行为。

点击这些模式名称以访问MySQL手册,了解更多信息。

关于如何过渡的建议

如果您正在使用最近版本的Wordpress,Drupal或Magento的好消息是,您不需要做任何事情. 这些应用程序已经知道MySQL的sql_mode功能,并在连接到MySQL时将设置它们兼容的选项。

如果您目前正在构建一个新的应用程序,那么改变现有MySQL 5.6服务器的配置可能是一个好主意,以便与MySQL 5.7中发送的sql_mode设置相处。

如果您有 现有的应用程序,您可能希望更逐步地完成更新,这些建议可以帮助您进行过渡:

  • Whitelist: 您的应用程序有新的部分启用新的默认 sql_mode选项. 例如,如果您正在构建一组 cron 工作来重新构建数据缓存,这些可以设置新的 sql_mode,一旦它们连接到MySQL。 现有的应用程序代码可以最初与现有的非严格的行为保持。 黑名单:当您在转换应用程序方面取得了一些进展时,是时候为您的服务器设置新的 sql_mode的默认。 仍然有可能让旧应用程序改变以前的行为。 当他们连接到SQL时,他们会更改 `sql_mode

步骤 1 – 查找产生警告或错误的不兼容声明

首先,看看您当前的任何查询是否会产生警告或错误,这是有用的,因为多个查询的行为已经从 5.6 中的警告改变到 5.7 中的错误,因此您可以在升级之前现在捕捉到警告。

MySQL performance_schema是一个诊断功能,在MySQL 5.6 和更高版本中是默认启用的。

MySQL 5.6+查询来报告产生错误或警告的陈述:

 1SELECT 
 2`DIGEST_TEXT` AS `query`,
 3`SCHEMA_NAME` AS `db`,
 4`COUNT_STAR` AS `exec_count`,
 5`SUM_ERRORS` AS `errors`,
 6(ifnull((`SUM_ERRORS` / nullif(`COUNT_STAR`,0)),0) * 100) AS `error_pct`,
 7`SUM_WARNINGS` AS `warnings`,
 8(ifnull((`SUM_WARNINGS` / nullif(`COUNT_STAR`,0)),0) * 100) AS `warning_pct`,
 9`FIRST_SEEN` AS `first_seen`,
10`LAST_SEEN` AS `last_seen`,
11`DIGEST` AS `digest`
12FROM
13 performance_schema.events_statements_summary_by_digest
14WHERE
15((`SUM_ERRORS` &gt; 0) OR (`SUM_WARNINGS` &gt; 0))
16ORDER BY
17 `SUM_ERRORS` DESC,
18 `SUM_WARNINGS` DESC;

MySQL 5.6+查询来报告产生错误的陈述:

 1SELECT 
 2`DIGEST_TEXT` AS `query`,
 3`SCHEMA_NAME` AS `db`,
 4`COUNT_STAR` AS `exec_count`,
 5`SUM_ERRORS` AS `errors`,
 6(ifnull((`SUM_ERRORS` / nullif(`COUNT_STAR`,0)),0) * 100) AS `error_pct`,
 7`SUM_WARNINGS` AS `warnings`,
 8(ifnull((`SUM_WARNINGS` / nullif(`COUNT_STAR`,0)),0) * 100) AS `warning_pct`,
 9`FIRST_SEEN` AS `first_seen`,
10`LAST_SEEN` AS `last_seen`,
11`DIGEST` AS `digest`
12FROM
13 performance_schema.events_statements_summary_by_digest
14WHERE
15 `SUM_ERRORS` &gt; 0
16ORDER BY
17 `SUM_ERRORS` DESC,
18 `SUM_WARNINGS` DESC;

步骤 2 — 使 MySQL 5.6 像 MySQL 5.7 一样行为

您还可以使用 MySQL 5.6 进行测试,以使其表现为 5.7。

作者,Morgan Tocker MySQL 团队,有一个 GitHub 项目 可用与 样本配置文件,这将允许你这样做。

该文件相当短,所以我们也在这里包括它:

 1# This makes a MySQL 5.6 server behave similar to the new defaults
 2# in MySQL 5.7
 3
 4[mysqld]
 5
 6# MySQL 5.7 enables more SQL modes by default, but also
 7# merges ERROR_FOR_DIVISION_BY_ZERO, NO_ZERO_DATE, NO_ZERO_IN_DATE
 8# into the definition of STRICT_TRANS_TABLES.
 9# Context: http://dev.mysql.com/worklog/task/?id=7467
10
11sql-mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE"
12
13# The optimizer changes the default from 10 dives to 200 dives by default
14# Context: http://mysqlserverteam.com/you-asked-for-it-new-default-for-eq_range_index_dive_limit/
15
16eq_range_index_dive_limit=200
17
18# MySQL 5.7 contains a new internal server logging API.
19# The setting log_warnings is deprecated in 5.7.2 in favour of log_error_verbosity.
20# *But* the default fo log_warnings also changes to 2 as well:
21
22log_warnings=2
23
24# MySQL 5.7.7 changes a number of replication defaults
25# Binary logging is still disabled, but will default to ROW when enabled.
26
27binlog_format=ROW
28sync_binlog=1
29slave_net_timeout=60
30
31# InnoDB defaults to the new Dynamic Row format with Barracuda file format.
32# large_prefix is also enabled, which allows for longer index values.
33
34innodb_strict_mode=1
35innodb_file_format=Barracuda
36innodb_large_prefix=1
37innodb_purge_threads=4 # coming in 5.7.8
38innodb_checksum_algorithm=crc32
39
40# In MySQL 5.7 only 20% of the pool will be dumped, 
41# But 5.6 does not support this option
42
43innodb_buffer_pool_dump_at_shutdown=1
44innodb_buffer_pool_load_at_startup=1
45
46# These two options had different names in previous versions
47# (binlogging_impossible_mode,simplified_binlog_gtid_recovery)
48# This config file targets 5.6.23+, but includes the 'loose' modifier to not fail
49# prior versions.
50
51loose-binlog_error_action=ABORT_SERVER
52loose-binlog_gtid_recovery_simplified=1
53
54# 5.7 enable additional P_S consumers by default
55# This one is supported in 5.6 as well.
56performance-schema-consumer-events_statements_history=ON

(可选)步骤 3 — 在每会话基础上更改 sql_mode

有时你想测试或升级你的服务器在几个阶段,而不是更改你的整个服务器配置文件 MySQL 使用新的 SQL 模式,它也可能在每个会话的基础上更改它们。

1CREATE TABLE sql_mode_test (a int);

没有 SQL 模式设置:

1set sql_mode = '';
2INSERT INTO sql_mode_test (a) VALUES (0/0);
3Query OK, 1 row affected (0.01 sec)

更严格的 SQL 模式:

1set sql_mode = 'STRICT_TRANS_TABLES';
2INSERT INTO sql_mode_test (a) VALUES (0/0);
3ERROR 1365 (22012): Division by 0

准备好升级

在此时刻,您应该确信您已经准备好升级到MySQL 5.7. 跟随MySQL的官方升级指南(http://dev.mysql.com/doc/refman/5.7/en/upgrading-from-previous-series.html)来扭转交换机。

结论

MySQL 5.7 在改进现代应用程序的默认配置和数据完整性方面迈出了重要一步,我们希望本文能帮助您顺利过渡!

有关 5.7 中的所有更改的概述(迄今为止),请参阅 MySQL Server 团队的博客文章:

Published At
Categories with 技术
comments powered by Disqus