第7章备份和恢复

目录

7.1备份和恢复类型
7.2数据库备份方法
7.3备份和恢复策略示例
7.3.1建立备份策略
7.3.2使用备份进行恢复
7.3.3备份策略摘要
7.4使用mysqldump进行备份
7.4.1使用mysqldump以SQL格式转储数据
7.4.2重新加载SQL格式备份
7.4.3使用mysqldump以分隔文本格式转储数据
7.4.4重新加载分隔文本格式备份
7.4.5 mysqldump提示
7.5使用二进制日志进行时间点(增量)恢复
7.5.1使用事件时间的时间点恢复
7.5.2使用事件位置的时间点恢复
7.6 MyISAM表维护和崩溃恢复
7.6.1使用myisamchk进行崩溃恢复
7.6.2如何检查MyISAM表是否存在错误
7.6.3如何修复MyISAM表
7.6.4 MyISAM表优化
7.6.5设置MyISAM表维护计划

备份数据库非常重要,这样您就可以恢复数据,并在发生问题时重新启动并运行,例如系统崩溃,硬件故障或用户错误地删除数据。 在升级MySQL安装之前,备份也是必不可少的保护措施,它们可用于将MySQL安装转移到另一个系统或设置复制从属服务器。

MySQL提供了各种备份策略,您可以从中选择最适合安装要求的方法。 本章讨论您应该熟悉的几个备份和恢复主题:

其他资源

与备份或维护数据可用性相关的资源包括:

7.1备份和恢复类型

本节介绍不同类型备份的特征。

物理(原始)与逻辑备份

物理备份由目录的原始副本和存储数据库内容的文件组成。 此类备份适用于需要在出现问题时快速恢复的大型重要数据库。

逻辑备份保存表示为逻辑数据库结构( CREATE DATABASE , CREATE TABLE 语句)和内容( INSERT 语句或分隔文本文件)的信息。 此类备份适用于较少量的数据,您可以在其中编辑数据值或表结构,或在不同的计算机体系结构上重新创建数据。

物理备份方法具有以下特征:

  • 备份包含数据库目录和文件的精确副本。 通常,这是MySQL数据目录的全部或部分副本。

  • 物理备份方法比逻辑更快,因为它们只涉及文件复制而不进行转换。

  • 输出比逻辑备份更紧凑。

  • 由于备份速度和紧凑性对繁忙,重要的数据库很重要,因此MySQL Enterprise Backup产品可执行物理备份。 有关MySQL Enterprise Backup产品的概述,请参见 第30.2节“MySQL Enterprise Backup概述” 。

  • 备份和还原粒度范围从整个数据目录的级别到单个文件的级别。 这可能会也可能不会提供表级粒度,具体取决于存储引擎。 例如, InnoDB 表可以分别位于单独的文件中,也可以与其他 InnoDB 表 共享文件存储 ; 每个 MyISAM 表唯一地对应于一组文件。

  • 除数据库外,备份还可以包括任何相关文件,如日志或配置文件。

  • 来自 MEMORY 表的 数据 很难以这种方式备份,因为它们的内容不存储在磁盘上。 (MySQL Enterprise Backup产品具有可 MEMORY 在备份期间 从 表中 检索数据的功能 。)

  • 备份仅可移植到具有相同或类似硬件特征的其他计算机。

  • 可以在MySQL服务器未运行时执行备份。 如果服务器正在运行,则必须执行适当的锁定,以便服务器在备份期间不会更改数据库内容。 MySQL Enterprise Backup会自动为需要它的表执行此锁定。

  • 物理备份工具包括用于 表 的MySQL Enterprise Backup 的 mysqlbackup InnoDB 或任何其他表,或文件系统级命令(如 cp , scp , tar , rsync ) MyISAM 。

  • 恢复:

    • MySQL Enterprise Backup还原 InnoDB 以及它备份的其他表。

    • ndb_restore 恢复 NDB 表。

    • 可以使用文件系统命令将在文件系统级别复制的文件复制回其原始位置。

逻辑备份方法具有以下特征:

  • 通过查询MySQL服务器以获取数据库结构和内容信息来完成备份。

  • 备份比物理方法慢,因为服务器必须访问数据库信息并将其转换为逻辑格式。 如果输出写在客户端,则服务器还必须将其发送到备份程序。

  • 输出大于物理备份,特别是以文本格式保存时。

  • 备份和还原粒度可在服务器级别(所有数据库),数据库级别(特定数据库中的所有表)或表级别中使用。 无论存储引擎如何,都是如此。

  • 备份不包括日志或配置文件,或其他不属于数据库的数据库相关文件。

  • 以逻辑格式存储的备份与机器无关且具有高度可移植性。

  • 在运行MySQL服务器的情况下执行逻辑备份。 服务器未脱机。

  • 逻辑备份工具包括 mysqldump 程序和 SELECT ... INTO OUTFILE 语句。 这些适用于任何存储引擎,甚至 MEMORY 。

  • 要恢复逻辑备份,可以使用 mysql 客户端 处理SQL格式转储文件 。 要加载分隔文本文件,请使用 LOAD DATA 语句或 mysqlimport 客户端。

在线与离线备份

在MySQL服务器运行时进行联机备份,以便可以从服务器获取数据库信息。 服务器停止时会发生脱机备份。 这种区别也可以描述为 “ 热 ” 与 “ 冷 ” 备份; 一个 “ 温暖 ” 的备份是一个在服务器保持运行,但锁定,以防止当你从外部访问数据库文件修改数据。

在线备份方法具有以下特征:

  • 备份对其他客户端的干扰较小,其他客户端可以在备份期间连接到MySQL服务器,并且可以根据需要执行的操作来访问数据。

  • 必须小心施加适当的锁定,以便不会发生会损害备份完整性的数据修改。 MySQL Enterprise Backup产品会自动执行此类锁定。

脱机备份方法具有以下特征:

  • 客户端可能会受到不利影响,因为备份期间服务器不可用。 因此,此类备份通常来自复制从属服务器,可以脱机而不会损害可用性。

  • 备份过程更简单,因为不会受到客户端活动的干扰。

在线和离线之间的类似区别适用于恢复操作,并且适用类似的特征。 但是,与在线备份相比,客户端更有可能受到在线恢复的影响,因为恢复需要更强的锁定。 在备份期间,客户端可能能够在备份数据时读取数据。 恢复修改数据而不仅仅是读取数据,因此必须防止客户端在恢复数据时访问数据。

本地与远程备份

本地备份在运行MySQL服务器的同一主机上执行,而远程备份则从其他主机执行。 对于某些类型的备份,即使输出是在服务器上本地写入的,也可以从远程主机启动备份。 主办。

  • mysqldump 可以连接到本地或远程服务器。 对于SQL输出( CREATE 和 INSERT 语句),可以完成本地或远程转储并在客户端上生成输出。 对于分隔文本输出(使用该 --tab 选项),将在服务器主机上创建数据文件。

  • SELECT ... INTO OUTFILE 可以从本地或远程客户端主机启动,但输出文件是在服务器主机上创建的。

  • 物理备份方法通常在MySQL服务器主机上本地启动,以便服务器可以脱机,但复制文件的目标可能是远程的。

快照备份

某些文件系统实现可以执行 “ 快照 ” 。 它们在给定时间点提供文件系统的逻辑副本,而不需要整个文件系统的物理副本。 (例如,实现可能使用写时复制技术,因此只需要复制快照时间之后修改的部分文件系统。)MySQL本身不提供获取文件系统快照的功能。 它可通过Veritas,LVM或ZFS等第三方解决方案获得。

完全与增量备份

