1. 数据库故障恢复概述

数据库的可恢复性:

  • DBMS能把数据库从被破坏、不正确的状态、恢复到最近一个正确的状态。

恢复管理任务的种类:

  • 一是在未发生故障而系统正常运行时,采取一些必要措施为恢复工作打基础。

  • 二是在发生故障后进行恢复处理。

转储和建立日志:

  • 周期地(比如一周一次)对整个数据进行复制,转储到另一个磁盘或磁带一类的存储介质上。

  • 建立日志数据库。记录事务的开始、结束标志,记录事务对数据库的每一次插入、删除和修改前后的值,写到日志库中,以便有案可查。

数据库系统基本的共同恢复方法:

  • 优先写日志。

    任何对数据库中数据元素的变更都必须先写入日志;将变更的数据写入磁盘前,日志中的所有相关记录必须写入磁盘。

  • REDO(重做)已提交事务的操作。

    当发生故障而使系统崩溃后,对那些已提交但其结果尚未真写到磁盘上去的事务操作要重做,使数据库恢复到崩溃时所处理状态。

  • UNDO(撤销)未提交事务的操作。

    系统崩溃时,那些未提交事务操作所产生的数据库变更必须恢复到原状,使数据库只反映已提交事务的操作结果。

2. 故障分类

2.1 事务故障

可预期的事务故障:

  • 即在程序中可以预先估计到的错误,可由程序本身解决。

非预期的事务故障:

  • 事务内部更多的故障是非预期的,不能由应用程序处理。

  • 非预期的情况:

    1. 运算溢出;

    1. 并发事务发生死锁而被选中撤销的事务;

    1. 违反某些完整性限制而被终止。

  • 解决方案:

    作事务撤消(UNDO)处理。

2.2 系统故障

系统故障指造成系统停止运转的任何事件,使得系统要重新启动。

系统故障的情况:

  • 硬件错误(CPU故障);

  • 操作系统故障;

  • 系统断电。

系统故障可能导致事务的两种情况:

  • 未完成的事务:

    系统重启后作撤销(UNDO)处理。

  • 已提交的事务,但更新还留在内存缓冲区:

    系统重启后作重作(REDO)处理。

2.3 介质故障

介质故障也称为硬故障,指外存故障,破坏性最大。

介质故障的情况:

  • 磁盘损坏;

  • 磁头碰撞;

  • 瞬时强磁场干扰;

  • 地震、火灾、爆炸等自然灾害造成外存的严重毁坏。

解决方案:

  • 装入最新的数据库后备副本。

  • 装入相应的日志文件副本,重做REDO已完成的事务。

3. 恢复的实现技术

3.1 数据备份

  • 海量转储:每次复制整个数据库。

  • 增量转储:每次只转储上次转储后被更新过的数据。

  • 动态转储:指转储期间允许对数据库进行存取或修改的转储操作。

  • 静态转储:指在系统中无运行事务时进行的转储操作。

3.2 登记日志文件

日志记录类型:

  • 关于事务活动的记录。

    • 事务的唯一标识符。

    • 事务的输入数据。

    • 事务的开始。

    • 事务的提交。但它所作的变更不一定写到磁盘上。

    • 事务的夭折。要保证事务的任何变更不能出现在磁盘上。

    • 事务完全结束。仅有COMMIT或ABORT日志记录是不够的,因为此后还有一些活动必须要完成,如收回事务所占有的工作缓冲区等。

    • 事务在数据对象上进行的操作。如插入、删除、读取、修改操作。

  • 关于数据库变更的记录。

    • 更新前数据的旧值(对于插入操作而言,此项为空值)。

    • 更新后数据的新值(对于删除操作而言,此项为空值)。

登记日志文件:

  • 登记的次序严格按并发事务执行的时间次序。

  • 必须先写日志文件,后写数据库。

4. 恢复策略

4.1 事务故障的恢复

引起事务故障原因:

  • 事务无法执行而中止。

  • 用户主动撤销事务。

  • 因系统调度差错而中止。

事务故障恢复步骤:

  • 从后向前的扫描日志,找到故障事务。

  • 撤消该事务已做的所有更新操作。

  • 从正在运行的事务列表中删除该事务,释放该事务所占资源

4.2 系统故障的恢复

系统故障导致数据不一致状态的原因:

  • 未提交事务对数据库的更新已写入数据库。

  • 已提交事务对数据库的更新还留在内存缓冲区中,没来得及写入数据库

系统故障恢复步骤:

  • 重新启动OS和DBMS。

  • 从前向后扫描日志,将已提交的事务记入重做(REDO)队列。未提交的事务记入撤销(UNDO)队列。

  • 对撤销队列中的各个事务进行撤销回退操作。

  • 对重做队列中的每个事务重新执行日志文件登记的操作。

4.3 介质故障的恢复

介质故障恢复步骤:

  • 重新启动系统。

  • 装入最近的数据库后备副本,使数据库恢复到最近一次转储时的一致性数据库状态。

  • 装入有关的日志副本,重做(REDO)已提交的事务。

  • 介质故障的恢复需要DBA的干预

  • DBA的任务是重装最近转储的数据库后备副本和有关的日志副本,发出系统恢复的命令

  • 具体的恢复操作仍由DBMS来完成。

5. 具有检查点的恢复技术

利用日志技术进行数据库恢复时,恢复子系统必须查阅日志,确定哪些事务需要REDO,哪些事务需要UNDO。

  • 查阅日志从头检查所有日志记录。

