前言
私有化 Gitea 从 1.18 升级到 1.21.1 后,无意间看到 维护
-> 自我检查
中报了一些问题:
期望数据库使用的校验方式:utf8mb4_ bin
数据库正在使用一个校验 utf8mb4_general_ci,这是一个不敏感的校验. 虽然Gitea可以与它合作,但可能有一些军见的情況不如预期的那样起作用。
但是当我看到官方文档里数据库准备的描述时:
使用 UTF-8 字符集和排序规则创建数据库。确保使用
**utf8mb4**
字符集,而不是utf8
,因为前者支持 Basic Multilingual Plane 之外的所有 Unicode 字符(包括表情符号)。排序规则根据您预期的内容选择。如果不确定,可以使用unicode_ci
或general_ci
。CREATE DATABASE giteadb CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';
根据需要替换数据库名称。
也不知道到底是我当初装的时候是意会错了还是什么,总之现在这个检查提示有问题就解决一下吧。
排序规则
在MySQL中,utf8mb4_bin
和 utf8mb4_general_ci
是两种不同的排序规则(collations)用于字符集 utf8mb4
。它们的主要区别在于字符串比较和排序的方式:
-
utf8mb4_bin
:- 二进制排序:比较和排序时,根据字符的二进制值进行逐字节比较。
- 区分大小写和重音:它区分大小写和重音符号,因此 ‘a’ 和 ‘A’ 被认为是不同的字符。
- 性能:因为是逐字节比较,性能通常较好,但不符合人类语言的排序习惯。
示例:
SELECT 'a' = 'A' COLLATE utf8mb4_bin; -- 返回 false SELECT 'a' < 'A' COLLATE utf8mb4_bin; -- 返回 true (根据二进制值比较)
-
utf8mb4_general_ci
:- 通用不区分大小写排序:比较和排序时,忽略字符的大小写和大多数重音符号。
- 不区分大小写和重音:‘a’ 和 ‘A’ 被认为是相同的字符,重音符号(如é和e)通常被忽略。
- 性能:虽然比
utf8mb4_bin
略慢,但对人类语言的排序更自然和直观。
示例:
SELECT 'a' = 'A' COLLATE utf8mb4_general_ci; -- 返回 true SELECT 'a' < 'A' COLLATE utf8mb4_general_ci; -- 返回 false
总结
utf8mb4_bin
适用于需要严格区分大小写和重音符号的场景,且性能较好,但不符合自然语言的排序习惯。utf8mb4_general_ci
适用于自然语言排序,忽略大小写和大多数重音符号,提供更自然的用户体验,但性能略低于utf8mb4_bin
。
选择哪种排序规则取决于你的具体需求和应用场景。
查询数据库的排序规则
你可以查询 information_schema.SCHEMATA
表来获取特定数据库的排序规则。
SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME = 'your_database_name';
将 your_database_name
替换为你想查询的数据库名称。
查询表的排序规则
你可以查询 information_schema.TABLES
表来获取特定表的排序规则。
SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database_name'
AND TABLE_NAME = 'your_table_name';
将 your_database_name
替换为你的数据库名称,将 your_table_name
替换为你想查询的表名称。
查询列的排序规则
你可以查询 information_schema.COLUMNS
表来获取特定列的排序规则。
SELECT COLUMN_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database_name'
AND TABLE_NAME = 'your_table_name'
AND COLUMN_NAME = 'your_column_name';
将 your_database_name
替换为你的数据库名称,将 your_table_name
替换为你的表名称,将 your_column_name
替换为你想查询的列名称。
修改排序规则
修改数据库的排序规则
按照你本地数据库名修改后执行SQL
ALTER DATABASE gitea COLLATE 'utf8mb4_bin';
如果只修改列数据库的排序规则,回到页面再次自我检查的时候发现提示列的排序规则不匹配,所以我们还需要修改表和列的排序规则
批量修改表的排序规则
可以使用存储过程之类的,但比较麻烦,直接拼接出所需修改的SQL拿来用最简单。
-- 修改表的排序规则
SELECT
CONCAT( 'ALTER TABLE ', TABLE_SCHEMA, '.', TABLE_NAME, ' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;' ) '查询结果'
FROM
INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = 'gitea';
执行后复制查询结果,再次执行即可
批量修改列的排序规则
与上述相同套路,拼接SQL。注意在MySQL中,只有字符类型的列(如 CHAR
, VARCHAR
, TEXT
等)具有排序规则(collation)。对于其他类型的列(如 INT
, FLOAT
, DATE
等),不存在排序规则的概念。因此,在修改所有表中所有列的排序规则时,需要仅针对字符类型的列进行修改。
-- 修改列的排序规则
SELECT
CONCAT( 'ALTER TABLE `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` MODIFY COLUMN `', COLUMN_NAME, '` ', COLUMN_TYPE, ' CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;' ) '查询结果'
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = 'gitea'
AND DATA_TYPE IN ( 'char', 'varchar', 'text', 'tinytext', 'mediumtext', 'longtext' );
执行后复制查询结果,再次执行即可
自我检查
回到页面再次点击 自我检查
可以看到提示 尚未发现问题
评论区