上周上线碰见的ORA-00054错误回放

简介: 上周应用上线,有一个数据库脚本,包含改字段长度等操作,执行过程中,现象就是有些改字段成功了,有些执行出错,报了ORA-00054的错误。了解一下原理,就能对这个错误,有比较深入的理解了。

上周应用上线,有一个数据库脚本,包含改字段长度等操作,执行过程中,现象就是有些改字段成功了,有些执行出错,报了ORA-00054的错误。了解一下原理,就能对这个错误,有比较深入的理解了。


首先,我们模拟下报错过程,创建测试表,session 1执行update语句,但不提交,session 2执行alter table变更name字段长度,此时立即报错ORA-00054,

SQL> create table tbl_lock(id number, name varchar2(10));
Table created.

SQL> select * from tbl_lock;
    ID NAME
---------- ----------
     1 a
     2 b


session 1:

SQL> update tbl_lock set name='c' where id=1;
1 rows updated.


session 2:

SQL> alter table tbl_lock modify name varchar2(5);
alter table tbl_lock modify name varchar2(5)
            *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired


我们看下报错,ORA-00054,提示的就是资源繁忙,因为设置了NOWAIT参数,或者超时,才返回这个错误,


看下此时的锁信息,其中14309是从dba_objects中根据object_name='TBL_LOCK'检索得出的,如下显示,TBL_LOCK表上有一个TM表锁,


表锁,又叫TM锁,当交易执行DML语句的时候,会拥有此锁。目的就是为了阻止此时有其他的进程正在执行DDL,修改表结构,

A table lock, also called a TM lock, is acquired by a transaction when a table is modified by an INSERT, UPDATE, DELETE, MERGE, SELECT with the FORUPDATE clause, or LOCK TABLE statement. DML operations require table locks to reserve DML access to the table on behalf of a transaction and to prevent DDL operations that would conflict with the transaction.


结论

至此,开始的问题,就可以解释清楚了,上线过程中,执行alter table改表的字段长度,但由于有些表,此时碰巧有业务操作,对数据做了DML,交易尚未提交,因此由于TM锁未释放,导致alter table这条DDL语句执行报错,对于alter table执行时尚未有DML未commit操作的表,自然就可以执行成功了。


解决方法

就是等一会再执行,只要出现真空期,没有业务操作,就可以执行成功了,毕竟alter table改字段长度,需要改数据字典信息,对于表结构的变更,何时执行时间,会和表数据量有关,何时则无关,以前写了几篇小文章,不同的场景,有一些不同的结论,可以参考,

一张几亿的分区表,能改名么?

alter table新增字段操作究竟有何影响?(上篇)

alter table新增字段操作究竟有何影响?(下篇)




针对ORA-00054这问题,可以再了解一些。


从11g开始,出现了一个新的参数,


这个参数可以session级别设置,作用就是可以控制一条DDL语句等待一个DML锁释放的时间,默认值是0,表示NOWAIT,最大值是1000000秒,大约11.5天,如果在设置的时间之内,仍未获取DDL锁,则抛出异常错误,错误号就是ORA-00054,

DDL_LOCK_TIMEOUT specifies a time limit for how long DDL statements will wait in a DML lock queue. The default value of zero indicates a status of NOWAIT. The maximum value of 1,000,000 seconds will result in the DDL statement waiting forever to acquire a DML lock.

If a lock is not acquired before the timeout period expires, then an error is returned.


上面的实验中,DDL_LOCK_TIMEOUT默认值是0,因此执行alter table会立即报错,


设置参数值,改为10妙,执行alter table,确实SQL等待了10秒,才返回了ORA-00054错误,

SQL> alter session set ddl_lock_timeout=10;
Session altered.
Elapsed: 00:00:00.00


SQL> alter table tbl_lock modify name varchar2(5);
alter table tbl_lock modify name varchar2(5)
            *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
Elapsed: 00:00:10.00


