- UID
- 446
- 注册
- 2019/10/02
- 消息
- 13
- 解决方案
- 1
- 黄金
- 2,857G
由于fullUnicode选项貌似是默认打开的,如果数据库使用UTF-8编码,在备份的时候,部分内容可能乱码,导致数据库插入语句无效,造成数据丢失
解决方法是修改数据库排序规则为utf8mb4_general_ci
官方说明文档: https://xenforo.com/docs/xf2/unicode/
以下内容为具体分析
# 商业转载请联系作者获得授权,非商业转载请注明出处。
# For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source.
# 协议(License):署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
# 作者(Author):Rayzggz
# 链接(URL):https://blog.ranfu.net/archives/391
# 来源(Source):Roy's Blog
分析
由于辣鸡宝塔的数据库导入导出都没有返回任何报错信息,所以最开始采用Navicat进行读取,使用Navicat的导出导入,由此得到以下测试结果
通过翻阅宝塔源码文件
可得知,宝塔使用的备份指令为
由此可以发现与命令备份指令相同,推测应该不是宝塔导出的问题,而且命令本身有问题。通过查阅相关资料,也并没有发现此备份命令有不当之处。
虽然从逻辑分析,应该是导出问题,但是由于导出没有任何报错,所有只能转向导出的报错提示
通过查阅谷歌,发现以下出现同样问题的人
www.v2ex.com
根据回复,应该是编码问题,但是米坛社区一直使用utf-8编码,从未使用过GBK等中文编码,应该不存在此问题,而且这也无法解释为什么会导致大量数据丢失,因为不可能人人都错误的使用GBK编码作为用户名注册。
由此,只能针对备份出来的SQL文件进行分析,通过对比原数据库和丢失数据了的测试服务器数据库,发现都在命令导出的SQL文件中,丢失的数据都位于同一个 INSERT INTO 语句,因为语句出错,导致整条 INSERT INTO 语句无法正常执行,只能跳过, INSERT INTO 语句中所有用户数据都没被成功导入。
由于 INSERT INTO 语句过长,有大概3000条用户信息,所有只能在原数据库一条条查看可疑的可能导致乱码的用户名,最后找到了两个使用emoji的用户名,并且在命令导出的sql文件中,这两个用户的用户名都乱码了,使用Navicat导出的由于软件正确识别,正常的写入了文件,所以一切正常。
归因
通过查阅资料,MySQL如果使用普通的UTF-8编码,是无法储存emoji的,xenforo提供了
选项来解决此问题,此选项是默认开启的,但是当初在使用宝塔创建数据库的时候,并不知道有这个限制,整个数据库使用了默认的UTF-8编码,而事实上应该使用UTF-8mb4,xenforo又自动的在创建表的使用UTF-8mb4进行了储存,所以emoji被正常储存了。但是宝塔在备份时使用了参数 --default-character-set="+ public.get_database_character(name)这导致备份输出使用了UTF-8,所有的emoji数据乱码,数据丢失。
所有这个问题就是在 xenforo没有检测直接使用UTF-8mb4 + 宝塔默认没有使用兼容性更好的UTF-8mb4 + 宝塔导入数据库不返回报错 的多重因素下产生了
解决
解决方法也很简单,直接修改数据库排序规则为 utf8mb4_general_ci 即可
参考资料:
https://xenforo.com/docs/xf2/unicode/
https://www.v2ex.com/t/60317
解决方法是修改数据库排序规则为utf8mb4_general_ci
官方说明文档: https://xenforo.com/docs/xf2/unicode/
以下内容为具体分析
# 商业转载请联系作者获得授权,非商业转载请注明出处。
# For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source.
# 协议(License):署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
# 作者(Author):Rayzggz
# 链接(URL):https://blog.ranfu.net/archives/391
# 来源(Source):Roy's Blog
分析
由于辣鸡宝塔的数据库导入导出都没有返回任何报错信息,所以最开始采用Navicat进行读取,使用Navicat的导出导入,由此得到以下测试结果
宝塔导出 | Mysqldump命令导出 | Navicat导出 | |
宝塔导入 | 导入报错、数据丢失 | 导入报错、数据丢失 | 正常 |
Mysqldump命令导入 | 导入报错、数据丢失 | 导入报错、数据丢失 | 正常 |
Navicat导入 | 导入报错、数据丢失 | 导入报错、数据丢失 | 正常 |
通过翻阅宝塔源码文件
代码:
/www/server/panel/class/database.py
代码:
--default-character-set="+ public.get_database_character(name)
虽然从逻辑分析,应该是导出问题,但是由于导出没有任何报错,所有只能转向导出的报错提示
代码:
ERROR 1062 (23000) at line 106: Duplicate entry '???'; for key 'username'
代码:
ERROR 1062 (23000) at line 109: Duplicate entry '?????' for key 'username'
[MySQL]mysqldump出来数据再导入回去,为什么会出现Duplicate entry? - V2EX
MySQL - @m - 库里的一个表,使用varchar(32)+int(16)作为主键,表结构:CREATE TABLE `name_lv` ( `name` varchar(32) NOT NULL,

由此,只能针对备份出来的SQL文件进行分析,通过对比原数据库和丢失数据了的测试服务器数据库,发现都在命令导出的SQL文件中,丢失的数据都位于同一个 INSERT INTO 语句,因为语句出错,导致整条 INSERT INTO 语句无法正常执行,只能跳过, INSERT INTO 语句中所有用户数据都没被成功导入。
由于 INSERT INTO 语句过长,有大概3000条用户信息,所有只能在原数据库一条条查看可疑的可能导致乱码的用户名,最后找到了两个使用emoji的用户名,并且在命令导出的sql文件中,这两个用户的用户名都乱码了,使用Navicat导出的由于软件正确识别,正常的写入了文件,所以一切正常。
归因
通过查阅资料,MySQL如果使用普通的UTF-8编码,是无法储存emoji的,xenforo提供了
代码:
$config['fullUnicode'] = true;
所有这个问题就是在 xenforo没有检测直接使用UTF-8mb4 + 宝塔默认没有使用兼容性更好的UTF-8mb4 + 宝塔导入数据库不返回报错 的多重因素下产生了
解决
解决方法也很简单,直接修改数据库排序规则为 utf8mb4_general_ci 即可
参考资料:
https://xenforo.com/docs/xf2/unicode/
https://www.v2ex.com/t/60317