完整备份包括MySQL服务器在给定时间点管理的所有数据。 增量备份包括在给定时间跨度内(从一个时间点到另一个时间点)对数据所做的更改。 MySQL有不同的方法来执行完整备份,例如本节前面所述的那些。 通过启用服务器的二进制日志(服务器用于记录数据更改),可以实现增量备份。

完全与时间点(增量)恢复

完全恢复可从完整备份中恢复所有数据。 这会将服务器实例还原到备份时的状态。 如果该状态不够充分,则可以在完全恢复之后恢复自完全备份以来所做的增量备份,以使服务器处于更新状态。

增量恢复是恢复在给定时间跨度内所做的更改。 这也称为时间点恢复,因为它使服务器的状态达到给定时间。 时间点恢复基于二进制日志,通常在备份文件完全恢复之后,将备份文件还原到备份时的状态。 然后,在二进制日志文件中写入的数据更改将作为增量恢复应用于重做数据修改,并使服务器达到所需的时间点。

表维护

如果表损坏,数据完整性可能会受到影响。 对于 InnoDB 表格,这不是典型问题。 MyISAM 如果 程序检查 表并在发现问题时进行修复,请参见 第7.6节“MyISAM表维护和崩溃恢复” 。

备份调度,压缩和加密

备份计划对于自动化备份过程很有价值。 压缩备份输出可减少空间需求,输出加密可提供更好的安全性,防止未经授权访问备份数据。 MySQL本身不提供这些功能。 MySQL Enterprise Backup产品可以压缩 InnoDB 备份,并且可以使用文件系统实用程序实现备份输出的压缩或加密。 可能还有其他第三方解决方案。

7.2数据库备份方法

本节总结了一些进行备份的常规方法。

使用MySQL Enterprise Backup进行热备份

MySQL Enterprise Edition的客户可以使用 MySQL Enterprise Backup 产品对 整个实例或选定的数据库,表或两者 进行 物理 备份。 此产品包括 增量 和 压缩 备份的功能。 备份物理数据库文件使得恢复比 mysqldump 命令 等逻辑技术快得多 。 InnoDB 使用 热备份 机制 复制表 。 (理想情况下, InnoDB 表应代表绝大部分数据。)使用 热备份 复制其他存储引擎的表 机制。 有关MySQL Enterprise Backup产品的概述,请参见 第30.2节“MySQL Enterprise Backup概述” 。

使用mysqldump进行备份

该 mysqldump的 程序可以进行备份。 它可以备份各种表。 (请参见 第7.4节“使用mysqldump进行备份” 。)

对于 InnoDB 表,可以使用 mysqldump --single-transaction 选项 执行不对表进行锁定的联机备份 。 请参见 第7.3.1节“建立备份策略” 。

通过复制表文件进行备份

可以通过复制表文件( *.MYD , *.MYI 文件和关联 *.sdi 文件) 来备份MyISAM表 。 要获得一致的备份,请停止服务器或锁定并刷新相关表:

带tbl_list读锁的冲洗表;

你只需要一个读锁; 这使得其他客户端可以在您复制数据库目录中的文件时继续查询表。 需要刷新以确保在开始备份之前将所有活动索引页写入磁盘。 请参见 第13.3.6节“LOCK TABLES和UNLOCK TABLES语法” 和 第13.7.7.3节“FLUSH语法” 。

只要服务器没有更新任何内容,您也可以通过复制表文件来创建二进制备份。 (但请注意,如果您的数据库包含 InnoDB 表 ,则表文件复制方法不起作用 。此外,即使服务器未主动更新数据, InnoDB 仍可能已将修改后的数据缓存在内存中而不会刷新到磁盘。)

有关此备份方法的示例,请参阅 第13.2.5节“IMPORT TABLE语法”中 的导出和导入示例 。

制作分隔文本文件备份

要创建包含表数据的文本文件,您可以使用 。 该文件是在MySQL服务器主机上创建的,而不是在客户端主机上创建的。 对于此语句,输出文件不能存在,因为允许覆盖文件会构成安全风险。 请参见 第13.2.10节“SELECT语法” 。 此方法适用于任何类型的数据文件,但仅保存表数据,而不保存表结构。 SELECT * INTO OUTFILE 'file_name' FROM tbl_name

创建文本数据文件的另一种方法(以及包含 CREATE TABLE 备份表的语句的 文件 )是使用 mysqldump 和该 --tab 选项。 请参见 第7.4.3节“使用mysqldump以分隔文本格式转储数据” 。

要重新加载分隔文本数据文件,请使用 LOAD DATA 或 mysqlimport 。

通过启用二进制日志进行增量备份

MySQL支持增量备份:必须使用 --log-bin 启用二进制日志记录 的 选项 启动服务器 ; 请参见 第5.4.4节“二进制日志” 。 二进制日志文件为您提供了在执行备份之后复制数据库所需的信息。 目前,您要进行增量备份(包含自上次完全备份或增量备份以来发生的所有更改),您应该使用旋转二进制日志 FLUSH LOGS 。 完成此操作后,您需要将所有二进制日志复制到备份位置,这些日志的范围从上次完全备份或增量备份到最后一个备份之一。 这些二进制日志是增量备份; 在还原时,按照 第7.5节“使用二进制日志进行时间点(增量)恢复”中的 说明应用它们 。 下次执行完整备份时,还应使用 FLUSH LOGS 或 mysqldump --flush-logs 旋转二进制 日志 。 请参见 第4.5.4节“ mysqldump - 数据库备份程序” 。

使用复制从站进行备份

如果在进行备份时主服务器出现性能问题,可以帮助的一种策略是在从服务器上而不是在主服务器上设置复制和执行备份。 请参见 第17.3.1节“使用备份复制” 。

如果要备份从属复制服务器,则在备份从属数据库时,应备份其主信息和中继日志信息存储库(请参见 第17.2.4节“复制中继和状态日志” ),无论备份方法如何你选。 恢复从属数据后,始终需要此信息才能恢复复制。 如果您的slave正在复制 LOAD DATA 语句,则还应备份 SQL_LOAD-* slave用于此目的的目录中存在的 所有 文件。 从站需要这些文件才能恢复任何中断 LOAD DATA 操作的 复制 。 该目录的位置是。的值 --slave-load-tmpdir 选项。 如果未使用该选项启动服务器,则目录位置是 tmpdir 系统变量 的值 。

恢复损坏的表

如果必须还原 MyISAM 已损坏的表,请先尝试使用 REPAIR TABLE 或 myisamchk -r 恢复它们 。 这应该在99.9%的情况下有效。 如果 myisamchk 失败,请参见 第7.6节“MyISAM表维护和崩溃恢复” 。

使用文件系统快照进行备份

如果您使用的是Veritas文件系统,则可以进行如下备份:

  1. 从客户端程序执行 FLUSH TABLES WITH READ LOCK 。

  2. 从另一个shell执行 mount vxfs snapshot 。

  3. 从第一个客户端执行 UNLOCK TABLES 。

  4. 从快照复制文件。

  5. 卸载快照。

类似的快照功能可能在其他文件系统中可用,例如LVM或ZFS。

7.3备份和恢复策略示例

本节讨论执行备份的过程,使您可以在几种类型的崩溃后恢复数据:

  • 操作系统崩溃

  • 电源(检测)失败

  • 文件系统崩溃

  • 硬件问题(硬盘驱动器,主板等)

该示例命令不包括诸如 --user 和 --password 针对 的mysqldump 和 MySQL的 客户端程序。 您应该包含必要的选项以使客户端程序能够连接到MySQL服务器。

假设数据存储在 InnoDB 存储引擎中,该引擎支持事务和自动崩溃恢复。 还假设MySQL服务器在崩溃时处于负载状态。 如果不是,则不需要恢复。