惜分飞文章(http://www.xifenfei.com/2012/07/oracle-11g%E7%9A%84ddl_lock_timeout%E5%8F%82%E6%95%B0.html)介绍了这个参数的作用,

ddl_lock_timeout可以在一定程度上解决因为我们不清楚这个表是否有dml操作而导致ddl操作不能进行的情况,从一定程度上减少了自己去尝试ddl操作,或者查询相关视图然后找出相关会话,然后kill掉对应数据的情况,可以说是在修改表结构的时候一个很不错的新特性。


11g之前,DDL操作,碰见TM锁,是直接报错,11g则用这参数,通过设置等待时间,可以避免一些DDL语句重复执行,例如开始碰见的问题,如果设置了DDL_LOCK_TIMEOUT,可能等待一会就会执行成功,而不需要我们手工再执行。


但这参数有一个问题,就是对于alter table加字段操作,是不起作用,无论ddl_lock_timeout设置为0还是非0,

SQL> alter table tbl_lock add sex varchar2(1);

会一直处于hang


直到人为中止

c^Calter table tbl_lock add sex varchar2(1)
*
ERROR at line 1:
ORA-01013: user requested cancel of current operation


但是alter table删除字段、drop table删除表操作,可以生效,

SQL> alter table tbl_lock drop column name;
alter table tbl_lock drop column name
            *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired


SQL> drop table tbl_lock;
drop table tbl_lock
           *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired


MOS(Alter Table Add Column Command Hangs With Wait Event 'blocking txn id for DDL' (文档 ID 1553725.1))这篇文章,同样说明了这一个问题,由于11g中,alter table add column操作,没有被DDL排他锁覆盖,因此不受DDL_LOCK_TIMEOUT参数的控制,更不会抛出ORA-00054错误,而是出于hang,

In 11g,  ALTER TABLE ADD COLUMN is not covered by an exclusive ddl lock; therefore, it will not wait for the specified time in DDL_LOCK_TIMEOUT parameter and it will not raise the ORA-00054 error.


《DDL_LOCK_TIMEOUT Behavior in 11G (文档 ID 779569.1)》介绍了这个参数。


11.1.0.6版本,有人开了《Bug 7707888 : DDL_LOCK_TIMEOUT IS NOT WORKING AS EXPECTED》这个bug,此版本中,若有seesion执行DML未提交,此时alter table add column可以执行,但是drop table可以执行。



总结:

1. DDL_LOCK_TIMEOUT是11g新参数,对于一些频繁DML的表,若需要结构变更,可以设置非0,一定程度上,可以避免人为重新执行,自动找出真空期,执行完成DDL语句。

2. alter table加字段操作,不受DDL_LOCK_TIMEOUT控制,需要人为控制。



如果您觉得此篇文章对您有帮助,欢迎关注微信公众号:bisal的个人杂货铺,您的支持是对我最大的鼓励!共同学习,共同进步:)

目录
相关文章
|
6月前
|
SQL 关系型数据库 MySQL
(十八)MySQL排查篇:该如何定位并解决线上突发的Bug与疑难杂症?
前面《MySQL优化篇》、《SQL优化篇》两章中,聊到了关于数据库性能优化的话题,而本文则再来聊一聊关于MySQL线上排查方面的话题。线上排查、性能优化等内容是面试过程中的“常客”,而对于线上遇到的“疑难杂症”,需要通过理性的思维去分析问题、排查问题、定位问题,最后再着手解决问题,同时,如果解决掉所遇到的问题或瓶颈后,也可以在能力范围之内尝试最优解以及适当考虑拓展性。
413 3
|
Oracle 关系型数据库 数据库
Oracle 求一个月内每天 22:00 ~ 第二天早上06:00 之间的数据
Oracle 求一个月内每天 22:00 ~ 第二天早上06:00 之间的数据
|
编解码 监控 Java
对页游《小兵大战》服务器DM内存溢出的排错过程总结
对页游《小兵大战》服务器DM内存溢出的排错过程总结
76 0
|
存储 人工智能 Java
把代码贴进去自动找bug,这个debug神器自动修复仅需几秒,还有GPT-3在线解惑
把代码贴进去自动找bug,这个debug神器自动修复仅需几秒,还有GPT-3在线解惑
197 0
FAQ系列 | SLAVE为什么停滞一直不动了
FAQ系列 | SLAVE为什么停滞一直不动了
|
存储 数据管理 数据挖掘
深夜凌晨女朋友问什么是数据仓库,我的回答让她惊讶,然后发现。。。
深夜凌晨女朋友问什么是数据仓库,我的回答让她惊讶,然后发现。。。
258 0
深夜凌晨女朋友问什么是数据仓库,我的回答让她惊讶,然后发现。。。
|
移动开发 应用服务中间件 nginx
没想到,日志还能这么分析!
这次,将用一个大概几万条记录的 nginx 日志文件作为案例,一起来看看如何分析出「用户信息」。
没想到,日志还能这么分析!
|
达摩院
【非广告】半年时间 90% 的收益就问你慌不慌
先说明这篇文章不包含任何广告内容,也不提供任何投资理财建议,股市有风险,投资需谨慎! 都说牛市来了,今年的 A 股的行情确实很不错,从上面的截图中可以看到阿粉的一只基金已经收益 90% 了。90% 是什么概念,反正阿粉是没有过的,估计很多人都没有经历过这种收益,所以这几天阿粉慌的一批,除了慌的很之外,另一个就是懊悔的很,当初应该多买点的,只能说人性是贪婪的。
【非广告】半年时间 90% 的收益就问你慌不慌
|
Web App开发 JavaScript
中国好声音?给你喜欢的选手疯狂的拉几票吧~(到目前为止,腾讯还未修复此BUG)
先上案例:不到20分钟,“吉克隽逸”的票已经上升了20000多票...(前提你得有一个好的CPU和足够的内存)   打开浏览器,按“F12”键,粘上以下代码回车即可!(首页得打开页面“http://ent.
922 0
|
关系型数据库 MySQL 数据库
顺丰被删库?半个DBA的跑路经验总结
最近顺丰又搞出一个热门:运维误删库事件! 看看有没有什么后路好走啊哥们~ 0. 国内呆不下了,赶紧出国 首先,不要选动车,要选最近的一班飞机,尽快出国,能走高速走高速,不然选人少的路线。
1727 0