Google Cloud Sql 二代 Utf8Mb4 编码

Posted

技术标签:

【中文标题】Google Cloud Sql 二代 Utf8Mb4 编码【英文标题】:Google Cloud Sql Second Generation Utf8Mb4 Encoding 【发布时间】:2016-12-17 01:03:23 【问题描述】:

我们在 AppEngine 应用程序中使用 Google Cloud Sql Second Generation。 但是今天我们发现了一些问题,我们无法将表情符号字符插入数据库,因为我们无法将某些服务器标志更改为 utf8mb4 字符编码。

我们改变了 character_set_server 标志为 utf8mb4,但这还不够

我们必须改变: 字符集系统 character_set_client colaction_connection

flags 为 utf8mb4,但第二代数据库不允许 root 用户更改这些标志。 我们可以做些什么来解决这个问题

有人知道吗?

谢谢

【问题讨论】:

实际上我可以通过 mysql 客户端添加表情符号字符,但我无法使用 Google App Engine java sdk 添加它我的连接字符串是 jdbc:google:mysql://xxxx:europe-west1:livyappdb/xxxxxx 你可以为这个问题添加一个小的Java repro吗?听起来字符集转换在途中的某个地方搞砸了。来自用户输入的带有表情符号的文本来自哪里? 您还应该检查包含表情符号的列所使用的字符集:***.com/questions/1049728/… 数据中包含表情符号的列,采用utf8mb4编码。如果我使用 mysql 客户端写入该列,它可以正常工作,但是当我尝试通过应用引擎 sql api 写入它时,它不接受表情符号字符 您能否在您的帖子中添加一个小型复制案例,展示您感兴趣的内容以及您如何插入它? 【参考方案1】:

SHOW CREATE TABLE -- 这可能会说列是CHARACTER SET utf8。这需要修复

ALTER TABLE tbl CONVERT TO CHARACTER SET utf8mb4 COLLATION utf8mb4_unicode_520_ci;

【讨论】:

【参考方案2】:

我们遇到了完全相同的问题。将character_set_server 设置为utf8mb4 是不够的。我们可以通过 MySQL Workbench 插入表情符号,但不能通过我们的应用程序。

在我们的例子中,当我们启动一个运行 MySQL 5.7 而不是 5.6 的新实例后,这个问题就消失了。所以我的假设是,在 5.7 中,而不是在 5.6 中,更改 character_set_server 标志可以让 Google Cloud SQL 更改您提到的其他标志或其他一些相关设置。

当然,如果您已经在运行 5.7,这不适用于您。

【讨论】:

【参考方案3】:

您必须将character_set_server 设置为utf8mb4,将您需要的列更改为utf8mb4,并使用新标志 (!!) 创建一个新的 Cloud SQL 第二代实例。基本上,在现有实例上设置标志并重新启动(用 5.7 测试)是不够的(这是一个错误吗?我在文档中没有找到它)。不需要任何与编码相关的连接参数,应将其删除。排序规则将是 utf8mb4 的标准排序规则,这对我(可能是大多数情况)来说是完美的,即使没有设置任何内容。

【讨论】:

在 5.7 上将 character_set_server 设置为 utf8mb4 并重新启动实例对我有用。【参考方案4】:

对我来说,我发现使用 AppEngine Console->SQL 并将 character_set_server 编辑为 utf8mb4 并重新启动数据库确实有效!

【讨论】:

错误评论抱歉【参考方案5】:

我有一个带有第二代数据库的旧 java 项目,并且表情符号工作正常,没有在连接字符串中使用任何其他内容。只有两件事:

将 character_set_server 标志设置为 utf8mb4, 并使用 utf8mb4 创建数据库。

(如果您不想全部阅读,请跳至最后。)现在我在 python 上遇到了这个问题,但没有任何效果。我必须解决这个问题,所以我会写下我发现的。 我已经尝试过(下面的这个不起作用,这正是我尝试过的):

1 移除flag,重启实例,添加flag,再次重启

2 我在连接字符串中设置了?charset=utf8,库返回错误:无效的utf8字符串:'F09F98'

3 我已设置 ?charset=utf8mb4 并且库将值写入数据库,但不是 emoji 而是 ??? .所以如果库识别出utf8mb4,并写入,那么问题不在库的连接上,而是在数据库中。

4 我已经跑了

SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';

'character_set_client', 'utf8'
'character_set_connection', 'utf8'
'character_set_database', 'utf8mb4'
'character_set_filesystem', 'binary'
'character_set_results', 'utf8'
'character_set_server', 'utf8mb4'  -> this is set from the Google Console
'character_set_system', 'utf8'
'collation_connection', 'utf8_general_ci'
'collation_database', 'utf8mb4_general_ci'
'collation_server', 'utf8mb4_general_ci'