对于操作系统崩溃或电源故障的情况,我们可以假设重启后MySQL的磁盘数据可用。 该 InnoDB 数据文件可能不包含由于崩溃一致的数据,但 InnoDB 读取它的日志,并在其中发现挂起还没有被刷新到数据文件的提交和未提交的事务清单。 InnoDB 自动回滚那些未提交的事务,并刷新其已提交的数据文件。 有关此恢复过程的信息将通过MySQL错误日志传达给用户。 以下是示例日志摘录:

InnoDB:数据库没有正常关闭。
InnoDB:从日志文件开始恢复......
InnoDB:根据检查点启动日志扫描
InnoDB:日志序列号0 13674004
InnoDB:执行恢复:扫描到日志序列号0 13739520
InnoDB:执行恢复:扫描到日志序列号0 13805056
InnoDB:执行恢复:扫描到日志序列号0 13870592
InnoDB:执行恢复:扫描到日志序列号0 13936128
...
InnoDB:执行恢复:扫描到日志序列号0 20555264
InnoDB:执行恢复:扫描到日志序列号0 20620800
InnoDB:执行恢复:扫描到日志序列号0 20664692
InnoDB:1个未提交的事务,必须回滚
InnoDB:开始回滚未提交的事务
InnoDB:回滚trx no 16745
InnoDB:回滚trx no 16745完成
InnoDB:完成了未提交事务的回滚
InnoDB:启动一批日志记录到数据库......
InnoDB:申请批量完成
InnoDB:开始了
mysqld:准备连接

对于文件系统崩溃或硬件问题的情况,我们可以假设 重启后 MySQL磁盘数据 不可 用。 这意味着MySQL无法成功启动,因为某些磁盘数据块不再可读。 在这种情况下,有必要重新格式化磁盘,安装新磁盘或以其他方式纠正基础问题。 然后有必要从备份中恢复MySQL数据,这意味着必须已经进行备份。 为了确保这种情况,请设计并实施备份策略。

7.3.1建立备份策略

为了有用,必须定期安排备份。 可以使用多种工具在MySQL中完成完整备份(某个时间点的数据快照)。 例如, MySQL Enterprise Backup 可以执行 整个实例 的 物理备份 ,通过优化来最小化开销并避免在备份 InnoDB 数据文件 时中断 ; mysqldump 提供在线 逻辑备份 。 本讨论使用 mysqldump 。

假设我们 InnoDB 在周日下午1点使用以下命令对所有数据库中 的所有 表 进行完整备份 ,当负载较低时:

外壳> mysqldump --all-databases --master-data --single-transaction > backup_sunday_1_PM.sql

mysqldump 生成的结果 .sql 文件 包含一组SQL 语句,可用于稍后重新加载转储的表。 INSERT

此备份操作在转储开始时(使用 FLUSH TABLES WITH READ LOCK ) 获取所有表的全局读锁定 。 获取此锁定后,将读取二进制日志坐标并释放锁定。 如果在 FLUSH 发出 语句时正在运行长更新语句 ,则备份操作可能会停止,直到这些语句完成。 之后,转储变得无锁,并且不会干扰表上的读取和写入。

之前假设要备份的表是 InnoDB 表,因此 --single-transaction 使用一致的读取并保证 mysqldump 看到的数据 不会更改。 ( mysqldump 进程 InnoDB 看不到 其他客户端对 表 所做的更改 。)如果备份操作包括非事务性表,则一致性要求它们在备份期间不会更改。 例如,对于 数据库中 的 表, 备份期间不得对MySQL帐户进行任何管理更改。 MyISAM mysql

完整备份是必要的,但创建它们并不总是方便。 它们生成大型备份文件并花费时间生成。 它们并不是最佳的,因为每个连续的完整备份都包含所有数据,即使是自上次完全备份以来未发生更改的部分。 进行初始完整备份然后进行增量备份更有效。 增量备份更小,生成时间更短。 权衡是,在恢复时,只能通过重新加载完整备份来恢复数据。 您还必须处理增量备份以恢复增量更改。

要进行增量备份,我们需要保存增量更改。 在MySQL中,这些更改在二进制日志中表示,因此应始终使用 --log-bin 启用该日志 的 选项 启动MySQL服务器 。 启用二进制日志记录后,服务器会在更新数据时将每个数据更改写入文件。 查看使用该 --log-bin 选项 启动 并且已运行了几天 的MySQL服务器的数据目录 ,我们找到这些MySQL二进制日志文件:

-rw-rw ---- 1 guilhem guilhem 1277324 11月10日23:59 gbichot2-bin.000001
-rw-rw ---- 1 guilhem guilhem 4月10日23:59 gbichot2-bin.000002
-rw-rw ---- 1 guilhem guilhem 79 Nov 11 11:06 gbichot2-bin.000003
-rw-rw ---- 1 guilhem guilhem 508 Nov 11 11:08 gbichot2-bin.000004
-rw-rw ---- 1 guilhem guilhem 220047446 11月12日16:47 gbichot2-bin.000005
-rw-rw ---- 1 guilhem guilhem 998412 11月14日10:08 gbichot2-bin.000006
-rw-rw ---- 1 guilhem guilhem 361 Nov 14 10:07 gbichot2-bin.index

每次重新启动时,MySQL服务器都会使用序列中的下一个数字创建一个新的二进制日志文件。 在服务器运行时,您还可以通过发出 FLUSH LOGS SQL语句或使用 mysqladmin flush-logs 命令 告诉它关闭当前的二进制日志文件并手动开始新的日志文件 。 mysqldump 还有一个刷新日志的选项。 该 .index 数据目录文件中包含该目录下所有MySQL二进制日志的清单。

MySQL二进制日志对于恢复非常重要,因为它们构成了一组增量备份。 如果确保在进行完全备份时刷新日志,则之后创建的二进制日志文件将包含自备份以来所做的所有数据更改。 让我们 稍微 修改之前的 mysqldump 命令,以便在完全备份时冲洗MySQL二进制日志,以便转储文件包含新的当前二进制日志的名称:

外壳> mysqldump --single-transaction --flush-logs --master-data=2 \
         --all-databases > backup_sunday_1_PM.sql

执行此命令后,数据目录包含新的二进制日志文件 gbichot2-bin.000007 ,因为该 --flush-logs 选项会导致服务器刷新其日志。 该 --master-data 选项导致 mysqldump 将二进制日志信息写入其输出,因此生成的 .sql 转储文件包括以下行:

- 从中​​开始复制或时间点恢复的位置
-  CHANGE MASTER TO MASTER_LOG_FILE ='gbichot2-bin.000007',MASTER_LOG_POS = 4;

因为 mysqldump 命令进行了完整备份,所以这些行意味着两件事:

  • 转储文件包含在写入 gbichot2-bin.000007 二进制日志文件或更高版本的 任何更改之前所做的所有更改 。

  • 备份后记录的所有数据更改都不存在于转储文件中,但存在于 gbichot2-bin.000007 二进制日志文件或更高版本中。

在星期一下午1点,我们可以通过刷新日志来开始新的二进制日志文件来创建增量备份。 例如,执行 mysqladmin flush-logs 命令会创建 gbichot2-bin.000008 。 周日下午1点完整备份和周一下午1点之间的所有更改都将在 gbichot2-bin.000007 文件中。 此增量备份很重要,因此最好将其复制到安全的地方。 (例如,将其备份到磁带或DVD上,或将其复制到另一台计算机上。)在星期二下午1点,执行另一个 mysqladmin flush-logs 命令。 周一下午1点到周二下午1点之间的所有更改都将在 gbichot2-bin.000008 文件中(也应该在安全的地方复制)。

MySQL二进制日志占用磁盘空间。 为了腾出空间,不时清除它们。 一种方法是删除不再需要的二进制日志,例如当我们进行完整备份时:

外壳> mysqldump --single-transaction --flush-logs --master-data=2 \
         --all-databases --delete-master-logs > backup_sunday_1_PM.sql
注意

如果您的服务器是复制主服务器,则 使用 mysqldump --delete-master-logs 删除MySQL二进制日志 可能会很危险,因为从服务器可能尚未完全处理二进制日志的内容。 该 PURGE BINARY LOGS 语句 的描述 说明了在删除MySQL二进制日志之前应该验证的内容。 请参见 第13.4.1.1节“PURGE BINARY LOGS语法” 。

7.3.2使用备份进行恢复

现在,假设我们在星期三上午8点发生了灾难性的崩溃,需要从备份中恢复。 要恢复,首先我们恢复上一次完整备份(从星期日下午1点开始)。 完整备份文件只是一组SQL语句,因此恢复它非常简单:

外壳> mysql < backup_sunday_1_PM.sql

此时,数据将恢复到截至周日下午1点的状态。 要恢复自那时以来所做的更改,我们必须使用增量备份; 也就是 gbichot2-bin.000007 和 gbichot2-bin.000008 二进制日志文件。 必要时从备份位置获取文件,然后按如下方式处理其内容:

外壳> mysqlbinlog gbichot2-bin.000007 gbichot2-bin.000008 | mysql

我们现在已经将数据恢复到周二下午1点的状态,但仍然缺少从该日期到崩溃日期的更改。 为了不丢失它们,我们需要让MySQL服务器将其MySQL二进制日志存储到与存储其数据文件的地方不同的安全位置(RAID磁盘,SAN,...),以便这些日志不会在被破坏的磁盘上。 (也就是说,我们可以使用一个 --log-bin 选项 来启动服务器,该 选项指定与数据目录所在的物理设备不同的物理设备上的位置。这样,即使包含该目录的设备丢失,日志也是安全的。)如果我们做到了这一点,我们会有 gbichot2-bin.000009 手头的文件(以及任何后续文件),我们可以使用 mysqlbinlog 和 mysql 来 应用它们 来恢复最新的数据更改,直到崩溃时都没有损失:

外壳> mysqlbinlog gbichot2-bin.000009 ... | mysql

有关使用 mysqlbinlog 处理二进制日志文件的 更多信息 ,请参见 第7.5节“使用二进制日志进行时间点(增量)恢复” 。

7.3.3备份策略摘要

如果操作系统崩溃或电源故障, InnoDB 它本身会完成恢复数据的所有工作。 但为了确保您能够安然入睡,请遵守以下准则:

7.4使用mysqldump进行备份

本节介绍如何使用 mysqldump 生成转储文件,以及如何重新加载转储文件。 转储文件可以通过多种方式使用:

  • 作为备份,在数据丢失的情况下启用数据恢复。

  • 作为设置复制从属的数据源。

  • 作为实验数据的来源:

    • 制作可以在不更改原始数据的情况下使用的数据库副本。

    • 测试潜在的升级不兼容性。

mysqldump 产生两种类型的输出,具体取决于是否 --tab 给出 了 选项:

  • 没有 --tab , mysqldump 将SQL语句写入标准输出。 此输出包含 CREATE 用于创建转储对象(数据库,表,存储例程等)的 INSERT 语句 ,以及 用于将数据加载到表中的语句。 输出可以保存在文件中,稍后使用 mysql 重新 加载 以重新创建转储的对象。 选项可用于修改SQL语句的格式,以及控制转储哪些对象。

  • 使用 --tab , mysqldump 为每个转储表生成两个输出文件。 服务器将一个文件写为制表符分隔的文本,每个表行一行。 此文件 tbl_name.txt 在输出目录中 命名 。 服务器还将 CREATE TABLE 表 的 语句 发送 到 mysqldump , mysqldump 将其写为 tbl_name.sql 输出目录中 指定的文件 。

7.4.1使用mysqldump以SQL格式转储数据

本节介绍如何使用 mysqldump 创建SQL格式转储文件。 有关重新加载此类转储文件的信息,请参见 第7.4.2节“重新加载SQL格式备份” 。

默认情况下, mysqldump 将信息作为SQL语句写入标准输出。 您可以将输出保存在文件中:

外壳> mysqldump [arguments] > file_name

要转储所有数据库,请 使用以下 选项 调用 mysqldump --all-databases :

外壳> mysqldump --all-databases > dump.sql

要仅转储特定数据库,请在命令行中为它们命名并使用以下 --databases 选项:

外壳> mysqldump --databases db1 db2 db3 > dump.sql

该 --databases 选项使命令行上的所有名称都被视为数据库名称。 如果没有此选项, mysqldump 会将第一个名称视为数据库名称,将后续名称视为表名称。

使用 --all-databases or --databases , mysqldump 在每个数据库的转储输出之前 写入 CREATE DATABASE 和 USE 语句。 这可确保在重新加载转储文件时,如果每个数据库不存在,它将创建每个数据库,并使其成为默认数据库,以便将数据库内容加载到它们所来自的同一数据库中。 如果要在重新创建数据库之前使转储文件强制删除每个数据库,请同时使用该 --add-drop-database 选项。 在这种情况下, mysqldump 在 DROP DATABASE 每个 CREATE DATABASE 语句 之前 写一个 语句。

要转储单个数据库,请在命令行中为其命名:

外壳> mysqldump --databases test > dump.sql

在单数据库的情况下,允许省略 --databases 选项:

外壳> mysqldump test > dump.sql

前面两个命令之间的区别在于,没有 --databases ,转储输出包含no CREATE DATABASE 或 USE 语句。 这有几个含义:

  • 重新加载转储文件时,必须指定默认数据库名称,以便服务器知道要重新加载的数据库。

  • 对于重新加载,您可以指定与原始名称不同的数据库名称,这使您可以将数据重新加载到其他数据库中。

  • 如果要重新加载的数据库不存在,则必须先创建它。

  • 由于输出不包含任何 CREATE DATABASE 语句,因此该 --add-drop-database 选项无效。 如果你使用它,它不会产生任何 DROP DATABASE 声明。

要仅从数据库转储特定表,请在数据库名称后面的命令行中为它们命名:

外壳> mysqldump test t1 t3 t7 > dump.sql

7.4.2重新加载SQL格式备份

要重新加载由 mysqldump 编写的 包含SQL语句 的转储文件 ,请将其用作 mysql 客户端的 输入 。 如果转储文件是由 mysqldump 使用 --all-databases or --databases 选项 创建的 ,则它包含 CREATE DATABASE 和 USE 语句,并且没有必要指定要加载数据的默认数据库:

外壳> mysql < dump.sql

或者,从 mysql中 ,使用 source 命令:

MySQL的> source dump.sql

如果文件是不包含 CREATE DATABASE 和 USE 语句 的单数据库转储 ,请首先创建数据库(如有必要):

外壳> mysqladmin create db1

然后在加载转储文件时指定数据库名称:

外壳> mysql db1 < dump.sql

或者,在 mysql 中创建数据库,将其选为默认数据库,然后加载转储文件:

mysql> CREATE DATABASE IF NOT EXISTS db1;
mysql> USE db1;
mysql>source dump.sql
注意

对于Windows PowerShell用户:由于“<”字符保留供将来在PowerShell中使用,因此需要一种替代方法,例如使用引号 cmd.exe /c "mysql < dump.sql" 。

7.4.3使用mysqldump以分隔文本格式转储数据

本节介绍如何使用 mysqldump 创建分隔文本转储文件。 有关重新加载此类转储文件的信息,请参见 第7.4.4节“重新加载分隔文本格式备份” 。

