警惕Oracle数据库操作高压线
背景:在日常的数据库技术支持工作中,会发现相当部分的数据库事故和人为操作不当有直接的关系。每次的新员工培训,也会用真实案例来说明和强调正确操作习惯的重要性。在强调职业化,推行可服务性的大环境下,了解数据库操作的高压线,掌握维护规则绕开雷区,就显得格外刻不容缓。为此我特别总结过去一两年中的突出数据库案例,罗列出常见的违规操作,希望借此能够尽可能的减少人为事故,从而提高用户对职业化服务的满意度。哲人说,不要被同一块石头绊倒两次,那么希望通过这篇文章能够避免同样人为事故的再次发生。
内容:
高压线一:不要随意删除/opt/oracle目录下的任何文件。
咋看这个标题,看官们第一反应可能是我怎么会去删除数据库文件呢?实际上最近三个月,产品线已经发生过几次数据库日志文件部分或者全部被删,导致数据库宕机的严重事故。究其表面原因,是小局点数据库文件建立在本地磁盘,日志文件的后缀又是.log,因此被维护工程师当成无用的垃圾日志删除。深究其实质原因,是维护工程师对数据库缺乏基本常识,不了解什么是数据库文件,从而碰了数据库操作的高压线。我们先来了解这个案例的来龙去脉。
典型案例: 某地系统数据库意外删除所有log file文件
办事处工程师到现场解决性能问题,发现Rootvg快满了,决定清除日志文件。工程师使用find –name *log,尽管800工程师在支持电话中警告不能删除数据库文件,现场工程师还是删除了数据库的所有在线重做日志文件(文件后缀为.log)。
数据库在删除文件数分钟后宕机,重新启动数据库报错:
ORA-313 signalled during: alter database open...
Sat Apr 2 02:20:49 2005
Errors in file /usr/oracle/admin/ora7/udump/ora_27520.trc:
ORA-00603: ORACLE server session terminated by fatal error
ORA-00449: background process "LGWR" unexpectedly terminated with error 313
ORA-00313: open failed for members of log group of thread
ORA-01092: ORACLE instance terminated. Disconnection forced
问题处理过程:
删除了数据库的所有在线重做日志文件是很严重的事故,而且现场没有任何数据库备份,如果不能恢复后果不堪设想。在经历10个小时的紧急恢复后,数据库终于正常运行。
总结:
本案例中的数据库历经紧急恢复得以正常运行,而另一个地方就没有这么幸运,最终是重建库然后导入历史数据。最近已有数起删除日志文件导致的人为事故,尤以举例的事故最为严重,删除了所有的日志文件,希望工程师尤其是新员工引以为戒。
删除数据库文件是非常严重的人为事故,数据库文件的缺失将直接导致数据库宕机和数据的丢失。那么如何避免删除数据库文件呢?我们需要了解数据库的组织结构,以Oracle来举例,每一个ORACLE数据库是由三种类型的文件组成:数据文件、日志文件、控制文件,缺一不可。另外参数文件、密码文件、归档日志文件也是重要的数据库文件。如果不使用裸设备,这些文件通常存放在oracle用户软件目录/opt/oracle中。如果不清楚文件的作用和来源,就不要随意动/opt/oracle目录下的任何文件。
高压线二:不能移除表空间的任何数据文件
一个常见的错误频繁出现在新员工中——直接删除表空间的物理数据文件,这个错误多半发生在测试环境或者是新开局。通常的情况是,工程师发现表空间的数据文件建错路径或者无用文件,就手工删除数据文件,导致数据库宕机或者无法启动。
典型案例:用rm命令物理删除表空间的数据文件
某地工程师为表空间增加数据文件,后发现文件路径给错,直接用rm命令物理删除了此文件。10分钟后数据库dbw0后台进程写文件失败,数据库宕机。尝试重新启动数据库失败,错误为:
ORA-01110: data file 446: "/ICTdata10/oradata/ICT/data/ict_restored_data081.dbf"
ORA-01115: IO error reading block from file 446 (block # 1)
ORA-27063: skgfospo: number of bytes read/written is incorrect
SVR4 Error: 6: No such device or address
问题处理过程:
1. 使用下述命令脱机删除已经丢失的数据文件:
ALTER DATABASE DATAFILE "/ICTdata10/oradata/ICT/data/ict_restored_data080.dbf" OFFLINE DROP;
2. 启动数据库:alter database open;
3. 删除或者重建表空间
总结:
Oracle的原则是一旦一个数据文件被加入到表空间中,那么除非这个表空间被删除,否则不能够将任何数据文件从表空间移除。ALTER DATABASE DATAFILE OFFLINE DROP命令并不是允许移除数据文件,它只是说明有立刻删除这个数据文件所在表空间的意图。因此启动数据库后,必须马上删除或者重建表空间,否则会继续在alert_SID.log中发现上述报错。
高压线三:数据库软件所在目录不能满
/opt/oracle通常是数据库软件所在目录,也有局点用/home/oracle。这个目录塞满的后果如同root用户根目录塞满,维护工程师需要时刻留意/opt/oracle有可用空间。开局指导书一般要求安装前/opt/oracle有6G,甚至12G的空间,就是为这个目录留有足够多的空间,避免影响Oracle程序的正常运行,引发灾难性后果。
典型案例:一节点/opt/oracle满导致RAC另一节点宕机
某地发生RAC的一个节点oracle1宕机事故,alert_SID.log报错如下:
Thu Nov 11 12:54:57 2004
Errors in file /home/oracle/app/oracle/admin/ora8/bdump/pmon_21062_ora8.trc:
ORA-00482: LMD* process terminated with error
Thu Nov 11 12:54:57 2004
PMON: terminating instance due to error 482
Instance terminated by PMON, pid = 21062
问题处理过程:
LMD* process 是服务于RAC环境的后台进程,ORA-00482的错误表明DLM (Distributed Lock Manager)重新配置没有在规定的等待时间内完成,导致instance crash。该节点宕机由对方节点引起的,任何异常比如网络断开等都有可能,这种异常通称是由Hardware-/OS-issue引起的。
据现场反馈,事故发生前有刚进行过IBM巡检,IBM工程师发现用户将数据库备份到ORACLE_HOME造成目录满的问题,但没有整改。因此这次事故中oracle2的ORACLE_HOME满和oracle1宕机有直接关联,甚至是直接原因。因此,我们给出exp压缩和磁带的备份方法,并告知注意备份不要保存在ORACLE_HOME目录,以免影响ORACLE的正常运行。
尽管问题已经定位,但事情并没有就此结束。由于没有及时整改,10天之后工程师反馈由于备份保存在ORACLE_HOME目录造成目录满,RAC中的一台再次意外宕机。
总结:
小型机上根目录满会造成各种各样的异常,比如:TELNET失败,执行命令HANG住或者失败,甚至宕机的严重后果。对于数据库也是如此,如果数据库软件所在目录满,也将扰乱Oracle程序的正常运行,造成严重后果。现场工程师需要经常使用df –k观察各目录的空间使用情况。
此外,在备份指导书中,明确要求备份不要保存在数据库软件所在目录,而是单独为备份文件划分专用的备份目录。在执行exp备份命令时file参数使用全路径,也能够避免上述问题。
高压线四:正确使用图形工具和第三方工具
Oracle的图形化工具:企业管理器,DBA Studio等,第三方工具:PL/SQL Developer, TOAD等,因其图形化界面,功能强大,使用方便而广泛流行。但是,这些工具就像“双刃剑”,一方面不用记忆繁琐的命令和数据库对象,加快维护效率,另一方面由于操作简单,如果使用不当则破坏力强大,造成人为事故。
典型案例:某地因设置数据库停顿模式造成应用中断
某地数据库突然在业务高峰无法使用,总是得到"ora-00020 maximum number of processes (%s) exceeded "。此时连接到oracle的用户已经达到了150(达到参数上限),而数据库平常的连接一般不超过100。现场尝试停止部分应用,减少连接数等措施,均无效。
问题处理过程:
检查alert_web.log文件,发现当天有人执行:
ALTER SYSTEM SET resource_manager_plan="SYSTEM_PLAN" SCOPE=MEMORY;
ALTER SYSTEM SET resource_manager_plan="INTERNAL_QUIESCE" SCOPE=MEMORY SID="*";
怀疑是有人使用oracle的资源管理器(resource manager)将数据库置为停顿模式(QUIESCED),导致数据库无法访问。
远程紧急尝试各种方法连接数据库,执行ALTER SYSTEM SET resource_manager_plan="" SCOPE=MEMORY; ,取消系统当前的资源管理计划。数据库在几分钟内恢复正常,业务恢复。
经过仔细检查,发现SYS用户下还有两个定时job,是这两个job发出了利用资源计划将数据库设为停顿的命令。为消除隐患,现场将这两个定时任务删除。
总结:
停顿是一个9i的新特征,使得DBA可以完成一些数据库处于受限模式才能完成的一些操作。当使用oracle的资源管理器向数据库发出停顿命令后,因为当前数据库还有大量活动事务,故数据库一直处于要想停顿,但还要等待活动的运行事务完成,此时数据库可能会启动很多垃圾连接来阻止新用户登陆,造成业务中断数个小时。这是一个典型的使用图形工具发出错误指令,造成严重后果的案例。
典型案例:某地因SELECT FOR UPDATE造成同步中断
某地割接后第二天中午12点突然发现一个子节点的同步异常,刷新组的job中断近一个小时。发现日志中报错:
ORA-12012: error on auto execute of job 23
ORA-12008: error in materialized view refresh path
ORA-02049: timeout: distributed transaction waiting for lock
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 803
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 860
ORA-06512: at "SYS.DBMS_IREFRESH", line 683
ORA-06512: at "SYS.DBMS_REFRESH", line 195
ORA-06512: at line 1
维护人员尝试重新运行job但不成功,再次得到ORA-02049错误。因此重启数据库,又杀掉数据库中的一个一直存在的本地连接。此后job运行成功,同步恢复。
问题原因分析:
维护人员反馈曾将在主节点PL/SQL Developer下执行的更新语句直接拷贝到同步节点执行,语句如下:
Select * from t_userinfo where phonenumber=’***’ for update;
发生问题的数据库是一个仅存放只读快照的数据库,也就是说这个库是不应该有任何DML操作的。ORA-02049表明同步写数据失败,问题原因是此语句对同步节点的只读快照加锁,直接修改/加锁了同步节点的物化视图,造成同步写失败,导致应用失常用户投诉。
总结:
如果使用PL/SQL Developer直接修改记录,那么会自动生成SELECT FOR UPDATE的语句。一个普通的SELECT操作不会对正处理的行执行任何锁定设置,但加上FOR UPDATE会在相关数据行上加互斥锁,直到整个事务被提交才释放。工程师拷贝执行了错误的语句,而且没有关闭命令窗口,事务一直没有提交或者回滚,造成此次事故。
最近已经发生数起使用PL/SQL Developer更新用户表或者系统表,没有关闭命令窗口,事务一直没有提交或者回滚,造成锁等待影响数据库正常运行的事故。
结语
红灯停,绿灯行。只有遵守交通规则,才能避免安全事故。
硬盘坏、数据库BUG造成数据库事故的是小概率事件。更多数据库事故是人为原因,该调的参数没有调,该日常巡检观察的没有检查,该注意的事项没有规避等等。近一两年发布的各种安装、维护、巡检、备份等系列指导书,专门归纳常见热点问题的数据库FAQ,以及收录产品线原创好文的主机空间,涵盖了数据库日常维护的方方面面,包括知识点、操作命令,维护经验和注意事项等等内容,希望工程师能够好好的使用这些资料,提高维护技能。只要我们掌握维护规则,避开数据库操作的高压线,就能够有效的减少外购件的人为事故。