关于Alter Table的几句话,或如何做


这可能不是文章,而是有关在MySQL中使用大型表的某些功能的简短说明。

写作的原因似乎是每天在表中增加一个新列。 但是事实证明,一切都不如预期的那么简单。

因此,有一天晚上,为了不打扰我们亲爱的客户,我们需要在表格中添加一列。

为了更清楚地说明表和基的特征:

  • 桌子大小110Gb
  • 行数:750万
  • 存储引擎:InnoDB
  • 根据主从方案连接了两个sql服务器,而master在SSD上,slave在HDD上

这似乎是添加列-Alter Table的明显解决方案。

alter table table_name add source varchar(32) 

我们使用了它(是的,我们知道它很糟糕,但是在这种情况下,风险很小)。

结果非常不愉快:

  • 在向导上,添加列的过程大约花费了一个小时(!)
  • 在从属服务器上,它在主服务器上的过程结束后开始,并持续了大约8个小时(!!)
  • 在更改表期间,数据复制(!!!)在从属服务器上完全停止

但是有一线希望:有一小点好处是,在添加了列之后,表的大小减少了10%。

在下面的图中,它清晰可见。


向导上的CPU负载图。


从站上的CPU负载图。


复制滞后。

那些在战场上这样做的人有什么麻烦呢?

首先,在Alter Table期间,您无法将数据写入表(但可以读取)。 实际上,它取决于MySQL的版本,而后者则不取决于MySQL的版本,但是尽管如此,您仍需要了解您的版本到底能提供什么功能,以避免麻烦。

因此, 如果表很大,则不可用时间将很长 (与我们一样,使用SSD时需要一个小时,而在常规磁盘上则需要8个小时),这是您的客户不太可能期望的。

其次,就像我们的情况一样,在执行Alter Table的过程中, 所有表 (不仅是我们更改的表)的同步都完全停止在从属服务器上。 因此,如果您在第二台服务器上的数据很关键并且应该是最新的,则可能会不做任何更新而造成所有后续后果。

我们在添加列时遇到的另一个非显而易见的问题(但这是另一次)- 需要额外的磁盘空间

事实是,对表的某些更改会从头开始重新创建表,因此您所需要的空间不会少于现有表。 分别对于大桌子,需要适度的空间。 根据文档,在与原始目录相同的目录中创建一个临时表。

另外,在执行各种Alter Table的过程中,所有更改都将写入日志文件,以便在更改之后,可以在执行操作的时间内滚动数据。 在这里,也可能会遇到不愉快的意外:如果表长时间更改,并且操作量很大,那么不仅磁盘空间可能会用完,而且SQL设置中指定的文件大小限制可能会超出。 在任何情况下,“在线DDL操作都会失败,并且未提交的并发DML操作会回滚”等待着您。

我们面临这样一个事实,即临时文件的目录很小,结果我们不得不重新定义innodb_tmpdir

要查看变量当前指向的位置,可以执行以下操作:

 select @@GLOBAL.innodb_tmpdir; 

请记住,临时目录的大小可能也需要表+索引的大小。 通常,要有足够的空间。

为了不重复文档,请在https://dev.mysql.com/doc/refman/5.7/zh-CN/innodb-online-ddl-space-requirements.html上阅读更多详细信息。

但是怎么做呢? 实际上,没有适合所有场合的配方。

可能的选项之一,就像我们对不重要的表所做的那样:

  • 创建具有所需结构的新表
  • 填写旧表中的字段
  • 删除或重命名旧表
  • 重命名新的

我重复一遍,这适用于非关键更新表。 同时避免复制阻塞。 应当牢记的是,必须以使复制继续进行的方式填充新表,并且由于它是按顺序运行的,因此您无法使用单个sql表达式来执行操作,因此必须将其分成几个小查询,在这些小查询之间将进行其他数据的复制。 在其他情况下,其他选择也是可能的,也许有人会分享评论。

UPD Syavadee建议使用percona在线模式更改。 实际上,它以其他优点实现了上述算法。

UPD Arheops建议启用并行复制/ gtid以解决复制问题。

好吧,偶然地,有时候,为了了解表有多大,表中有多少行,您需要做一些教导

 select count(*) from table_name 

但是,在大型和已加载的表上,这也不是最快的操作,尤其是当您有50万行或更多的行时。

因此,对于近似的体积估计,可以使用以下方法:

 SHOW TABLE STATUS FROM express where name='table_name' 

不幸的是,在InnoDB引擎上,结果大小可能相差50%(在我们的示例中,如上表所示,实际记录数约为750万,而该方法仅显示了500万),但这非常适合进行指示性估算。

仅此而已,我希望本文能帮助某人避免使用原本无害的SQL命令带来的麻烦。

Source: https://habr.com/ru/post/zh-CN479696/


All Articles