基于日志的恢复2024 年 12 月 17 日 | 阅读 10 分钟 - 日志是一系列记录。每个事务的日志都保存在某种稳定存储中,以便在发生任何故障时可以从中恢复。
- 如果在数据库上执行了任何操作,它将被记录在日志中。
- 但日志的存储过程应在实际事务应用于数据库之前完成。
假设有一个事务用于修改学生姓名。将为该事务写入以下日志。 当事务启动时,它会写入“start”日志。 当事务将姓名从“Noida”修改为“Bangalore”时,将向文件写入另一个日志。 当事务完成时,它会写入另一个日志以指示事务的结束。 有两种方法可以修改数据库 1. 延迟数据库修改- 如果事务在提交之前不修改数据库,则会发生延迟修改技术。
- 在此方法中,所有日志都会创建并存储在稳定存储中,并在事务提交时更新数据库。
 基于延迟更新的单用户环境恢复技术 单用户环境下的恢复比多用户同时运行事务的环境要容易得多。要使用延迟更新过程恢复故障前所有已提交和已启动的事务,请执行以下步骤 - 在此,向前搜索日志以查找最近的检查点记录。这是最后一次将事务数据发送到磁盘。在最后检查点之前开始并提交的所有事务无需执行任何操作,因为数据已保存。
