Oracle的TNS_ADMIN获取与设置混乱误删除案例

TNS_ADMIN 是Oracle的一个环境变量,指向 SQL*Net 配置文件的位置。常见的配置文件有 sqlnet.ora 和 tnsnames.ora 等。

通常在 Windows 上,环境变量的设置类似如下:
set TNS_ADMIN=%ORACLE HOME%\network\admin

在 Unix/ Linux 设置类似如下:
export TNS_ADMIN=$ORACLE HOME/network/admin

那么是否可以通过其他方式获取当前采用的变量值呢?

我们可以通过DBMS_SYSTEM包来获取,Oracle提供了非常强大的工具。通过dbms_system.get_env可以获取环境变量的当前生效值:
SQL> var envout varchar2(200);
SQL> exec dbms_system.get_env('ORACLE_HOME',:envout);
PL/SQL procedure successfully completed.
SQL> set serveroutput on
SQL> exec dbms_system.get_env('ORACLE_HOME',:envout);
PL/SQL procedure successfully completed.
SQL> print envout
ENVOUT
---------------------------------------------------------------
/u01/app/oracle/product/11.2.0/dbhome_1
SQL> exec dbms_system.get_env('TNS_ADMIN',:envout);
PL/SQL procedure successfully completed.
SQL> print envout
ENVOUT
--------------------------------------------------------------------
/u01/app/oracle/product/11.2.0/dbhome_1/network/admin

当然,如果你在服务器上也有高阶权限,找到后台进程PMON的进程号:
[root@enmoteam1]# ps -ef|grep pmon
root      4800  4584  0 15:22 pts/0    00:00:00 grep pmon
oracle    9669     1  0 May26 ?        00:05:03 ora_pmon_enmot1

检查该进程的环境变量文件,也可以看到数据库启动所采用的缺省TNS_ADMIN参数值:
[root@enmoteam1]# cd /proc/9669
[root@enmoteam1 9669]# strings environ |grep TNS_ADMIN
TNS_ADMIN=/u01/app/oracle/product/11.2.0/dbhome_1/network/admin
TNS_ADMIN 参数重要么?有时候的确非常重要,老熊曾经记录过一个非常危险的案例(Oracle 9i中)。写在这里,供大家警示。

事发经过:一个开发人员,试图通过OEM(Oracle Enterprise Manager)连接到开发库上,删除一个用户。在删除时确认OEM上的连接字符串是正确的,然而很快发现,生产库的数据被删除了。

过程回放在数据恢复完成后,观看数据库用户被删除时的屏幕录像,从录像中可以看到,操作时的确是连接到开发库的,为什么会删除了生产库上的用户呢?

问题定位:原来进行删除操作的那台客户端机器运行的是Windows系统,在系统环境变量(我的电脑=>属性=>高级=>环境变量=>系统变量)中设置了TNS_ ADMIN,指向了另外的目录。现在,TNS_ADMIN指向的目录(下面简称TNS_ADMIN目录)和%ORACLE_HOME%\NETWORK\ADMIN(下面简称Oracle目录)下都有tnsnames.ora这个文件。

在TNS_ADMIN中,tnsnames.ora有一tnsname指向生产库。

在Oracle目录中,tnsnames.ora中有一同样名称的tnsname指向开发库。

OEM在处理TNS_ADMIN上是有问题的。OEM在启动后,左边的数据库目录树是从Oracle目录的tnsnames.ora中解析出来的,完全忽略了TNS_ADMIN环境变量,即使是执行“将数据库添加到树”操作,也是完全忽略了TNS_ADMIN变量,而是将Oracle目录中的tnsnames.ora的项添加到树中。

下面是两幅截图所示:

图1中显示的被选中的数据库为“XTY”,图2显示的是这个库的连接字符串。

然而,在用这个tnsname连接数据库时,却是按照TNS_ADMIN目录中的tnsnames.ora文件的配置进行连接的,如果这两个tnsnames.ora都有TNS Name,那么错误就发生了,本来我们期望是连接到OEM中显示的那个数据库上,结果却连接到了另一个库上。这可以是说OEM的重大Bug

案例警示:事情虽然过去了,但是有很多值得我们深思的地方。软件不可避免地存在Bug,所以在出现问题后,一味抱怨软件的Bug无济于事。我们只有吸取教训,从管理上、技术手段上去防止此类问题的发生,才是有意义的。

数据库的安全防范措施:


1. 开发库和生产库、测试库的密码不能相同,特别是要严格保护生产库的密码,生产库的密码应该定期修改。

2. 开发环境不能有到生产主机的TnsName

3. 通过IP地址来限制可以连接生产库的机器

4. 对于一些重要的特别是危及数据安全的操作,应分步进行。比如删除用户(Drop User)时,应先Lock User;删除表空间时,先将表空间OFFLINE;删除表等其他对象时,先进行改名(rename)操作;完成这些操作后,观察一段时间确认没有问题后,再真正执行删除操作。

5. 通过使用触发器,来限制可以进行的ddl操作

数据库运维,备份重于一切:


1. 有效的备份是在发生数据丢失和损坏后能够进行恢复的基础。每一个数据库DBA都应该切实关注备份问题。曾经有客户,虽然使用VERITAS进行数据库备份,然而在某次阵列出现问题不可用要进行恢复时才发现居然有部分数据文件没有备份,结果可想而知。

2. 进行恢复测试。恢复测试是数据备份恢复策略的重要组成部分。通过恢复测试,一方面检查备份是否有效,同时能够确认恢复流程是否正确、安全,恢复所需要的环境是否能够满足要求,恢复所需要的时间有多长,出现数据丢失或损坏后,能不能在预定的时间内完成恢复。

请使用浏览器的分享功能分享到微信等