CentOS 6.7 中把Mysql从 5.1 升级到 5.6

准备

本地测试环境一台Linux服务器中初始安装的Mysql版本是5.1,为什么这么老呢?因为最早安装服务器的时候,我是一路默认yum过来的,而早起版本的系统自带的yum资源非常老,比如Mysql是5.1,php是5.3(已经被我升级到5.5了)。所以决定把Mysql升级一下,原因之一是新的版本能得到性能的提升,之二,可以用到更多新版的特性(比如uft8mb4字符)。

这里考虑的是5.6,虽然目前最新是5.7(甚至8.0,正式版未发布),但5.6版本使用的人最多,而且如果强行从5.1到5.7,跨度太大,怕会对目前数据产生不可预估的问题,保险起见,选择了5.6最为升级版本。

升级

1、先确认系统版本

1
2
3
4
# uname -r
2.6.32-573.7.1.el6.x86_64
# lsb_release -r
Release: 6.7

2、下载对应版本的yum资源仓库

1
# rpm -Uvh http://dev.mysql.com/get/mysql57-community-release-el6-7.noarch.rpm

3、编辑仓库,设置5.6的enabled=1(默认是5.7的enabled=1),这样yum升级的时候才会选择5.6升级。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# vim /etc/yum.repos.d/mysql-community.repo

[mysql56-community]
name=MySQL 5.6 Community Server
baseurl=http://repo.mysql.com/yum/mysql-5.6-community/el/6/$basearch/
enabled=1 # 从0改成1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

[mysql57-community]
name=MySQL 5.7 Community Server
baseurl=http://repo.mysql.com/yum/mysql-5.7-community/el/6/$basearch/
enabled=0 # 从1改成0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

4、保险起见,备份数据库

1
2
3
4
5
6
7
# vim bak.sh

mysqldump -uroot -pxxx db1 > db1.sql
mysqldump -uroot -pxxx db2 > db2.sql
...

# sh bak.sh

5、开始升级Mysql。执行以下命令就可以,会同时自动升级其他的如mysql-devel、mysql-client等。

1
# yum update mysql-server

注:由于本地网络从mysql官网下载较慢,可以在其他系统下翻墙或借助下载工具下载对应的包如 http://repo.mysql.com/yum/mysql-5.6-community/el/6/x86_64/mysql-community-server-5.6.35-2.el6.x86_64.rpm 再上传到服务器的目录 /var/cache/yum/x86_64/6/mysql56-community/packages/ 里,再执行 yum update mysql-server 会自动认为下载完成而跳过下载步骤。

6、安装完毕后,默认会自动重启Mysql服务,如果没有重启,手动重启或启动。查看版本号,已经是新版。

1
2
3
4
5
6
# service mysqld start
OR
# service mysqld restart

# mysql -V
mysql Ver 14.14 Distrib 5.6.35, for Linux (x86_64) using EditLine wrapper

7、最重要的一步,而且不能忽略的一步:

1
# mysql_upgrade -uroot -pxxx