如果 使用该 选项 调用 mysqldump ,它将 用作输出目录,并使用每个表的两个文件在该目录中单独转储表。 表名是这些文件的基本名称。 对于名为的表 ,文件名为 and 。 该 文件包含 该表 的 语句。 该 文件包含表数据,每个表行一行。 --tab=dir_name dir_name t1 t1.sql t1.txt .sql CREATE TABLE .txt

以下命令将 db1 数据库 的内容转储到 数据库中的文件 /tmp :

外壳> mysqldump --tab=/tmp db1

.txt 包含表数据 的 文件由服务器写入,因此它们由用于运行服务器的系统帐户拥有。 服务器用于 SELECT ... INTO OUTFILE 写入文件,因此您必须具有 FILE 执行此操作 的 权限,并且如果给定 .txt 文件已存在 则会发生错误 。

服务器将 CREATE 转储表 的 定义 发送 到 mysqldump ,后者将它们写入 .sql 文件。 因此,这些文件由执行 mysqldump 的用户拥有 。

最好 --tab 只用于转储本地服务器。 如果您与远程服务器使用,该 --tab 目录必须存在于本地和远程主机都和 .txt 文件将通过在远程目录服务器(服务器主机上)写,而 .sql 文件将被写入 的mysqldump 在本地目录(在客户端主机上)。

对于 mysqldump --tab ,服务器默认情况下将表数据写入 .txt 文件每行一行,列值之间有选项卡,列值周围没有引号,新行作为行终止符。 (这些默认值与 SELECT ... INTO OUTFILE 。 相同 。)

要使用不同的格式写入数据文件, mysqldump 支持以下选项:

根据您为任何这些选项指定的值,可能需要在命令行上为命令解释程序引用或转义值。 或者,使用十六进制表示法指定值。 假设您希望 mysqldump 在双引号内引用列值。 为此,请指定双引号作为 --fields-enclosed-by 选项 的值 。 但是这个角色通常对指挥口译员来说是特殊的,必须特别对待。 例如,在Unix上,您可以引用双引号,如下所示:

--fields封闭逐=““”

在任何平台上,您都可以以十六进制指定值:

--fields封闭逐=为0x22

通常一起使用几个数据格式化选项。 例如,要以逗号分隔值格式转储表格,并使用由回车符/换行符对( \r\n ) 终止的行 ,请使用此命令(在一行中输入):

外壳> mysqldump --tab=/tmp --fields-terminated-by=,
         --fields-enclosed-by='"' --lines-terminated-by=0x0d0a db1

如果您使用任何数据格式化选项来转储表数据,则需要在以后重新加载数据文件时指定相同的格式,以确保正确解释文件内容。

7.4.4重新加载分隔文本格式备份

对于使用 mysqldump生成的 备份 --tab ,每个表在输出目录中由 .sql 包含 CREATE TABLE 表 的 语句的 .txt 文件 和 包含表数据 的 文件表示。 要重新加载表,首先将位置更改为输出目录。 然后 .sql 使用 mysql 处理 文件 以创建一个空表并处理该 .txt 文件以将数据加载到表中:

shell> mysql db1 < t1.sql
shell>mysqlimport db1 t1.txt

使用 mysqlimport 加载数据文件 的另一种方法 是使用 mysql 客户端中 的 LOAD DATA 语句 :

mysql> USE db1;
mysql>LOAD DATA INFILE 't1.txt' INTO TABLE t1;

如果 在最初转储表时 使用了 mysqldump的 任何数据格式化选项 ,则必须使用与 mysqlimport 相同的选项 或 LOAD DATA 确保正确解释数据文件内容:

外壳> mysqlimport --fields-terminated-by=,
         --fields-enclosed-by='"' --lines-terminated-by=0x0d0a db1 t1.txt

要么:

mysql> USE db1;
mysql>LOAD DATA INFILE 't1.txt' INTO TABLE t1
       FIELDS TERMINATED BY ',' FIELDS ENCLOSED BY '"'
       LINES TERMINATED BY '\r\n';

7.4.5 mysqldump提示

本节介绍了使用 mysqldump 解决特定问题的技术:

  • 如何复制数据库

  • 如何将数据库从一个服务器复制到另一个服务器

  • 如何转储存储的程序(存储过程和函数,触发器和事件)

  • 如何单独转储定义和数据

7.4.5.1制作数据库副本

shell> mysqldump db1 > dump.sql
shell> mysqladmin create db2
shell>mysql db2 < dump.sql

不要 --databases 在 mysqldump 命令行 上 使用 , 因为这会导致 USE db1 包含在转储文件中,这会覆盖 db2 在 mysql 命令行 上命名的效果 。

7.4.5.2将数据库从一个服务器复制到另一个服务器

在服务器1上:

外壳> mysqldump --databases db1 > dump.sql

将转储文件从服务器1复制到服务器2。

在服务器2上:

外壳> mysql < dump.sql

使用 --databases 与 mysqldump的 命令行导致转储文件,包括 CREATE DATABASE 与 USE 创建数据库语句,如果它确实存在,并使其成为默认的数据库为重新加载数据。

或者,你可以省略 --databases 从 mysqldump的 命令。 然后,您需要在服务器2上创建数据库(如果需要),并在重新加载转储文件时将其指定为默认数据库。

在服务器1上:

外壳> mysqldump db1 > dump.sql

在服务器2上:

shell> mysqladmin create db1
shell>mysql db1 < dump.sql

你可以在这种情况下指定不同的数据库名称,所以省略 --databases 从 mysqldump的 命令,可以从一个数据库转储数据并将其加载到另一个。

7.4.5.3转储存储的程序

有几个选项控制 mysqldump 如何 处理存储的程序(存储过程和函数,触发器和事件):

--triggers 默认情况下启用 该 选项,以便在转储表时,它们伴随着它们具有的任何触发器。 默认情况下禁用其他选项,必须明确指定以转储相应的对象。 要禁用的任何选项明确,利用其跳跃的形式: --skip-events , --skip-routines ,或 --skip-triggers 。

7.4.5.4单独倾倒表定义和内容

该 --no-data 选项告诉 mysqldump 不要转储表数据,导致转储文件只包含用于创建表的语句。 相反,该 --no-create-info 选项告诉 mysqldump 禁止 CREATE 输出语句,以便转储文件仅包含表数据。

例如,要分别为 test 数据库 转储表定义和数据 ,请使用以下命令:

shell> mysqldump --no-data test > dump-defs.sql
shell>mysqldump --no-create-info test > dump-data.sql

对于仅定义转储,添加 --routines 和 --events 选项还包括存储的例程和事件定义:

外壳> mysqldump --no-data --routines --events test > dump-defs.sql

7.4.5.5使用mysqldump测试升级不兼容性

在考虑进行MySQL升级时,谨慎的做法是将新版本与当前的生产版本分开安装。 然后,您可以从生产服务器转储数据库和数据库对象定义,并将它们加载到新服务器中,以验证它们是否已正确处理。 (这对于测试降级也很有用。)

在生产服务器上:

外壳> mysqldump --all-databases --no-data --routines --events > dump-defs.sql

在升级的服务器上:

外壳> mysql < dump-defs.sql

由于转储文件不包含表数据,因此可以快速处理。 这使您能够发现潜在的不兼容性,而无需等待冗长的数据加载操作。 在处理转储文件时查找警告或错误。

验证定义处理正确后,转储数据并尝试将其加载到升级后的服务器中。

在生产服务器上:

外壳> mysqldump --all-databases --no-create-info > dump-data.sql

在升级的服务器上:

外壳> mysql < dump-data.sql

现在检查表内容并运行一些测试查询。

7.5使用二进制日志进行时间点(增量)恢复