UPDATE comment set body="?" where id=1;
Invalid utf8 character string: '\xF0\x9F\x98\x8E'   0,045 sec

SET NAMES utf8mb4;
SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
'character_set_client', 'utf8mb4'
'character_set_connection', 'utf8mb4'
'character_set_database', 'utf8mb4'
'character_set_filesystem', 'binary'
'character_set_results', 'utf8mb4'
'character_set_server', 'utf8mb4'
'character_set_system', 'utf8'
'collation_connection', 'utf8mb4_general_ci'
'collation_database', 'utf8mb4_general_ci'
'collation_server', 'utf8mb4_general_ci'

UPDATE comment set body="?" where id=1;

SUCCESS

所以问题出在其中一个标志上。

5 我关闭了当前连接并再次重新打开了我的客户端,以便我将这些变量再次设置为 utf8。首先,我更改了 character_set_results 和character_set_client ,以便我可以在我的客户端(MysqlWorkbench)中看到正确的结果。我再次运行更新语句但没有成功,仍然???在该领域。在将 character_set_connection 更改为utf8mb4 并再次更新该字段后,这次我的表中有表情符号。但是为什么 character_set_connection正如上面的测试所示,来自库的连接已经是 utf8mb4。所以在这一点上我不明白在哪里将我的连接字符集设置为 utf8mb4 以便事情可以开始工作。

6 我尝试使用 charset 标志创建新的 Cloud SQL 实例,并使用 utf8mb4 创建数据库,使用 utf8mb4 创建表(虽然表是使用默认数据库字符集创建的),但插入语句没有不能再工作了。所以我唯一能想到的是 charset=utf8mb4 在连接字符串中不起作用。但事实并非如此。我试图删除连接字符串中的字符集,并且在连接字符串中仅使用 utf8 字符集时再次出现与以前相同的错误

所以剩下什么,我不知道。

7 我已尝试将实例与 HDD 一起使用,而不是 SSD。

8 尝试通过 Google Cloud shell 连接并通过他们的控制台插入行。

ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x98\x8E' for column 'body' at row 1

有趣的是,即使在“显示创建表”中,云 shell 也显示该表的默认编码是 utf8mb4。所以云外壳(Light Bulb)就像mysqlworkbench一样默认连接utf8

终于

在插入数据库(在 python 中)之前,使用 db.session.execute("SET NAMES 'utf8mb4'") 工作,(并且仅在本地使用 ?charset=utf8mb4)。测试这样的东西时真正的问题可能是您使用什么方法来检查数据库中的结果。 MySQL Workbench 始终使用 utf8 编码作为默认连接(您可以使用上面的“SHOW ...”命令进行检查)。因此,首先要做的是使用 SET NAMES 'utf8mb4' 在 MySQL Workbench(或您的客户端)中切换连接。上面的测试表明,谷歌云shell默认也是用utf8连接的。我搜索了互联网,发现他们不能默认使用 utf8mb4,因为他们等待 utf8mb4 成为 mysql 中的新标准连接,并且成为这样的人将被命名为“utf8”。也没有办法让 MySQL Workbench 在连接后自动以 utf8mb4 运行。你应该自己做这件事。 从数据库读取时是否会出现问题?我现在要测试一下。

【讨论】:

是的,该项目在插入任何有问题的字符之前使用此 db.session.execute("SET NAMES 'utf8mb4'")。同样,请注意如何检查数据库中写入的内容。我使用的所有客户端,即使是在终端中工作的客户端,都默认使用 utf8。【参考方案6】:

将此添加到settings.py

'OPTIONS': 'charset': 'utf8mb4'

非常感谢:Unable to use utf8mb4 character set with CloudSQL on AppEngine Python

【讨论】:

以上是关于Google Cloud Sql 二代 Utf8Mb4 编码的主要内容,如果未能解决你的问题,请参考以下文章

来自应用引擎的 google cloud sql 允许的最大并发连接数

Google Cloud SQL 很慢:10GB RAM 的 mysql 实例比配置 125MB ram 的 Macbook Pro 慢 20 倍

Google Cloud Compute Engine 是不是与 Google Cloud SQL 分开

Google Cloud Spanner 和 Cloud SQL 有啥区别?

将 Spring Boot 应用程序连接到 Google Cloud 中的 MySQL 数据库

无法从 Data Fusion 连接 Cloud SQL mySql 实例。异常“无法创建套接字工厂 'com.google.cloud.sql.mysql.SocketFactory”