官方文档:Once the server restarts, run mysql_upgrade to check and possibly resolve any incompatibilities between the old data and the upgraded software. mysql_upgrade also performs other functions; see [mysql_upgrade — Check and Upgrade MySQL Tables](http://dev.mysql.com/doc/refman/5.7/en/mysql-upgrade.html) details.

至此,Mysql 5.6 已经升级完毕。

问题

那么问题来了。

我有个项目,某一张表需要用到utf8mb4字符编码,我更改了数据库表字段的CHARACTER和COLLATE,修改了项目的数据库连接默认encoding:

1
2
3
4
5
6
mysql> ALTER TABLE tb1 CHANGE col1 col1 VARCHAR(127) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

# vim config/app.php
...
'encoding' => 'utf8mb4',
...

完毕后程序报错了:

1
2
3
mysql: Character set 'utf8mb4' is not a compiled character set and is not specified in the '/usr/share/mysql/charsets/Index.xml' file 

PDOException: SQLSTATE[HY000] [2019] Can't initialize character set utf8mb4 (path: /usr/share/mysql/charsets/) in /xxx.php on line oo

说好的5.5以后就支持utf8mb4了呢,现在怎么说utf8mb4不存在呢!?无奈,网上搜索结果包括什么 把/usr/share/mysql/charsets/Index.xml配置里的utf8直接改为utf8mb4 等做法完全无效。另外我这个数据库里包含了好几个库,不能全部设置 /etc/my.cnf 里的默认字符,应该要兼容才对。

后来找到了这个 MySQL 5.6 Reference Manual / Globalization / Adding a Character Set,按照他的步骤添加 utf8mb4 (而不是修改或直接拷贝修改utf8)到 /usr/share/mysql/charsets/Index.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
mysql> SELECT * FROM INFORMATION_SCHEMA.COLLATIONS WHERE CHARACTER_SET_NAME='utf8mb4';
+------------------------+--------------------+-----+------------+-------------+---------+
| COLLATION_NAME | CHARACTER_SET_NAME | ID | IS_DEFAULT | IS_COMPILED | SORTLEN |
+------------------------+--------------------+-----+------------+-------------+---------+
| utf8mb4_general_ci | utf8mb4 | 45 | Yes | Yes | 1 |
| utf8mb4_bin | utf8mb4 | 46 | | Yes | 1 |
| utf8mb4_unicode_ci | utf8mb4 | 224 | | Yes | 8 |
...
+------------------------+--------------------+-----+------------+-------------+---------+
26 rows in set (0.00 sec)

# vim /usr/share/mysql/charsets/Index.xml
<!-- 添加到utf8之前 -->
<!-- 下面2个id分别为上面mysql查到的id -->
<charset name="utf8mb4">
<family>Unicode</family>
<description>UTF-8 Unicode</description>
<collation name="utf8mb4_general_ci" id="45">
<flag>primary</flag>
<flag>compiled</flag>
</collation>
<collation name="utf8mb4_bin" id="46">
<flag>binary</flag>
<flag>compiled</flag>
</collation>
</charset>

但是仍然还是报那个错。感觉Mysql方面的设置已经是没有问题了的,那么会不会是PHP方面的问题呢?PDO?

1
# yum reinstall perl-DBD-MySQL php55w-pdo php55w-odbc php55w-mysqlnd php55w-mysql php55w-dba

仍然报错!最后,在折腾了近2小时后,找到了最后的解决办法:PHP PDOException: SQLSTATE[HY000] [2019] Can’t initialize character set utf8mb4

1
2
# yum erase php55w-mysql
# yum install php55w-mysqlnd

卸载mysql连接扩展,安装mysqlnd PDO_MySQL 扩展,成功解决。

另外 /usr/share/mysql/charsets/Index.xml 里我添加的utf8mb4的配置并没有删除(虽然一开始加了并没有解决问题,但并不排除这个也是问题之一),在安装 php55w-mysqlnd 解决了问题后并没有验证去掉utf8mb4之后会不会有问题。

参考

  1. Download MySQL Yum Repository: http://dev.mysql.com/downloads/repo/yum/

  2. A Quick Guide to Using the MySQL Yum Repository: http://dev.mysql.com/doc/mysql-yum-repo-quick-guide/en/

  3. PHP PDOException: SQLSTATE[HY000] [2019] Can’t initialize character set utf8mb4: http://stackoverflow.com/questions/33834191/php-pdoexception-sqlstatehy000-2019-cant-initialize-character-set-utf8mb4

  4. MySQL 5.6 Reference Manual / Globalization / Character Set Configuration: http://dev.mysql.com/doc/refman/5.6/en/charset-configuration.html

  5. MySQL 5.6 Reference Manual / Globalization / Adding a Character Set: https://dev.mysql.com/doc/refman/5.6/en/adding-character-set.html