UNDO相关问题总结(四)

这次主题继续介绍undo相关的内容,主要讲述undo数据文件丢失的处理示例(1),这次示例的处理方法简单,下一篇介绍一个更加复杂的处理示例。
模拟环境
os: linux x86-64
db: oracle 11gr2
mode: archivelog

模拟过程
1、用户发起事务(insert),未提交
2、shutdown abort 数据库
3、模拟undo数据文件丢失
4、数据库mount状态下offline drop掉undo数据文件
5、alter database open 数据库
6、完成后续处理

预备知识
"_offline_rollback_segments"/"_corrupted_rollback_segments"两个参数的解释:
if the rollback segments corrupt,we should recover it from bacup.sometimes there's no backup or it's not necessary to recover,we maybe consider using undocument parameter to avoid access these rollback segments,Oracle provides "_offline_rollback_segments" and "_corrupt_rollback_segments",before use them,we should be clear the difference between them.when opening a database,any rollback segments listed in "_offline_rollback_segments" or "_corrupted_rollback_segments" parameter:
  • are not scanned,and any active transactions are neither marked as dead nor rolled back;
  • appear offline in undo$
  • can't be acquered by instance for new transaction;
  • note that although the rollback segments listed in "_offline_rollback_segments",oracle actually reads the segemnts to find transaction status and gather undo records to perform rollback,if a corrupt block is found,the oracle will still fail.if an open ITL is found to associated with "_corrupted_rollback_segments",the segment is not read to find the transaction status
  • it is as though the rollback segment had been dropped,the transaction is assumed to be commited and delayed block cleanout is performed;
  • so the transaction was not commited,logical corruption will occur

以下描述转载于askmaclean博客:

_OFFLINE_ROLLBACK_SEGMENTS(offline undo segment list)隐藏参数(hidden parameter)的独有作用:

  • 在实例startup启动并open database的阶段仍将读取_OFFLINE_ROLLBACK_SEGMENTS所列出的Undo segments(撤销段/回滚段),若访问这些undo segments出现了问题则将在alert.log和其他TRACE中体现出来,但不影响实际的startup进程
    • 若查询数据块发现活跃的事务,并ITL指向对应的undo segments则:
    • 若读取undo segments的transaction table事务表发现事务已提交则做数据块的清除
    • 若读取发现事务仍活动未commit,则生成一个CR块拷贝
    • 若读取该undo segments存在问题(可能是corrupted讹误,可能是missed丢失)则产生一个错误并写出到alert.log,查询将异常终止
  • 若DML更新相关的数据块会导致服务进程为了恢复活跃事务而进入死循环消耗大量CPU,解决方法是通过可以进行的查询工作重建相关表 

_CORRUPTED_ROLLBACK_SEGMENTS(corrupted undo segment list)隐藏参数所独有的功能:

  • 在实例启动startup并open database的阶段_CORRUPTED_ROLLBACK_SEGMENTS所列出的undo segments(撤销段/回滚段)将不会被访问读取
  • 所有指向这些被_CORRUPTED_ROLLBACK_SEGMENTS列出的undo segments的事务都被认为已经提交了commit,和这个undo segments已经被drop时类似
    • 这将导致严重的逻辑讹误(数据不一致)
    • 如果数据字典上有活跃事务那么将更糟糕,数据字典逻辑讹误会造成数据库管理问题
    • 如果bootstrap自举核心对象有活跃事务,那么将无法忽略错误ORA-00704: bootstrap process failure错误,导致无法强制打开数据库
  • 衷心地建议用_CORRUPTED_ROLLBACK_SEGMENTS这个参数打开数据库后导出数据并重建数据库,这个参数使用的后遗症可能很顽固
  • Oracle公司内部有叫做TXChecker的工具可以检查问题事务 
示例

