我可以将 spamassassin bayes 标记从 utf8 CHAR(5) 转换为 BINARY(5) 吗?

我可以将 spamassassin bayes 标记从 utf8 CHAR(5) 转换为 BINARY(5) 吗?

我的 spamassassin 设置非常旧,已在两台机器之间迁移,并多次重新安装 mysql。我最近注意到,在运行sa-learn消息时,我的日志中会出现大量错误,如下所示:

bayes: _put_token: SQL error: Incorrect string value: '\x8A\x98s\x9A\xC8' for column 'token' at row 1

我检查了数据库并做了一些研究,发现这个非常古老的错误报告确定了问题所在:我的架构(非常)过时了。列的排序规则bayes_token.tokenCHAR(5)utf8_general_ci,而 9 年前它应该是BINARY(5)

我不能简单地转换列类型,因为许多 UTF8 5 字符值长于 5 个字节(该表有~110K 行)。

我的问题是:是否有任何方法可以截断过长的标记,以使其在贝叶斯分类器中保持有效?或者,如果做不到这一点,我可以只删除那些行,以便将剩余部分转换为二进制吗?

更新:我确实设法将列内容转移到BINARY(5)表中的添加列(此处名为token2),如下所示:

UPDATE bayes_token SET token2 = CONVERT(token USING latin1);

这是我所能想到的最接近“追溯”插入标记时所发生的情况的方法。但是,结果列中有许多重复项,并且由于该token列是主键的一部分,因此这样做不好。

我认为可以保存数据,但可能不能用纯 SQL。我需要:

  1. 根据最新架构创建空表的新副本
  2. 将每个标记的所有重复项分组,并将这些行的ham_countspam_countatime最大值相加
  3. 将这些汇总结果插入到新表中
  4. 用新表替换原始表

答案1

听起来文本可能有不同的编码。除非您先转换为 utf8mb4,否则您不能将不同的编码放入单个列中。但是,如果您不知道编码是什么,那就不切实际了。

如果您的目标只是传递字节,我会使用VARBINARY(..)BLOB,这样您就不会遇到字符集问题。

在 MySQL 中,foo VARCHAR(5) CHARACTER SET utf8最多可占用 15 个字节。对于 utf8mb4,最多可占用 20 个字节。因此VARBINARY(20),没有CHARACTER SET

如果你的表foo中当前有这样声明的内容,那么

ALTER TABLE t
    MODIFY COLUMN foo BINARY(20);

(根据需要添加NULLNOT NULL。)

答案2

我相信我已经尽我所能重建了数据,如下所示。

  1. token2 BINARY(5) NOT NULL向表中添加列bayes_token
  2. UPDATE bayes_token SET token2 = CONVERT(token USING latin1);
  3. bayes_token2使用现代模式创建新表
  4. INSERT INTO bayes_token2 SELECT '1' AS id, token2 AS token, SUM(spam_count) AS spam_count, SUM(ham_count) AS ham_count, MAX(atime) AS atime FROM bayes_token GROUP BY token2;
  5. 删除表格bayes_token并替换为bayes_token2

无论如何,绝大多数数据都是唯一的,并且在 UTF8 中不超过 5 个字节,但我认为我这样做的方式也以正确的方式保存了剩余部分。

相关内容