添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

随着业务快速增长,MySQL 数据量不断增加,会带来如下两个问题:

  • 磁盘空间吃紧 :数据库数据最终将会保存在本地磁盘中,数据记录越多,磁盘占用空间就会越多,对应剩余可用空间就会越少。
  • 查询效率降低 :MySQL 的 InnoDB 存储引擎的存储结构是 B+ 树,查找的时间复杂度是 O(log n)。随着数据量的增大,B+ 树自然也会变的很大,查找效率也会随之下降。
  • 所以,解决海量数据导致存储系统慢的问题,一般思路就是进行数据拆分,即 分片 。拆开之后,每个分片里的数据就没那么多了,然后让查找尽量落在某一个分片上,这样来提升查找性能。

    当单表的数据太多,多到影响性能的时候,首选的方案是: 归档历史数据

    数据归档的解决思路非常简单,就是将生产库的数据转移到拥有相同表结构的数据库中,通过减少生产库记录数量,从而提高数据查询等操作的效率。

    数据归档分为三个流程:

  • 创建一个新的数据库作为归档库,然后在归档库创建与生产库相同的表;
  • 不断查询生产库数据记录,同步复制到归档库;
  • 生产库删除已经复制的数据记录;
  • 数据归档需要考虑的问题:

  • 确定需要归档的数据范围;
  • 确定归档的执行方案:使用工具归档(pt-archiver)、自定义程序进行归档;
  • 确定数据归档后带来的问题的预案;
  • 归档需要考虑的问题

    1. 生产库备份
    在进行数据归档之前,一定要确保生产库的数据进行了备份。如果在归档过程中出现一些意想不到的问题,可以使用备份数据进行还原。

    2. 何时进行归档
    数据归档过程需要不断的读写生产库,这个过程将会大量使用的网络、IO。为了防止对线上业务造成压力,数据归档一般只在业务低峰期执行。另外,我们需要尽可能调优数据,尽量降低对线上业务的影响。

    3. 删除已复制数据
    数据归档之后,将会删除生产库的数据,这些数据删除之后,将会造成数据空洞。即数据删除之后,表空间并未及时的释放,当长时间没有新的数据填充,会造成空间浪费的情况。所以数据删除之后,需要及时优化数据空洞,释放这些被浪费的空间。

    4. 历史数据还原
    数据归档之后,生产库就会缺失这部分数据,如果业务上正好需要使用这些数据,那就会造成业务上异常。所以,我们需要提供数据 逆向接口 ,反向将归档数据库的记录重新还原到生产库。

    5. 数据一致性问题
    如果在进行数据归档的过程中,生产库中已复制的数据存在更新操作,那么会造成归档库与生产库的数据出现不一致的情况。所以,在进行数据归档时,需要保证历史数据没有更新操作。

    如何删除已复制数据

    还有一个很重要的细节问题:如何从原表中删除已经迁走的历史数据?直接执行一个删除历史数据的 SQL 行不行?比如:

    DELETE FROM orders WHERE createTime < SUBDATE(CURDATE(),INTERVAL 3 month);

    这样肯定是不行,如果删除的数据量比较大,会造成 SQL 语句占用时间长,锁的时间也比较长(即大事务),影响数据库性能;
    而正确的方式是进行 多次分批删除 ,并且最好在 每次删除之间停顿一会儿 ,避免给数据库造成太大的压力。

    DELETE FROM orders WHERE createTime < SUBDATE(CURDATE(),INTERVAL 3 month) ORDER BY id LIMIT 1000;

    由于会对原表已归档的数据进行删除,会造成数据空洞,也就是 表碎片 。所以需要定期对表碎片进行清理,即重建表,以释放磁盘空间。

    我们可以使用 alter table A engine=InnoDB 命令来重建表。重建表的过程中,索引也会重建,这样表数据和索引数据都会更紧凑,不仅占用磁盘空间更小,查询效率也会有提升。在 MySQL 8.0.26 或 8.0.29 这些高版本的数据库,执行此命令时,加锁时间很短,基本不会阻塞增删改操作。