侧边栏壁纸
  • 累计撰写 16 篇文章
  • 累计创建 52 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录
DB

Gitea 数据库校验方式

Stone
2024-06-22 / 0 评论 / 0 点赞 / 145 阅读 / 1,453 字

前言

私有化 Gitea 从 1.18 升级到 1.21.1 后,无意间看到 维护 -> 自我检查 中报了一些问题:

期望数据库使用的校验方式:utf8mb4_ bin

数据库正在使用一个校验 utf8mb4_general_ci,这是一个不敏感的校验. 虽然Gitea可以与它合作,但可能有一些军见的情況不如预期的那样起作用。

自我检查

但是当我看到官方文档里数据库准备的描述时:

  1. 使用 UTF-8 字符集和排序规则创建数据库。确保使用 **utf8mb4** 字符集,而不是 utf8,因为前者支持 Basic Multilingual Plane 之外的所有 Unicode 字符(包括表情符号)。排序规则根据您预期的内容选择。如果不确定,可以使用 unicode_cigeneral_ci

    CREATE DATABASE giteadb CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';
    

    根据需要替换数据库名称。

也不知道到底是我当初装的时候是意会错了还是什么,总之现在这个检查提示有问题就解决一下吧。

排序规则

在MySQL中,utf8mb4_binutf8mb4_general_ci 是两种不同的排序规则(collations)用于字符集 utf8mb4。它们的主要区别在于字符串比较和排序的方式:

  1. utf8mb4_bin

    • 二进制排序:比较和排序时,根据字符的二进制值进行逐字节比较。
    • 区分大小写和重音:它区分大小写和重音符号,因此 ‘a’ 和 ‘A’ 被认为是不同的字符。
    • 性能:因为是逐字节比较,性能通常较好,但不符合人类语言的排序习惯。

    示例:

    SELECT 'a' = 'A' COLLATE utf8mb4_bin; -- 返回 false
    SELECT 'a' < 'A' COLLATE utf8mb4_bin; -- 返回 true (根据二进制值比较)
    
  2. 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' );

执行后复制查询结果,再次执行即可

自我检查

回到页面再次点击 自我检查 可以看到提示 尚未发现问题

0

评论区