- 对于日志中包含 [Start_transaction, T] 记录和 [Commit, T] 记录(出现在最后检查点之后的)的任何事务 T,数据库管理使用日志记录来重做事务并使用事务日志中的新值更新数据库。
- 对于在日志中仅具有 [Start_transaction, T] 记录但自上次检查点以来没有 [Commit, T] 记录的任何事务 T,无需执行任何操作,因为数据库从未被更新过。
为了说明单用户环境中延迟更新的概念,请考虑一个涉及两个事务 T1 和 T2 的示例。事务 T1 将 200 卢比从账户 A 转账到账户 B,事务 T2 从账户 C 提取 100 卢比。账户 A、B 和 C 的初始余额分别为 1000 卢比、1500 卢比和 2000 卢比。假设事务 T1 和 T2 按顺序执行,T1 在 T2 之前。 T1 | T2 |
---|
读取 (A) | 读取 I | A : = A - 200 | C : = C - 100 | 写入 (A) | 写入 I | 读取 (B) | | B := B + 200 | | 写入 (B) | |
下面将讨论这些事务在系统日志中存储的顺序 - 当事务启动时,事务启动记录会被写入系统日志,因此当事务 T1 启动时,启动记录会写入日志。同样,当事务 T2 启动时,启动记录会写入系统日志。
- 当执行写操作时,会写入写日志记录,其中包含所有先前的数据。因此,当事务 T1 执行写 (A) 操作时,会写入写记录。
[Write, T1, A, 800] 被写入系统日志。此时应注意,更新未写入磁盘。同样,当事务 T1 执行写 (B) 操作和事务 T2 执行写 (C) 操作时,会写入相应的写日志记录。 - 当事务提交时,提交记录会被写入系统日志。因此,如果事务 T1 即将提交,则事务提交记录会被写入系统日志。
[Commit, T1] 磁盘和事务的所有日志记录已提交。同样,对于即将提交的事务 T2,事务提交记录会被写入系统日志。 以下是执行顺序为 T1 和 T2 的这两个事务 (T1 和 T2) 执行时系统日志的完整内容 日志 | 数据库 |
---|
[Start_transaction, T1] | | [Write , T1 , A, 800] | | [Write , T1 , B, 1700] | | [Commit, T1] | A = 800 | | B = 1700 | [Start_transaction, T2] | | [Write , T2 , C, 1900] | | [Commit , T2] | | | C = 1900 |
让我们举一个系统在事务完成前崩溃的例子。因此,系统使用日志处理导致信息丢失的故障。发生故障时,会检查日志文件,从最后一个条目开始一直到最近的检查点。应重做所有在中止记录之前的事务开始和事务提交记录。重做方法按照写入日志的顺序将所有写入操作应用于数据库。如果此更新已执行,则在重做时,写操作对数据项没有影响。这确保了所有数据项都将被正确更新。所有仅包含开始记录但没有提交记录的事务都需要重新启动。 下图显示了系统崩溃的不同情况  重做操作在延迟更新中必须是强制性的,这意味着重复运行它与只运行一次相同。如果系统在恢复过程中失败,后续的恢复尝试可能会重做在第一次恢复过程中已经重做的某些写操作,就好像恢复操作从一开始就已重新启动一样。由于重做写值当前已在数据库中,因此第二次成功恢复过程对重做的影响与第一次重做成功时的影响相同。 条件 1 | 条件 2 | 条件 3 |
---|
[Start_transaction, T] | [Start_transaction, T1] | [Start_transaction, T1] | [Write , T1 , A, 800] | [Write , T1 , A, 800] | [Write , T1 , A, 800] | [Write , T1 , B, 1700] | [Write , T1 , B, 1700] | [Write , T1 , B, 1700] | [abort, T1] | [Commit, T1] | [Commit, T1] | | [Start_transaction, T2] | [Start_transaction, T2] | 崩溃 | [Write , T2 , C, 1900] | [Write , T2 , C, 1900] | | [abort, T1] | [Commit , T2] | | | [abort, T1] | | 崩溃 | | | | 崩溃 | 每当恢复过程开始时,都不需要执行重做操作,因为日志中没有出现提交记录,账户 A 和 B 的值保持不变,即分别为 1000 和 1500。 | 每当恢复过程开始时,它会发现事务 T1 已在日志中提交。因此,必须为事务 T1 执行重做操作,并且事务 T1 更新的所有数据项将被复制到数据库。A = 800 且 B = 1700。但事务 T2 尚未在日志中提交,因此无需重做事务 T2。该事务 T2 将从日志中删除并重新执行,因此 C = 2000。 | 每当恢复过程开始时,它会发现日志中都有事务 T1 和 T2 的已提交记录。这将导致对 T1 和 T2 执行重做操作。因此,数据项 A、B 和 C 的值分别为 800 卢比、1700 卢比和 1900 卢比。 | 无需重做 | 重做 (T1) T2 必须重新执行 | 重做 (T1) , 重做 (T1) | A = 1000, B = 1500, C = 2000 | A = 800, B = 1700, C = 2000 | A = 800, B =1700, C = 1900 |
2. 即时数据库修改- 当事务仍处于活动状态时,会发生即时修改技术。
- 在此技术中,数据库在每次操作后立即修改。它遵循实际的数据库修改。
基于即时更新的恢复 在此技术中,当事务发出更新命令时,数据库可以立即更新,而无需等待事务读取其提交点。由于它会跟踪日志并回滚事务的每个写操作的所有数据项,因此即时更新技术也称为向后恢复。 使用写前日志 (WAL) 技术,在将更改记录到数据库之前,更新操作所做的更改已在日志中更新,以便我们在发生故障时可以进行恢复。 即时更新技术分为以下两类 - 撤销/无需重做技术:在此技术中,由于所有更改在事务提交前都已记录在数据库中,因此无需执行重做操作。
- 撤销/重做恢复技术:在此技术中,事务被允许在将所有更改写入数据库之前提交。
基于即时更新的单用户环境下的撤销/重做恢复技术 在此,如果事务在更新数据库中的某些更改后但在到达提交点之前失败,则必须撤销其操作对数据库的影响,即必须回滚事务。此外,如果事务在到达提交点后失败,则有必要从日志中重做已提交事务的操作的效果。 使用即时更新过程恢复故障前所有已提交和活动的事务,请遵循以下恢复步骤 - 在此,向前搜索日志以查找最近的检查点记录。这是最后一次将事务数据发送到磁盘。在最后检查点之前开始并提交的所有事务无需执行任何操作,因为数据已保存。
- 对于任何事务 T,日志中包含自上次检查点以来出现的 [Start_transaction, T] 记录和 [Commit, T] 记录。数据库管理使用日志记录来重做事务并使用事务日志中的新值更新数据库。
- 对于任何事务 T,日志中仅包含 [Start_transaction, T] 记录,但自上次检查点以来没有 [Commit, T] 记录。数据库管理使用日志记录来撤销操作,使用日志中的旧值。要从日志中撤销多个写操作,我们必须按照它们被写入的顺序倒序进行,因为事务可能对单个项目进行了多次更改。
为了说明单用户环境中即时更新的概念,请考虑与延迟更新中讨论的相同示例,该示例涉及两个事务 T1 和 T2。事务 T1 将 200 卢比从账户 A 转账到账户 B,事务 T2 从账户 C 提取 100 卢比。账户 A、B 和 C 的初始余额分别为 1000 卢比、1500 卢比和 2000 卢比。假设事务 T1 和 T2 按 T1 顺序顺序执行,而 T2 以不同的顺序执行,实际输出可能同时出现在日志和数据库中。 日志 | 数据库 | [Start_transaction, T1] | | [Write , T1 , A, 1000, 800] | | | A = 800 | [Write , T1 , B, 1500, 1700] | | | B = 1700 | [Commit, T1] | | [Start_transaction, T2] | | [Write , T2 , C, 2000, 1900] | | | C = 1900 | [Commit , T2] | |
现在我们将检查发生故障时的不同情况。 条件 1 | 条件 2 | 条件 3 | [Start_transaction, T] | [Start_transaction, T1] | [Start_transaction, T1] | [Write , T1 , A, 800] | [Write , T1 , A, 800] | [Write , T1 , A, 800] | [Write , T1 , B, 1700] | [Write , T1 , B, 1700] | [Write , T1 , B, 1700] | [abort, T1] | [Commit, T1] | [Commit, T1] | | [Start_transaction, T2] | [Start_transaction, T2] | 崩溃 | [Write , T2 , C, 1900] | [Write , T2 , C, 1900] | | [abort, T1] | [Commit , T2] | | | [abort, T1] | | 崩溃 | | | | 崩溃 | 每当恢复过程开始时,都应该撤销事务 T1,因为在日志中没有对应的 [Start_transaction, T1] 记录的提交记录。因此,旧值将被复制到数据库。 | 每当恢复过程开始时,事务 T1 必须被重做,事务 T2 必须被撤销,因为 [Start_transaction, T1] 和 [Commit, T1] 记录都存在。因此,事务 T1 所做的更新将被复制到数据库,但事务 T2 尚未在日志记录中提交,因此必须撤销它。因此,事务 T2 所做的更新必须被撤销。 | 每当恢复过程开始时,事务 T1 和 T2 都应该被重做,因为它们在日志中都有 [Start_transaction, T1] 和提交记录。因此,它们所做的更新应该被记录到数据库中。 | 撤销 (T1) | 重做 (T1) 撤销 (T2) | 重做 (T1) , 重做 (T2) | A = 1000, B = 1500, C = 2000 | A = 800, B = 1700, C = 2000 | A = 800, B =1700, C = 1900 |
基于多用户环境即时更新的撤销/重做恢复技术 在此,在事务提交前立即对数据库进行更新,因此当严格 2PL 中发生死锁时,必须中止该事务,并且必须回滚该事务操作所做的任何更改。 多用户环境中即时更新恢复的恢复步骤与单用户环境中的步骤相同。为了解释多用户环境中即时更新的概念 根据多用户环境中即时更新恢复的算法。 - 在此,无需撤销或重做事务 T1 的写操作,因为它在最后检查点之前已经提交。
- 事务 T2 和 T3 的写操作必须被重做,因为这两个事务在系统崩溃(即故障)之前,在最后检查点之后都达到了提交点。
- 事务 T4 的写操作应该被撤销,因为提交记录没有写入日志。
使用日志记录进行恢复当系统崩溃时,系统会查阅日志以确定哪些事务需要撤销,哪些需要重做。 - 如果日志包含记录 <Ti, Start> 和 <Ti, Commit> 或 <Ti, Commit>,则事务 Ti 需要被重做。
- 如果日志包含记录<Tn, Start> 但不包含 <Ti, commit> 或 <Ti, abort> 记录,则事务 Ti 需要被撤销。
|