(1)模拟undo数据文件丢失
[oracle@netdbhost dbs]$ sqlplus dbmon/dbmon_123
SQL*Plus: Release 11.2.0.1.0 Production on Mon May 5 10:23:55 2014
Copyright (c19822009, Oracle.  All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> create table test as select * from dba_objects;
Table created.
SQL> select count(*from test;
  COUNT(*)
----------
     71896
SQL> insert into test select * from test;
71896 rows created.
SQL> alter system flush buffer_cache;
System altered.
SQL> quit
SQL> shutdown abort;
ORACLE instance shut down.
SQL> host mv /u01/test/test/undotbs1.dbf /u01/test/test/undotbs1.dbfbak


(2)启动数据库报错,提示undo文件不存在
SQL> startup
ORACLE instance started.
Total System Global Area 1369579520 bytes
Fixed Size                  2213216 bytes
Variable Size             905972384 bytes
Database Buffers          452984832 bytes
Redo Buffers                8409088 bytes
Database mounted.
ORA-01157: cannot identify/lock data file 3 - see DBWR trace file
ORA-01110data file 3'/u01/test/test/undotbs01.dbf'

(3)查询undo文件的文件名,并offline drop 掉(这种方式处理后,数据库可以open成功!!)
SQL> select name from v$datafile where file#=3;
NAME
--------------------------------------------------------------------------------
/u01/test/test/undotbs01.dbf
SQL> alter database datafile '/u01/test/test/undotbs01.dbf' offline drop;    ----直接offline drop
Database altered.

(4)open数据库,这时数据库可以open成功!查看数据库内undo段的状态
SQL> alter database open;                      ---这种情况下,数据库可以open成功!
Database altered.
SQL> select status,count(*from dba_rollback_segs group by status;
STATUS             COUNT(*)
---------------- ----------
NEEDS RECOVERY           10
ONLINE                    1
SQL> select usn,status from v$rollstat;
       USN STATUS
---------- ---------------
         0 ONLINE
SQL> col segment_name format a30
SQL> set linesize 200
SQL> select segment_name,status from dba_rollback_segs where status='NEEDS RECOVERY';
SEGMENT_NAME                   STATUS
------------------------------ ----------------
_SYSSMU1_3780397527$           NEEDS RECOVERY
_SYSSMU2_2232571081$           NEEDS RECOVERY
_SYSSMU3_2097677531$           NEEDS RECOVERY
_SYSSMU4_1152005954$           NEEDS RECOVERY
_SYSSMU5_1527469038$           NEEDS RECOVERY
_SYSSMU6_2443381498$           NEEDS RECOVERY
_SYSSMU7_3286610060$           NEEDS RECOVERY
_SYSSMU8_2012382730$           NEEDS RECOVERY
_SYSSMU9_1424341975$           NEEDS RECOVERY
_SYSSMU10_3550978943$          NEEDS RECOVERY
10 rows selected.

(5)重建新的undo表空间(这一步也可以延后执行,影响不大)
SQL> create undo tablespace undo2 datafile '/u01/test/test/undo2.dbf' size 50m;
Tablespace created.
SQL> select tablespace_name from dba_tablespaces;
TABLESPACE_NAME
------------------------------
SYSTEM
SYSAUX
UNDOTBS1
TEMP
USERS
UNDO2
6 rows selected.
SQL> show parameter undo       
NAME                                 TYPE                             VALUE
------------------------------------ -------------------------------- ------------------------------
_undo_autotune                       boolean                          FALSE
undo_management                      string                           AUTO
undo_retention                       integer                          1800
undo_tablespace                      string                           UNDOTBS1
SQL> alter system set undo_tablespace='undo2';
System altered.
SQL> alter system set undo_management=manual  scope=spfile;   ---调整为手工管理,执行后续的扫尾工作(drop rollbacksegment 的执行)
System altered.

(6)重新启动数据库,通过pfile来启动,同时将丢失undo文件中的undo段都通过隐含参数(_offline_rollback_segments)屏蔽掉,告知oracle这写回滚段已经丢次,如果数据库内有数据块需要用到这些回滚段,则默认数据块内的数据已经提交
SQL> create pfile='/home/oracle/dhtest.ora' from spfile;
File created.
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
*.undo_management=manual
*._offline_rollback_segments=('_SYSSMU1_3780397527$','_SYSSMU2_2232571081$','_SYSSMU3_2097677531$','_SYSSMU4_1152005954$','_SYSSMU5_1527469038$','_SYSSMU6_2443381498$','_SYSSMU7_3286610060$','_SYSSMU8_2012382730$','_SYSSMU9_1424341975$','_SYSSMU10_3550978943$')
SQL> startup pfile=/home/oracle/dhtest.ora
ORACLE instance started.
Total System Global Area 1369579520 bytes
Fixed Size                  2213216 bytes
Variable Size             905972384 bytes
Database Buffers          452984832 bytes
Redo Buffers                8409088 bytes
Database mounted.
Database opened.
SQL> select count(*from dh.test;             ---检查数据发现,为提交的数据默认为提交了。                                
  COUNT(*)
----------
    143792
SQL> select status,count(*from dba_rollback_segs group by status;
STATUS             COUNT(*)
---------------- ----------
NEEDS RECOVERY           10
OFFLINE                  10
ONLINE                    1

(7)手工删除丢失undo数据文件中的undo段
SQL> drop rollback segment  "_SYSSMU1_3780397527$";
drop rollback segment  "_SYSSMU2_2232571081$";
drop rollback segment  "_SYSSMU3_2097677531$";
drop rollback segment  "_SYSSMU4_1152005954$";
drop rollback segment  "_SYSSMU5_1527469038$";
drop rollback segment  "_SYSSMU6_2443381498$";
drop rollback segment  "_SYSSMU7_3286610060$";
drop rollback segment  "_SYSSMU8_2012382730$";
drop rollback segment  "_SYSSMU9_1424341975$";
drop rollback segment  "_SYSSMU10_3550978943$";
Rollback segment dropped.
SQL> 
Rollback segment dropped.
SQL> 
Rollback segment dropped.
SQL> 
Rollback segment dropped.
SQL> 
Rollback segment dropped.
SQL> 
Rollback segment dropped.
SQL> 
Rollback segment dropped.
SQL> 
Rollback segment dropped.
SQL> 
Rollback segment dropped.
SQL> 
Rollback segment dropped.
SQL> 
SQL> select status,count(*from dba_rollback_segs group by status;
STATUS             COUNT(*)
---------------- ----------
OFFLINE                  10
ONLINE                    1

(8)删除原先的undo表空间,重新启动,将undo_management改回自动,同时去掉隐含参数,至此数据库恢复完毕
SQL> drop tablespace undotbs1 including contents and datafiles;
Tablespace dropped.
SQL> 
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 1369579520 bytes
Fixed Size                  2213216 bytes
Variable Size             905972384 bytes
Database Buffers          452984832 bytes
Redo Buffers                8409088 bytes
Database mounted.
Database opened.
SQL> 
SQL> show parameter undo
NAME                                 TYPE                             VALUE
------------------------------------ -------------------------------- ------------------------------
_undo_autotune                       boolean                          FALSE
undo_management                      string                           MANUAL
undo_retention                       integer                          1800
undo_tablespace                      string                           undo2
SQL> alter system set undo_management=auto scope=spfile;
System altered.
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 1369579520 bytes
Fixed Size                  2213216 bytes
Variable Size             905972384 bytes
Database Buffers          452984832 bytes
Redo Buffers                8409088 bytes
Database mounted.
Database opened.
<think>好的,我现在需要详细回答用户关于MySQL中redo log和undo log的区别与作用的问题。用户已经提供了一些站内引用,我需要结合这些引用以及之前回答中的内容来构建一个全面且准确的解释。 首先,我需要明确redo log和undo log的基本概念,然后分析它们的不同点,包括功能、存储位置、生命周期、日志类型、恢复方向以及关联事务等方面。同时,用户提到的引用中有关于两阶段提交和日志结构的内容,这些也需要整合到回答中,确保覆盖关键点。 接下来,我应该检查之前的回答是否已经涉及了这些日志类型。在之前的回答中,用户主要关注错误日志、二进制日志、慢查询日志和通用查询日志,而redo log和undo log属于事务日志,需要在此次回答中详细展开。 需要确保回答结构清晰,分点说明,使用用户要求的格式,如行内数学表达式用$...$,独立公式用$$...$$,并且正确引用提供的参考资料。同时,生成相关问题,帮助用户进一步理解。 另外,要注意引用标记的正确使用,例如引用[^1]、[^2]等,这些需要与用户提供的引用对应起来。例如,用户提供的引用[1]提到redo log和binlog的区别,引用[4]涉及两阶段提交和恢复机制,这些都需要在适当的位置引用。 最后,总结redo log和undo log的区别与作用,确保内容准确,语言简洁,符合用户要求的中文回答,并生成相关问题供用户参考。</think>### MySQL中redo log与undo log的对比解析 --- #### 一、核心概念与作用对比 1. **redo log(重做日志)** - **功能定位**:InnoDB存储引擎层日志,确保事务的**持久性**(Durability) - **核心作用**: - 记录物理层面的数据页修改(例如:$page\_no=5$的页中偏移量$offset=128$处更新为值$0x1A3F$)[^1][^4] - 用于崩溃恢复时**重放未写入数据文件的修改** - **写入机制**: - 采用**循环写入**模式(固定大小文件组) - 通过`innodb_flush_log_at_trx_commit`参数控制刷盘策略[^4] 2. **undo log(回滚日志)** - **功能定位**:实现事务的**原子性**(Atomicity)与多版本并发控制(MVCC) - **核心作用**: - 记录事务修改前的数据镜像,支持事务回滚(`ROLLBACK`) - 为读操作提供一致性视图(通过`Read View`访问历史版本数据)[^2] - **存储形式**: - 以**逻辑日志**形式记录反向操作(例如:INSERT对应DELETE,UPDATE记录旧值) - 存储在特殊的undo表空间中(MySQL 8.0默认使用独立UNDO表空间) --- #### 二、关键差异分析 | **对比维度** | **redo log** | **undo log** | |--------------------|---------------------------------------|---------------------------------------| | **所属层级** | InnoDB存储引擎层实现[^4] | InnoDB存储引擎层实现[^4] | | **日志类型** | 物理日志(记录数据页修改) | 逻辑日志(记录反向操作语句) | | **主要目的** | 崩溃恢复时保证数据持久性 | 事务回滚与MVCC支持 | | **生命周期** | 事务提交后仍可能保留(用于恢复) | 事务提交后随版本链清理逐渐删除 | | **写入触发条件** | 数据修改发生时立即记录 | 事务开启后首次数据修改时生成 | | **可见性** | 仅InnoDB内部使用 | 通过`SELECT ... FOR UPDATE`可间接访问| | **与事务的关系** | 所有事务共享日志缓冲区 | 每个事务拥有独立的undo链 | --- #### 三、协作流程示例(以UPDATE为例) 1. **事务启动**:生成事务ID(trx_id)并分配undo log段 2. **修改数据前**: - 将原始数据拷贝到undo log(构建回滚段) - 生成`UNDO LOG RECORD`记录旧值[^4] 3. **执行数据修改**: - 在内存中更新数据页,生成`redo log record`写入log buffer - 若开启binlog,同时写入binlog cache(两阶段提交)[^4] 4. **事务提交**: - 将redo log buffer刷盘(`prepare`阶段) - binlog刷盘后,redo log标记为`commit`状态[^4] 5. **崩溃恢复**: - 检查binlog完整性,通过redo log重做未落盘的数据页修改 - 使用undo log回滚未提交的事务修改 --- #### 、高级特性关联 1. **两阶段提交(2PC)** redo log与binlog通过两阶段提交保证跨存储引擎的事务一致性[^4]: ```mermaid graph LR A(事务提交) --> B(redo log prepare) B --> C(binlog写入) C --> D(redo log commit) ``` 2. **MVCC实现基础** 通过undo log构建版本链实现非锁定读: $$ \text{Read View} = [trx\_id_{min}, trx\_id_{max}, active\_trx\_list] $$ 根据事务ID选择可见的undo log版本 --- #### 五、配置与管理要点 1. **redo log优化** - 设置合理的日志文件大小(`innodb_log_file_size`,建议4GB以上) - 调整刷盘策略(`innodb_flush_log_at_trx_commit=1`确保ACID) ```ini [mysqld] innodb_log_files_in_group=3 # 日志文件数量 innodb_log_file_size=4G # 单个文件大小 ``` 2. **undo log管理** - 控制undo表空间数量(MySQL 8.0+) - 设置自动清理阈值(`innodb_undo_log_truncate=ON`) ```sql ALTER UNDO TABLESPACE innodb_undo_001 SET INACTIVE; # 手动触发清理 ``` --- ### 相关问题 1. 如何通过redo log实现崩溃恢复的具体流程? 2. undo log在MVCC中如何支持一致性读? 3. 两阶段提交如何避免binlog与redo log数据不一致? 4. 什么情况下需要调整redo log文件的大小?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值