UNDO相关问题总结(三)

过完5.1假期回来后,发现关于undo相关问题中还有一个常见问题没有涉及和总结,那就是enq: US – contention,本次主题简单描述一下enq: US – contention这类问题

问题描述
This event indicates the session is currently waiting on the Undo Segments ,即该等待表示会话进行的事务(transaction)正在队列中等待UNDO segment。

常见原因
1.undo 空间不足,事务申请undo空间保存前映像数据时,undo表空间中暂无空间可分配,因此该session进入等待队列中
2.活动session过多,事务申请undo空间保存前映像数据时,分配undo空间的lock已经全部被占用,此时该session进入等待队列中。这种情况下,检查online undo segments 非常多,同时可能会出现一个undo 段被多个事务共同使用

解决方法(仅供参考)
1.确认问题的具体原因,查询undo表空间使用情况,判断是否因为undo空间不足导致该类问题。
2.如果确认是由于undo空间不足引起,紧急添加数据文件到undo表空间,暂缓问题,然后继续下一步分析根本原因。
3.继续查询系统中每个session的undo使用量(v$session ,v$transaction),同时查询系统中是否有事务正在回滚(v$fast_start_transactions or v$fast_start_servers),或者存在死事务回滚(x$ktuxe)
4.确认具体的进程后,可以根据我上一篇博客(“UNDO 相关问题总结(二)”中”加快事务回滚的解决方法(仅供参考)“部分)描述的方法进行解决,最后向应用、开发、维护人员培训此类问题,避免再次发生。
5.判断是否是因为活动session过多引起enq: US – contention等待,这类判断可能需要从多方面入手,判断方法如下(仅供参考)
  • 活动session过多引起的enq: US – contention等待,一般是受害者,是由于其它问题的裙带效应而导致(例如,一个并发量较高的SQL突然执行效率下降,此时会导致整个事务执行时间边长,进一步会导致整个数据库活动事务(session)增多,从而可能引起enq: US – contention等待
  • enq: US – contention等待不会消耗CPU、IO资源,但是这时,我们一般可以看到数据库服务器上CPU资源或者IO资源紧张
  • 查看数据库的等待情况,一般可以看到大量其它等待,例如row cache、latch、scattered read、RAC类等待等等....
6.如果判断为活动session过多引起enq: US – contention等待,根据上一步,我们知道解决这类问题,需要解决问题的源头(瓶颈点),由于源头问题的现象多样,需要具体问题具体分析了,暂不在这次主题的讨论范围之内。
注意:如果此时问题现象已经消失,对于第6步中问题源头的分析,可以抽取enq: US – contention等待开始出现的前几分钟AWR和ASH两个报告进行分析(因为首先有源头,才会导致后续enq: US – contention等待)

查询语句(仅供参考)
1.undo表空间使用情况查询语句:
select b.tablespace_name,
       nvl(used_undo,0) "USED_UNDO(M)",
       total_undo "Total_undo(M)",
       trunc(nvl(used_undo,0) / total_undo * 100, 2) || '%' used_PCT
  from (select nvl(sum(bytes / 1024 / 1024), 0) used_undo, tablespace_name
          from dba_undo_extents
         where status in ( 'ACTIVE','UNEXPIRED')
         group by tablespace_name) a,
       (select tablespace_name, sum(bytes / 1024 / 1024) total_undo
          from dba_data_files
         where tablespace_name in
               (select value
                  from v$spparameter
                 where name = 'undo_tablespace'
                   and (sid = (select instance_name from v$instance) or
                       sid = '*'))
         group by tablespace_name) b
 where a.tablespace_name (+)= b.tablespace_name
/
2.session使用的undo量查询语句:
SELECT r.name rbs,
       nvl(s.username, 'None') oracle_user,
       s.osuser client_user,
       p.username unix_user,
       s.sid,
       s.serial#,
       p.spid unix_pid,s.MACHINE,s.PROGRAM,s.MODULE,
       t.used_ublk * TO_NUMBER(x.value) / 1024 / 1024 as undo_mb ,
       TO_CHAR(s.logon_time, 'mm/dd/yy hh24:mi:ss') as login_time,
       TO_CHAR(sysdate - (s.last_call_et) / 86400, 'mm/dd/yy hh24:mi:ss') as last_txn,
       t.START_TIME transaction_starttime
 FROM v$process      p,
       v$rollname    r,
       v$session     s,
       v$transaction t,
       v$parameter x   
 WHERE s.taddr = t.addr   
   AND s.paddr = p.addr   
   AND r.usn = t.xidusn(+)   
   AND x.name = 'db_block_size'   
 ORDER by undo_mb desc
/
3.回滚的事务和回滚进度语句查询:
语句1.
  alter session set NLS_DATE_FORMAT='DD-MON-YYYY HH24:MI:SS'; 
  select usn, state, undoblockstotal "Total", undoblocksdone "Done", undoblockstotal-undoblocksdone "ToDo",
         decode(cputime,0,'unknown',sysdate+(((undoblockstotal-undoblocksdone) / (undoblocksdone / cputime)) / 86400)) "Estimated time to complete" 
  from v$fast_start_transactions; 
语句2.
select ktuxeusn, to_char(sysdate,'DD-MON-YYYY HH24:MI:SS') "Time", ktuxesiz, ktuxesta 
   from x$ktuxe 
   where ktuxecfl = 'DEAD'; 


MOS文档

How to correct performance issues with enq: US - contention related to undo segments [ID 1332738.1]

Purpose

Assist in correcting performance issues related to "enq: US Contention" on undo segments.
You have many offline undo segments and the workload starts to online many undo segments over a short period of time. This can lead to high 'latch: row cache objects' contention may be seen on dc_rollback_segments together with high 'enq: US - contention' waits when using system managed undo with an auto tuned undo retention period.
Sessions attempting to online undo segments should show ktusmous_online_undoseg() in their call stack.
Another aspect of the problem can be due to long running queries which can raise tuned_undoretention to very high values and exhausts the undo tablespace resulting in ORA-1628.
A real world case: 
A query is being executed and some rows are fetched from the cursor and then the user stops working on that query (e.g. does not press the "next" button on the application screen) and works on something else (e.g. in a different window). After some time the user continues working on the query ... auto-tune starts tracking the query from this point and the maxquerylen is quite large now, hence also the tuned_undoretention (that depends directly on the maxquerylen).
NOTE: The Seibel application can allow for this problem to happen.

Last Review Date

June 24, 2011

Instructions for the Reader

A Troubleshooting Guide is provided to assist in debugging a specific issue. When possible, diagnostic tools are included in the document to assist in troubleshooting.

Troubleshooting Details

The wait event "enq: US Contention" is associated with contention on the latch in the row cache (dc_rollback_seg). Enqueue US - Contention can become a bottle-neck for performance if workload dictates that a lot of offlined undo segments must be onlined over a short period of time. The latch on the row cache can be unable to keep up with the workload.
This can happen for a number of reasons and some scenarios are legitimate workload demands.
Solution:
Ensure that peaks in onlined undo segments do not happen (see workaround #2). That is not always feasible.
Workarounds:
1. Bounce the instance.
2. Setting _rollback_segment_count to a high number to keep undo segments online.
alter system set "_rollback_segment_count"=;
3. Set _undo_autotune to false
alter system set "_undo_autotune" = false;
NOTE: Simply using _smu_debug_mode=33554432 may not be enough to stop the problem, but valid fix for bug 5387030.
4. A fix to bug 7291739 is to set a new hidden parameter, _highthreshold_undoretention to set a high threshold for undo retention completely distinct from maxquerylen.
alter system set "_highthreshold_undoretention"=;
If problems persist, please file a Service Request with Oracle Support.
@ Diagnosis

@
 Should the workarounds and/or configuration changes not help to alleviate the problems,
@ development would need the following diagnostics data:

@
 a. Provide alert.log which shows the last instance startup parameters through the time of the 
@ latest isssues. 

@
 b. AWR and/or ASH report of 30 or 60 minutes interval.

@
 b. Following query output:

@
 alter session set nls_date_format='mm/dd/yy hh24:mi:ss';
@ select begin_time, MAXQUERYID, MAXQUERYLEN from v$undostat;

@
 c. While the error is ongoing:

@
 On single instance:

@
 sqlplus / as sysdba
@ oradebug setmypid
@ oradebug unlimit
@ oradebug hanganalyze 3
@ oradebug dump systemstate 266

@
 wait for 5 seconds

@
 oradebug dump systemstate 266

@
 wait for 2 minutes 

@
 sqlplus / as sysdba
@ oradebug setmypid
@ oradebug unlimit
@ oradebug hanganalyze 3
@ oradebug dump systemstate 266

@
 wait for 5 seconds

@
 oradebug dump systemstate 266

@
 On RAC get tracing on all nodes

@
 sqlplus / as sysdba
@ oradebug setmypid
@ oradebug unlimit
@ oradebug -g all hanganalyze 3
@ oradebug -g all dump systemstate 266

@
 wait for 5 seconds

@
 oradebug -g all dump systemstate 266

@
 wait for 2 minutes 

@
 sqlplus / as sysdba
@ oradebug setmypid
@ oradebug unlimit
@ oradebug -g all hanganalyze 3
@ oradebug -g all dump systemstate 266

@
 wait for 5 seconds

@
 oradebug -g all dump systemstate 266


<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、付费专栏及课程。

余额充值