利用日志技术进行数据库恢复的缺点:

  • 搜索整个日志将耗费大量时间。

  • 很多需要REDO处理的事务已将更新操作结果写到数据库中,而恢复子系统又重新执行了这些操作,浪费大量时间。

引入检查点机制以解决上述问题。

引入检查点机制数据的恢复过程:

  • 从故障发生前的最后一个检查点处开始正向扫描日志文件;

  • 将提交的事务放入REDO队列,未提交的事务放入UNDO队列;

  • 对队列中每个事务执行REDO或UNDO处理。

6. MySQL的备份与恢复

6.1 数据库的备份与恢复

使用mysqldump命令备份数据:

  • 备份单个数据库或表:

mysqldump -u 用户名 -h 主机名 -p 密码 数据库名 [表名 [表名…]] >备份文件名.sql
  • 备份多个数据库:

mysqldump -u 用户名 -h 主机名 -p 密码 --databases 数据库名 数据库名 … >备份文件名.sql
  • 备份所有数据库:

mysqldump -u 用户名 -h 主机名 -p 密码  --all-databases >备份文件名.sql

使用mysql命令恢复数据:

mysql -u 用户名 -p 数据库名 < 备份文件名.sql

执行mysql命令前,必须在MySQL服务器中创建命令中的数据库。

6.2 表数据的导出与导入

  • FIELDS后的TERMINATED BY '字符':

    设置字段之间的分隔字符,可以为单个或多个字符,默认是制表符'\t'。

  • [OPTIONALLY] ENCLOSED BY '字符':

    设置字段的包围字符,只能为单个字符。如果使用OPTIONALLY选项,只在CHAR和VARCAHR等字符串类型的字段值两边添加字段包围符。

  • ESCAPED BY '字符':

    设置如何写入或读取特殊字符,只能为单个字符,即设置转义字符,默认值为''。

  • STARTING BY '字符串':

    设置每行开头的字符,可以为单个或多个字符,默认情况下不使用任何字符。

  • LINES后的TERMINATED BY '字符串':

    设置每行的结束符,可以为单个或多个字符,默认值是'\n'。

FIELDS和LINES两个子句都是可选的,如果两个都被指定了,则FIELDS就必须位于LINES前面。

由于MySQL默认对导出的目录有权限限制,在使用SELECT …INTO OUTFILE语句进行导出时,导出的文本文件的路径需要指定为MySQL的secure_file_priv参数所指定的位置。

使用LOAD DATA INFILE语句导入表数据:

LOAD  DATA  INFILE  '文本文件'  INTO  TABLE 表名
[FIELDS   [TERMINATED BY '字符']
                   [[OPTIONALLY] ENCLOSED BY '字符']
                  [ESCAPED BY '字符']
]
[LINES    [STARTING BY '字符串']
                 [TERMINATED BY '字符串'] 
 ]
[IGNORE n LINES];
  • FIELDS和LINES选项功能与“SELECT …INTO OUTFILE”语句中选项的功能相同。

  • IGNORE n LINES:忽略文本文件中的前n条记录。

  • 使用“SELECT …INTO OUTFILE”语句将数据从一个数据库表导出到一个文本文件,再使用“LOAD DATA INFILE”语句从文本文件中将数据导入到数据库表时,两个命令的选项参数必须匹配,否则“LOAD DATA INFILE”语句无法解析文本文件的内容。

使用mysqldump命令导出表数据:

mysqldump -u root -p -T "目标路径" 数据库名 表名
[--fields-terminated-by=字符]
[--fields-enclose-by=字符]
[--fields-optionally-enclosed-by=字符]
[--fields-escaped-by=字符]
[--lines-terminated-by=字符串]
  • 只有指定-T参数,才能导出纯文本文件。

  • 导出生成的文件有两个,一个是包含创建表的CREATE TABLE语句的“表名.sql”文件,一个是包含其数据的“表名.txt”文件。

  • 目标路径必须是MySQL的secure_file_priv参数所指定的位置。

  • 各选项功能对应“SELECT …INTO OUTFILE”语句中的各对应项功能。

使用mysqlimport命令导入表数据:

mysqlimport -u root -p 数据库名 "文本文件名.txt"
  [--fields-terminated-by=字符]
  [--fields-enclose-by=字符]
  [--fields-optionally-enclosed-by=字符]
  [--fields-escaped-by=字符]
  [--lines-terminated-by=字符串]
  [--ignore-lines=n]
  • 各选项功能对应“LOAD DATA INFILE”语句中的各对应项功能。

  • --ignore-lines=n:忽略文本文件的前n行。

6.3 使用二进制日志文件恢复数据

错误日志:

  • 记录MySQL服务的启动、运行或停止服务时出现的问题。

查询日志:

  • 记录建立的客户端连接和执行的语句。

二进制日志:

  • 记录所有更改数据的语句,可以用于数据恢复。

慢查询日志:

  • 记录所有执行时间超过long_query_time的所有查询或不使用索引的查询。

查看二进制日志开启状态:

SHOW GLOBAL VARIABLES;

查看二进制日志:

SHOW BINARY LOGS;

使用二进制日志恢复数据库:

mysqlbinlog [option] "日志文件" | mysql -u root -p

  • option选项:

    1. start-datetime:指定恢复数据库的起始时间点。

    1. stop-datetime:指定恢复数据库的结束时间点。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