时间点恢复是指恢复自给定时间点以来所做的数据更改。 通常,在还原完整备份之后执行此类型的恢复,该备份使服务器进入备份时的状态。 (完整备份可以通过多种方式进行,例如 第7.2节“数据库备份方法”中 列出的那些 。)时间点恢复然后使服务器从完全备份的时间开始逐步更新为更多最近的时间。

注意

这里的许多示例都使用 mysql 客户端来处理 mysqlbinlog 生成的二进制日志输出 。 如果您的二进制日志包含 \0 (null)字符,则 除非您使用该 选项 调用 该输出, 否则 mysql 无法解析该输出 --binary-mode 。

时间点恢复的信息源是由完全备份操作之后生成的二进制日志文件表示的增量备份集。 因此,必须使用 --log-bin 启用二进制日志记录 的 选项 启动服务器 (请参见 第5.4.4节“二进制日志” )。

要从二进制日志还原数据,您必须知道当前二进制日志文件的名称和位置。 默认情况下,服务器在数据目录中创建二进制日志文件,但可以使用 --log-bin 选项将文件放在不同的位置 来指定路径名 。 第5.4.4节“二进制日志” 。

要查看所有二进制日志文件的列表,请使用以下语句:

MySQL的> SHOW BINARY LOGS;

要确定当前二进制日志文件的名称,请发出以下语句:

MySQL的> SHOW MASTER STATUS;

该 mysqlbinlog可以 实用转换从二进制格式的二进制日志文件的事件文本,以便他们可以执行或查看。 mysqlbinlog 具有根据日志中事件时间或事件位置选择二进制日志部分的选项。 请参见 第4.6.8节“ mysqlbinlog - 处理二进制日志文件的实用程序” 。

从二进制日志执行事件会导致重做它们所代表的数据修改。 这样可以在给定的时间范围内恢复数据更改。 要从二进制日志执行事件,请 使用 mysql 客户端 处理 mysqlbinlog 输出 :

外壳> mysqlbinlog binlog_files | mysql -u root -p

如果二进制日志文件已经加密,可以从MySQL 8.0.14开始加密, mysqlbinlog 不能像上面的例子那样直接读取它们,但是可以使用 --read-from-remote-server ( -R )选项 从服务器读取它们 。 例如:

外壳> mysqlbinlog --read-from-remote-server --host=host_name --port=3306  --user=root --password --ssl-mode=required  binlog_files | mysql -u root -p

这里,该选项 --ssl-mode=required 用于确保二进制日志文件中的数据在传输过程中受到保护,因为它 以未加密的格式 发送到 mysqlbinlog 。

在需要确定事件时间或位置以在执行事件之前选择部分日志内容时,查看日志内容非常有用。 要从日志中查看事件,请将 mysqlbinlog 输出 发送 到分页程序:

外壳> mysqlbinlog binlog_files | more

或者,将输出保存在文件中并在文本编辑器中查看文件:

shell> 
shell> ......
mysqlbinlog binlog_files > tmpfileedit tmpfile

将输出保存在文件中非常有用,可以在删除某些事件(例如意外事件)时执行日志内容 DROP DATABASE 。 您可以在执行其内容之前从文件中删除任何不执行的语句。 编辑文件后,执行如下内容:

外壳> mysql -u root -p < tmpfile

如果要在MySQL服务器上执行多个二进制日志,则安全方法是使用与服务器的单个连接来处理它们。 这是一个演示可能 不安全 的示例 :

shell> mysqlbinlog binlog.000001 | mysql -u root -p # DANGER!!
shell>mysqlbinlog binlog.000002 | mysql -u root -p # DANGER!!

如果第一个日志文件包含 CREATE TEMPORARY TABLE 语句而第二个日志包含使用临时表的语句,则使用与 服务器的不同连接以这种方式处理二进制日志会导致问题 。 当第一个 mysql 进程终止时,服务器将删除临时表。 当第二个 mysql 进程尝试使用该表时,服务器报告 “ 未知表”。 ”

为避免此类问题,请使用 单个 连接来执行要处理的所有二进制日志的内容。 这是一种方法:

外壳> mysqlbinlog binlog.000001 binlog.000002 | mysql -u root -p

另一种方法是将所有日志写入单个文件,然后处理该文件:

shell> mysqlbinlog binlog.000001 >  /tmp/statements.sql
shell> mysqlbinlog binlog.000002 >> /tmp/statements.sql
shell>mysql -u root -p -e "source /tmp/statements.sql"

在从包含GTID的二进制日志中读取时写入转储文件时(请参见 第17.1.3节“使用全局事务标识符复制” ),请使用 mysqlbinlog --skip-gtids 选项 ,如下所示:

shell> mysqlbinlog --skip-gtids binlog.000001 >  /tmp/dump.sql
shell> mysqlbinlog --skip-gtids binlog.000002 >> /tmp/dump.sql
shell>mysql -u root -p -e "source /tmp/dump.sql"

7.5.1使用事件时间的时间点恢复

要指示恢复的开始和结束时间 ,请以 格式 指定 mysqlbinlog 的 --start-datetime 和 --stop-datetime 选项 。 例如,假设确切地在2005年4月20日上午10:00执行了删除大表的SQL语句。 要还原表和数据,可以还原前一晚的备份,然后执行以下命令: DATETIME

外壳> mysqlbinlog --stop-datetime="2005-04-20 9:59:59" \
         /var/log/mysql/bin.123456 | mysql -u root -p

此命令将恢复所有数据,直到该 --stop-datetime 选项 给出的日期和时间 。 如果您没有检测到几小时后输入的错误SQL语句,您可能还希望恢复之后发生的活动。 基于此,您可以 使用开始日期和时间再次 运行 mysqlbinlog ,如下所示:

外壳> mysqlbinlog --start-datetime="2005-04-20 10:01:00" \
         /var/log/mysql/bin.123456 | mysql -u root -p

在此命令中,将重新执行从上午10:01开始记录的SQL语句。 恢复前一晚的转储文件和两个 mysqlbinlog 命令的组合将所有内容恢复到上午10:00之前的一秒钟以及从上午10:01开始的所有内容。

要使用此时间点恢复方法,您应检查日志以确保为命令指定的确切时间。 要显示日志文件内容而不执行它们,请使用以下命令:

外壳> mysqlbinlog /var/log/mysql/bin.123456 > /tmp/mysql_restore.sql

然后 /tmp/mysql_restore.sql 使用文本编辑器 打开 文件进行检查。

如果多个语句与要排除的语句同时执行,则 通过指定 mysqlbinlog的 时间来排除特定更改将 无法正常工作。

7.5.2使用事件位置的时间点恢复

mysqlbinlog 的 --start-position 和 --stop-position 选项 可用于指定日志位置 ,而不是指定日期和时间 。 除了指定日志位置编号而不是日期之外,它们的工作方式与启动和停止日期选项相同。 使用位置可以使您更准确地了解要恢复的日志部分,尤其是在许多事务与破坏性SQL语句同时发生的情况下。 要确定位置编号,请 在执行不需要的事务的时间附近 运行 mysqlbinlog 一段时间,但将结果重定向到文本文件以供检查。 这可以这样做:

外壳> mysqlbinlog --start-datetime="2005-04-20 9:55:00" \
         --stop-datetime="2005-04-20 10:05:00" \
         /var/log/mysql/bin.123456 > /tmp/mysql_restore.sql

此命令在 /tmp 目录中 创建一个小文本文件,该 文件包含执行有害SQL语句时的SQL语句。 使用文本编辑器打开此文件,然后查找您不想重复的语句。 确定二进制日志中的位置以停止和恢复恢复并记下它们。 职位标记为 log_pos 后跟数字。 恢复上一个备份文件后,使用位置编号处理二进制日志文件。 例如,您将使用以下命令:

