恢复后不同的 MySQL 数据文件大小

jua*_*n80 5 mysql innodb mysqldump backup size

我在数据库管理方面很新。我现在公司的数据库架构是主从复制。我们使用的是 MySQL 5.0.86 版。

几周前,我们升级了公司的主应用程序。此升级为其数据库的所有表添加了一列。升级前,我们的 ibdata 大小约为 3.1GiB。升级后是~5.2GiB。

今天,我已经用 mysqldump 完成了一个完整的备份恢复测试。恢复后,ibdata 大小约为 3.6 GiB。标准选择在恢复中显示与原始数据库中相同的数据。

我已经通过 select to information_schema 检查了数据大小(CUSTODIA 是我们主应用程序的名称):

select SUM(DATA_LENGTH+INDEX_LENGTH) from TABLES where TABLE_SCHEMA='CUSTODIA';
Run Code Online (Sandbox Code Playgroud)

这是主数据库中的结果:

+-------------------------------+
| SUM(DATA_LENGTH+INDEX_LENGTH) |
+-------------------------------+
|                    5683345068 |
+-------------------------------+
Run Code Online (Sandbox Code Playgroud)

这是恢复数据库的结果:

+-------------------------------+
| SUM(DATA_LENGTH+INDEX_LENGTH) |
+-------------------------------+
|                    3735748608 |
+-------------------------------+
Run Code Online (Sandbox Code Playgroud)

我的问题:

  1. 为什么原始和恢复的数据库大小之间存在这种差异?
  2. 尽管大小不同,但假设恢复的数据库没问题是否安全?
  3. MySQL如何计算data_length?是估价吗?
  4. 我可以在不停机的情况下安全地将生产的 ibdata 文件大小减少到 3.6GiB 吗?

对此的任何想法将不胜感激。谢谢你。

Rol*_*DBA 5

这对我来说是世界上所有的意义。

InnoDB 创建每个 16K 的数据页和索引页。如果数据行被插入、更新、删除、提交和回滚,你将有碎片!!!

有两种情况可以产生内部碎片:

  • 单行可以写入多个数据页,因为某些列值会使一行太大而无法放入数据页。
  • 有一个包含 32K 数据的 TEXT 列。

在这两种情况下,跨越多个数据页的单行必须像链表一样链接起来。读取行时,必须始终导航内部生成的数据页列表。

在信用到期时给予信用,PostgreSQL 实施了一种非常出色的机制,称为TOAST(超大属性存储技术),将超大数据保留在表之外,以阻止这种内部碎片化的趋势。

使用 mysqldump 使用 CREATE TABLE 语句创建文件,然后进行大量插入,当将 mysqldump 加载到新服务器时,您将获得一个没有未使用空间的新表以及连续数据和索引页。

对于我的解释,假设您在 CUSTODIA 数据库中有一个 InnoDB 表,名为 userinfo

如果您想压缩表,您有三 (3) 个选项

选项1

OPTIMIZE TABLE CUSTODIA.userinfo;
Run Code Online (Sandbox Code Playgroud)

选项 2

ALTER TABLE CUSTODIA.userinfo ENGINE=InnoDB;
Run Code Online (Sandbox Code Playgroud)

选项 3

CREATE TABLE CUSTODIA.userinfo2 LIKE CUSTODIA.userinfo;
INSERT INTO CUSTODIA.userinfo2 SELECT * FROM CUSTODIA.userinfo;
DROP TABLE CUSTODIA.userinfo;
ALTER TABLE CUSTODIA.userinfo2 RENAME CUSTODIA.userinfo;
Run Code Online (Sandbox Code Playgroud)

CAVEAT :选项 3 不适用于有约束的表。选项 3 非常适合 MyISAM。

现在回答您的问题:

问题 1. 为什么原始数据库和恢复后的数据库大小会有这种差异?

如上所述

问题 2. 尽管大小不同,但假设恢复的数据库没问题是否安全?

如果要绝对确保两台服务器上的数据相同,只需在两台数据库服务器上运行以下命令:

CHECKSUM TABLE CUSTODIA.userinfo;
Run Code Online (Sandbox Code Playgroud)

希望两台服务器上同一张表的校验和值相同。如果您有数十个甚至数百个表,则可能需要编写脚本。

问题三:MySQL如何计算data_length?是估价吗?

您正在使用正确的方法来总结 data_length 和 index_length。根据我对碎片的解释,这是一个估计。

问题 4. 我可以在不停机的情况下安全地将生产的 ibdata 文件大小减少到 3.6GiB 吗?

好消息 !!!你绝对可以压缩它!!!其实怎么想压缩到那个数字的一​​小部分???请遵循这两个链接,因为我在StackOverflowServerFault 中解决了这个问题。

/sf/ask/274938331/#4056261

https://serverfault.com/questions/230551/mysql-innodb-innodb-file-per-table-cons/231400#231400

坏消息 !!!抱歉,您将有 3-5 分钟的停机时间来重建 ib_logfile0 和 ib_logfile1 以及一劳永逸地缩小 ibdata1。这是非常值得的,因为它将是一次性操作。