在docker容器中备份和恢复mysql数据库时出现Unicode字符问题

drnojrws  于 12个月前  发布在  Mysql
关注(0)|答案(1)|浏览(265)

我用这段代码在docker中创建了一个数据库:

docker run -d -p 9906:3306 --name db -e MYSQL_ROOT_PASSWORD=1234567890 -e MYSQL_DATABASE=mydb -e MYSQL_USER=myuser -e MYSQL_PASSWORD=123 mysql --character-set-server=utf8mb4 --collation-server=utf8mb4_persian_ci;

字符串
当我尝试使用PhpMyAdmin备份和恢复时,一切都很好。但是当我尝试在PowerShell中使用docker命令时,过程完成,但Unicode字符受到干扰,如:
“+«+<$”
而不是:
“请原谅我的无礼”
以下是我的备份和恢复命令:

# Backup:
docker exec db /usr/bin/mysqldump -u myuser --password=123 --no-tablespaces mydb | set-content backup__.sql;

# Restore:
get-content backup.sql | docker exec -i db mysql -u myuser --password=123 mydb;

已编辑

事实上,我想提交一个.ps1文件给产品经理,以备份和恢复数据库,而无需登录到phpMyAdmin。如果PS是问题所在,除了PS,你还有其他建议吗?

siotufzp

siotufzp1#

  • 要使当前的PowerShell控制台完全支持UTF-8(仅当PowerShell与docker等外部程序进行通信时才有关系),您需要将[Console]::InputEncoding[Console]::OutputEncoding以及PowerShell的$OutputEncoding首选项变量设置为UTF-8(在PowerShell (Core) 7+中,仅后者已经默认为UTF-8)。
  • 要使Set-Content在保存文件时使用UTF-8,请传递-Encoding utf8
  • 需要注意的是,在 Windows PowerShell 中,您总是会得到一个带有BOM* 的UTF-8文件。
  • 如果需要(这里没有),有一个用于创建无BOM的UTF-8文件的解决方案,例如通过New-Item-参见this answer
  • 但是,这在您的情况下并不重要,因为您正在使用Get-Content读取文件,该文件可以正确处理BOM(实际上,* 需要 * 才能在 Windows PowerShell 中识别解码)。

PowerShell 7+ 中,PowerShell 命令的一致默认值是 BOM-less UTF-8,因此您不需要-Encoding utf8(这实际上要求默认行为是什么;在那里得到一个BOM,您需要-Encoding utf8bom),而Get-Content现在在没有BOM的情况下假定为UTF-8(而在 Windows PowerShell 中,它假定为活动的旧版 ANSI 代码页)。
因此:

# Switch PowerShell and the console to UTF-8.
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = 
  [System.Text.UTF8Encoding]::new()

# Backup:
# Note the uses of -Encoding uf8
docker exec db /usr/bin/mysqldump -u myuser --password=123 --no-tablespaces mydb |
  set-content -Encoding utf8 backup__.sql

# Restore:
get-content backup.sql | 
  docker exec -i db mysql -u myuser --password=123 mydb;

字符串
注意事项:

  • 上面假设docker exec db /usr/bin/mysqldump ...发出UTF-8编码的文本,并同样期望它通过管道(stdin);如果不同,请将[System.Text.UTF8Encoding]::new()替换为实际编码。
  • [Console]::InputEncoding[Console]::OutputEncoding有效地设置了当前控制台的输入和输出 * 代码页 *,然后在chcp的输出中反映出来(注意,但是你不能从PowerShell内部chcp来 * 设置 * 活动代码页,因为.NET缓存了原始代码页):
  • 严格地说,[Console]::InputEncoding不会从PowerShell会话内部发挥作用,但[Console]::OutputEncoding是PowerShell用来解码来自外部程序的标准输出的。
  • 相反,$OutputEncoding是PowerShell在将数据发送到外部程序(后者通过其stdin流读取)时使用的编码。
  • This answer讨论了如何将PowerShell控制台 * 默认 * 设置为UTF-8,包括将系统配置为使用UTF-8 * 系统范围 * 的Windows 10+方法,在这种情况下,OEM和ANSI代码页都设置为65001(UTF-8)。但是,后者具有 * 深远的影响 *,因为它可以改变现有控制台应用程序和PowerShell脚本的行为。

相关问题