外壳> mysqlbinlog --stop-position=368312 /var/log/mysql/bin.123456 \
         | mysql -u root -p

外壳> mysqlbinlog --start-position=368315 /var/log/mysql/bin.123456 \
         | mysql -u root -p

第一个命令恢复所有事务,直到给出停止位置。 第二个命令恢复从给定的起始位置到二进制日志结束的所有事务。 因为 mysqlbinlog 的输出 包括 SET TIMESTAMP 记录每个SQL语句之前的语句,所以恢复的数据和相关的MySQL日志将反映执行事务的原始时间。

7.6 MyISAM表维护和崩溃恢复

本节讨论如何使用 myisamchk的 检查或修复 MyISAM 表(有表 .MYD 和 .MYI 文件存储数据和索引)。 有关一般的 myisamchk 背景,请参见 第4.6.4节“ myisamchk - MyISAM表维护实用程序” 。 其他表修复信息可以在 第2.11.13节“重建或修复表或索引”中找到 。

您可以使用 myisamchk 检查,修复或优化数据库表。 以下部分介绍了如何执行这些操作以及如何设置表维护计划。 有关使用 myisamchk 获取有关表的信息的信息,请参见 第4.6.4.5节“使用myisamchk获取表信息” 。

尽管使用 myisamchk进行 表修复 非常安全,但 在进行修复或任何可能对表进行大量更改的维护操作 之前 进行 备份总是一个好主意 。

影响索引的 myisamchk 操作可能导致 MyISAM FULLTEXT 使用与MySQL服务器使用的值不兼容的全文参数重建索引。 要避免此问题,请遵循 第4.6.4.1节“myisamchk常规选项”中 的指导原则 。

MyISAM 表维护也可以使用执行类似于 myisamchk 可以 执行的操作的SQL语句 来完成:

有关这些语句的其他信息,请参见 第13.7.3节“表维护语句” 。

这些语句可以直接使用,也可以通过 mysqlcheck 客户端程序使用。 这些语句相对于 myisamchk的 一个优点 是服务器可以完成所有工作。 使用 myisamchk ,您必须确保服务器不会同时使用这些表,以便 myisamchk 和服务器 之间不会发生不必要的交互 。

7.6.1使用myisamchk进行崩溃恢复

本节介绍如何检查和处理MySQL数据库中的数据损坏。 如果您的表经常损坏,您应该尝试找出原因。 请参见 第B.4.3.3节“如果MySQL不断崩溃该怎么办” 。

有关 MyISAM 表 如何 损坏的说明,请参见 第16.2.4节“MyISAM表问题” 。

如果运行 mysqld 并禁用外部锁定(这是默认设置),则 当 mysqld 使用同 一个表时 ,您无法可靠地使用 myisamchk 检查 表。 如果你可以确定在 运行 myisamchk 时 没有人会通过 mysqld 访问表 ,你只需要 在开始检查 表 之前 执行 mysqladmin flush- tables。 如果你不能保证这一点,你必须 在检查表时 停止 mysqld 。 如果你运行 myisamchk 来检查 mysqld的 表 在同时更新时,您可能会收到一个警告,即表格已损坏,即使它没有。

如果在启用外部锁定的情况下运行服务器,则可以随时使用 myisamchk 检查表。 在这种情况下,如果服务器尝试更新 myisamchk 正在使用 的表, 服务器将等待 myisamchk 完成后再继续。

如果使用 myisamchk 来修复或优化表,则 必须 始终确保 mysqld 服务器未使用该表(如果禁用外部锁定,这也适用)。 如果你不停止 mysqld ,你至少应该在 运行 myisamchk 之前 做一个 mysqladmin flush-tables 。 如果服务器和 myisamchk 同时访问表, 您的表 可能会损坏 。

执行崩溃恢复时,请务必了解 数据库 中的每个 MyISAM 表 tbl_name 都对应于下表中显示的数据库目录中的三个文件。

文件 目的
tbl_name.MYD 数据文件
tbl_name.MYI 索引文件

这三种文件类型中的每一种都以各种方式受到损坏,但数据文件和索引文件中最常出现问题。

myisamchk的 工作原理是 .MYD 逐行 创建 数据文件 的副本 。 它通过删除旧 .MYD 文件并将新文件重命名为原始文件名来 结束修复阶段 。 如果您使用 --quick , myisamchk 不会创建临时 .MYD 文件,而是假定 .MYD 文件正确并且只生成新的索引文件而不触及该 .MYD 文件。 这是安全的,因为 myisamchk会 自动检测 .MYD 文件是否损坏,如果是,则中止修复。 您还可以为 myisamchk 指定 --quick 两次选项 。 在这种情况下, myisamchk 不会中止某些错误(例如重复键错误),而是尝试通过修改 .MYD 文件 来解决它们 。 通常, --quick 只有在可用磁盘空间太少而无法执行正常修复时,才 使用两个 选项。 在这种情况下,您应该在运行 myisamchk 之前至少备份表 。

7.6.2如何检查MyISAM表是否存在错误

要检查 MyISAM 表,请使用以下命令:

  • myisamchk的 tbl_name

    这发现99.99%的错误。 它找不到的是 只 涉及 数据文件的 腐败 (非常不寻常)。 如果要检查表,通常应该在 没有选项或使用 (silent)选项的 情况 下运行 myisamchk -s 。

  • myisamchk -m tbl_name

    这发现99.999%的错误。 它首先检查所有索引条目是否有错误,然后读取所有行。 它计算行中所有键值的校验和,并验证校验和是否与索引树中键的校验和匹配。

  • myisamchk -e tbl_name

    这样可以对所有数据进行全面彻底的检查( -e 意味着 “ 延长检查 ” )。 它对每行的每个键进行检查读取,以验证它们确实指向了正确的行。 对于具有许多索引的大型表,这可能需要很长时间。 通常, myisamchk 在找到第一个错误后停止。 如果要获取更多信息,可以添加 -v (详细)选项。 这导致 myisamchk 继续前进,最多20个错误。

  • myisamchk -e -i tbl_name

    这与上一个命令类似,但该 -i 选项告诉 myisamchk 打印其他统计信息。

在大多数情况下,一个简单的 myisamchk 命令没有表名以外的参数就足以检查表。

7.6.3如何修复MyISAM表

本节中的讨论描述了如何 在 表(扩展 和 ) 上 使用 myisamchk 。 MyISAM .MYI .MYD

您还可以使用 CHECK TABLE 和 REPAIR TABLE 语句来检查和修复 MyISAM 表。 请参见 第13.7.3.2节“检查表语法” 和 第13.7.3.5节“修复表语法” 。

损坏的表的症状包括意外中止的查询和可观察到的错误,例如:

  • 找不到文件 tbl_name.MYI (ERRCODE: nnn )

  • 意外的文件结束

  • 记录文件崩溃了

  • nnn 从表处理程序 得到错误

要获取有关错误的更多信息,请运行 perror nnn , nnn 错误号 在哪里 。 以下示例显示如何使用 perror 查找指示表有问题的最常见错误号的含义:

外壳> perror 126 127 132 134 135 136 141 144 145
MySQL错误代码126 =索引文件崩溃
MySQL错误代码127 =记录文件崩溃
MySQL错误代码132 =旧数据库文件
MySQL错误代码134 =记录已被删除(或记录文件崩溃)
MySQL错误代码135 =记录文件中没有更多空间
MySQL错误代码136 =索引文件中没有更多空间
MySQL错误代码141 =写入或更新时复制唯一键或约束
MySQL错误代码144 =表崩溃,上次修复失败
MySQL错误代码145 =表被标记为崩溃,应该修复

