MySQL压缩大家好,我们都知道在MySQL中表压缩的好处,以目前的技术,处理速度和压缩磁盘,在大多数情况下,这是一个好处。

那么,如果没有这种情况会发生什么呢?

在这个简单的博客中,我将向您展示一些有趣的事情,当您试图从压缩表转换到普通表时,会发生这种情况。我们不打算详细讨论或讨论其他问题,例如:为什么表被压缩是件坏事?性能如何,系统性能如何,甚至不包括压缩需要消耗多少硬件资源?我们也不打算讨论内存中的页面是压缩的、未压缩的,还是两者都有。这已经讨论得够多了,你可以在我们的网站上找到一些非常有趣的博客,甚至在文档中也可以找到。

我将向您展示的是一些非常有趣的东西,为此,我们将从头到尾以一种您可以自己完成的方式执行这个练习(好吧,除了数据加载部分,呵呵!),我将给出一个示例脚本(稍后)。

让我们在数据库实例中创建表雷竞技下载官网Percona Server for MySQL 5.7安装。

之后,让我们用一些数据(100,000行)加载表。

让我们验证表的大小(之前使用innodb_stats_persistent_sample_pages=100000执行ANALYZE table,以便统计数据尽可能真实)。

接下来,我们将用KEY_BLOCK_SIZE=4压缩表(这个大小是任意选择的,在任何时候都没有指示或决定它是否是最佳值,事实上,它不是)。

我们再次验证表的大小(之前使用innodb_stats_persistent_sample_pages=100000执行ANALYZE table,以便统计数据尽可能真实)。

正如您所看到的,表已经被压缩了,让我们检查一下它的结构。

我们如何逆转压缩?好问题。应该很简单,对吧?

(澄清一下,在你问之前,我们不会根据表的大小来判断应该怎么做,这个ALTER会对复制产生什么影响,以及其他事情,我们的想法是展示如何反转它,而不是其他。)

我们可以使用这个命令,让我们看看:

这似乎起作用了!未压缩的:

更好的检查:

有点不对劲!KEY_BLOCK_SIZE仍然是4。

第二次尝试:

更好的检查:

有点不对劲!主键和辅助索引都继续显示KEY_BLOCK_SIZE=4。

虽然当表从压缩转换为未压缩时,在内部索引的KEY_BLOCK_SIZE尊重表的KEY_BLOCK_SIZE,但CREATE table语句不这样做。一开始,这可能是一个美观/表面的问题,但当您执行转储时,这是一个真正的问题,因为CREATE TABLE留下了KEY_BLOCK_SIZE值,这并不好。下面是mysqldump的输出:

正如你所看到的,似乎没有办法用全局ALTER table命令(如果我们可以这样称呼它的话)来反转表定义索引中的KEY_BLOCK_SIZE,所以我们将做最后一次尝试:

现在,它有了没有KEY_BLOCK_SIZE的正确定义:

显然,MariaDB中存在与案件相关的bug:

https://jira.mariadb.org/browse/MDEV-26400

https://jira.mariadb.org/browse/MDEV-11757

MySQL中也有类似的情况:

https://bugs.mysql.com/bug.php?id=56628

在MySQL 8中,情况如下:

让我们执行ALTER来压缩表:

让我们再检查一下:

到目前为止,一切都与MySQL 5.7相同:KEY_BLOCK_SIZE保留在整个表的定义中,而不是索引的定义中。

幸运的是,通过运行这个命令,我们有效地扭转了一切:

与往常一样,我们建议在生产环境中运行之前在开发环境中进行初步测试。

结论

在MySQL 5.7中,完全恢复(至少在表及其索引的定义中)的唯一方法是重新生成主键及其所有索引。这听起来像一个终端解决方案,但如果您使用mysqldump(我们总是建议使用rayben雷竞技 出于这些目的,它更快更有效),这是一个需要考虑的问题,因为在其定义中,它保留了那些错误的定义。幸运的是,这在MySQL 8中得到了修复。

很有趣,不是吗?

订阅
通知的
客人

2评论
最古老的
最新的 大多数投票
内联反馈
查看所有评论
让他赢

其他相关的MySQL错误:

这个问题在MySQL 8.0中看起来解决了,但是如果一个表以这种方式被改变了,那么升级一个安装会怎么样呢?

费尔南多Mattera

你好弗朗,

非常感谢你的评论。你能详细说明一下你的问题吗?你是在告诉我告诉客户端升级到MySQL 8,还是在告诉我如果我使用MySQL 5.7的修复,一段时间后我们迁移到MySQL 8,会发生什么,表的目标会发生什么。