请注意,错误135(记录文件中没有空间)和错误136(索引文件中没有空间)不是可以通过简单修复修复的错误。 在这种情况下,您必须使用 ALTER TABLE 增加 MAX_ROWS 和 AVG_ROW_LENGTH 表选项值:

ALTER TABLE tbl_nameMAX_ROWS = xxxAVG_ROW_LENGTH = yyy;

如果您不知道当前表选项值,请使用 SHOW CREATE TABLE 。

对于其他错误,您必须修复表。 myisamchk 通常可以检测并修复发生的大多数问题。

修复过程最多涉及三个阶段,如此处所述。 在开始之前,您应该将位置更改为数据库目录并检查表文件的权限。 在Unix上,确保 mysqld 运行 的用户可以读取它们 (对你而言,因为你需要访问你正在检查的文件)。 如果结果你需要修改文件,它们也必须是你可写的。

本节适用于表检查失败的情况(例如 第7.6.2节“如何检查MyISAM表中的错误”中所述的情况 ),或者您希望使用 myisamchk 提供 的扩展功能 。

用于表维护 的 myisamchk 选项在 第4.6.4节“ myisamchk - MyISAM表维护实用程序”中介绍 。 myisamchk 还有一些变量可以设置为控制可以提高性能的内存分配。 请参见 第4.6.4.6节“myisamchk内存使用” 。

如果要从命令行修复表,则必须先停止 mysqld 服务器。 请注意,当您 在远程服务器上 执行 mysqladmin shutdown 时, mysqld 服务器在 mysqladmin 返回 后仍然可用一段时间 ,直到所有语句处理已停止并且所有索引更改都已刷新到磁盘。

第1阶段:检查你的桌子

如果你有更多的时间,请 运行 myisamchk * .MYI 或 myisamchk -e * .MYI 。 使用 -s (静音)选项可以抑制不必要的信息。

如果 mysqld 服务器停止,你应该使用该 --update-state 选项告诉 myisamchk 将表标记为 “已 检查”。 ”

您必须仅修复 myisamchk 宣布错误的 那些表 。 对于此类表格,请转到第2阶段。

如果在检查时遇到意外错误(例如 out of memory 错误),或者 myisamchk 崩溃,请转到第3阶段。

第2阶段:轻松安全维修

首先,尝试 myisamchk -r -q tbl_name ( -r -q 意思是 “ 快速恢复模式 ” )。 这会尝试修复索引文件而不触及数据文件。 如果数据文件包含它应该包含的所有内容,并且删除链接指向数据文件中的正确位置,则应该可以使用,并且表是固定的。 开始修复下一张桌子。 否则,请使用以下过程:

  1. 在继续之前备份数据文件。

  2. 使用 myisamchk -r tbl_name ( -r 表示 “ 恢复模式 ” )。 这将从数据文件中删除不正确的行和已删除的行,并重建索引文件。

  3. 如果上一步失败,请使用 myisamchk --safe-recover tbl_name 。 安全恢复模式使用旧的恢复方法来处理常规恢复模式不能(但速度较慢)的一些情况。

注意

如果你想有一个修复操作去得更快,你应该设置的值 sort_buffer_size ,并 key_buffer_size 运行时,每一个变量到您的可用内存的大约25% myisamchk的 。

如果修复时出现意外错误(例如 out of memory 错误),或者 myisamchk 崩溃,请转到第3阶段。

第3阶段:难以修复

只有当索引文件中的第一个16KB块被销毁或包含不正确的信息,或者索引文件丢失时,才应该到达此阶段。 在这种情况下,需要创建一个新的索引文件。 这样做如下:

  1. 将数据文件移动到安全的位置。

  2. 使用表描述文件创建新的(空)数据和索引文件:

    外壳> mysql db_name
    
    mysql> SET autocommit=1;
    mysql> 
    mysql>TRUNCATE TABLE tbl_name;quit
    
  3. 将旧数据文件复制回新创建的数据文件。 (不要只将旧文件移回新文件。如果出现问题,您希望保留副本。)

重要

如果您正在使用复制,则应在执行上述过程之前将其停止,因为它涉及文件系统操作,并且MySQL不会记录这些操作。

回到第2阶段 .myisamchk -r -q 应该可以工作。 (这不应该是无限循环。)

您还可以使用 SQL语句,该语句自动执行整个过程。 实用程序和服务器之间也不可能发生不需要的交互,因为服务器在您使用时会完成所有工作 。 请参见 第13.7.3.5节“修复表语法” 。 REPAIR TABLE tbl_name USE_FRM REPAIR TABLE

7.6.4 MyISAM表优化

要合并碎片行并消除因删除或更新行而导致的浪费空间,请 在恢复模式下 运行 myisamchk :

外壳> myisamchk -r tbl_name

您可以使用 OPTIMIZE TABLE SQL语句 以相同的方式优化表 。 OPTIMIZE TABLE 进行表修复和密钥分析,并对索引树进行排序,以便密钥查找更快。 实用程序和服务器之间也不可能发生不需要的交互,因为服务器在您使用时会完成所有工作 OPTIMIZE TABLE 。 请参见 第13.7.3.4节“OPTIMIZE TABLE语法” 。

myisamchk 还有许多其他选项可用于提高表的性能:

  • --analyze 或 -a :执行密钥分发分析。 这可以通过使连接优化器更好地选择连接表的顺序以及应该使用的索引来提高连接性能。

  • --sort-index 或 -S :对索引块进行排序。 这样可以优化搜索并使表扫描更快地使用索引。

  • --sort-records=index_num 或 :根据给定索引对数据行进行排序。 这使您的数据更加本地化,​​并且可以加速 使用此索引 的基于范围 和 操作。 -R index_num SELECT ORDER BY

有关所有可用选项的完整说明,请参见 第4.6.4节“ myisamchk - MyISAM表维护实用程序” 。

7.6.5设置MyISAM表维护计划

最好定期执行表检查,而不是等待问题发生。 检查和修复 MyISAM 表的 一种方法 是使用 CHECK TABLE 和 REPAIR TABLE 语句。 请参见 第13.7.3节“表维护声明” 。

检查表的另一种方法是使用 myisamchk 。 出于维护目的,您可以使用 myisamchk -s 。 的 -s 选项(简称 --silent )导致 myisamchk的 到无声模式运行,印刷消息只有当出现错误。

启用自动 MyISAM 表检查 也是一个好主意 。 例如,只要机器在更新过程中重新启动,您通常需要在进一步使用之前检查可能受影响的每个表。 (这些都是 “ 预计坠毁表 。 ” ),使服务器检查 MyISAM 自动表,与启动 --myisam-recover-options 选项。 请参见 第5.1.7节“服务器命令选项” 。

您还应该在正常系统操作期间定期检查您的表。 例如,您可以运行一个 cron 作业来每周检查一次重要的表,在 crontab 文件中 使用这样的行 :

35 0 * * 0  - /path/to/myisamchkfast --silent /path/to/datadir/*/*.MYI

这将打印出有关崩溃表的信息,以便您可以根据需要检查和修复它们。

首先, 每晚在所有在过去24小时内更新的表上 执行 myisamchk -s 。 如您所见,问题很少发生,您可以将检查频率提前一周左右。

通常,MySQL表几乎不需要维护。 如果要对 MyISAM 具有动态大小的行(带有 VARCHAR , BLOB 或 TEXT 列的表)的 表 执行许多更新, 或者对具有许多已删除行的 表 执行许多更新,则 可能需要不时对表中的空间进行碎片整理/回收。 您可以通过使用 OPTIMIZE TABLE 相关表格 来执行此操作 。 或者,如果您可以暂停 mysqld 服务器一段时间,请将位置更改为数据目录,并在服务器停止时使用此命令:

外壳> myisamchk -r -s --sort-index --myisam_sort_buffer_size=16M */*.MYI

原文