Skip to content

Database - 55. page

简便的数据刷选安全控制方式以及不可避免的ORA-01039错误

对于一些使用Oracle或者其他数据库(比如mysql,sql server,sybase,db2等)的企业或者单位,在涉及到一些数据交涉(可能是多级单位之间的数据交换获取)过程中,经常会碰到一些不愿意被对方看到的数据,那么这个时候就需要相关的表数据做刷选再传递给对方,刷选的方式有不少,比如dmg,rls,ols(rls的升级版),fgac,身份验证,role control等,更甚者会用dbv,这些都是oracle在安全方面所做的支持,每一种的设置都有自己优势和弊端,到这里你一定以为我会选择上面的一种方式来实现,哈哈~这里我要介绍的是采用view或者synonym的方式来控制,这里以Oracle数据库中来限制数据访问的最简单的方式为例子,在Oracle中如果相关数据规模不大,或者相关的业务执行频率可控,而且要做dml的限制,那么首先建议就是是采用view或者synonym,反之如果对dml有要求,要么在评估性能的基础上选择上面介绍的方式外,还有物化视图的方式。

具体如下:
我们先提出需求,用户a要求查询b下的b.t1表的关于id=100的数据,但是b用户不希望a用户在能看到t1表下id=100之外的数据,采用view的方式就会如下:

一.测试环境搭建:

create user a identified by ludatoua;
create user b identified by ludatoub;
grant resource,connect to ludatoua;
grant resource,connect to lidatoub;
grant select any dictionary to ludatoua; — 必须要的
grant select any dictionary to ludatoub; — 必须要的
grant select on v_$session to ludatoua;
grant select on v_$sesstat to ludatoua;
grant select on v_$statname to ludatoua;

B用户下:

create table t1 as select * from all_objects; –记得要现有权限
alter table t1 add rn number;
update t1 set rn=300;
update t1 set rn=100 where rownum < 5;

二.根据要求,通过建立view的方式刷选数据:

B用户下:

create view xh$t1 as select * from t1 where id=100;
grant select on ludatoub.xh$t1 to ludatoua;

A用户下操作:
view方式限制:

create synonym t1 for ludatoub.xh$t1;

synonym方式限制:

create synonym t1 for ludatoub.xh$t1;

到了这里我们要做简单的数据刷选(数据访问限制)已经完成了,但是有一个问题是不能被忽略的,ORA – 01039错误(在看执行计划的时候产生导致无法对这个view的执行计划进行观测), insufficient privileges on underlying objects of the view。错误的解释是相关对象的视图没有权限去访问定义的基表。这样的错误很多人都碰到过,但是都没有一个很好的解决方案,网上公布得最多的是grant select any dictionary to user的方式来解决,但是这个只能解决本身用户的,在我们这的情况下(在ludatoua)用户下,这种方式就起不到左右了。有兴趣的同学可以使用10053或者46去看在看执行计划时候到哪一步报错没权限,我这里就不列出了。
问题的原因在与view的嵌套视图的基础对象,ludatoua用户是没有对ludatoub下的对象select权限的,因为我们需要控制ludatoua不能直接访问ludatoub的t1表。在我们的案例中就是ludatoua用户无法对ludatoub的t1对象进行select才导致了这里看执行计划时候报错 ORA – 01039。这是采用view方式的一种弊端,所以时候时候还是需要权衡(个人使用过程影响不大,调优都是对view的刷选语句进行)。

这里在选择view或者synonym方式的时候就需要对view相关sql的性能进行了解,避免糟糕的性能对业务引起的不必要的影响,而view方式的调优都都在view本身这层。

某行维护的一些事,顺便附上自动清除Oracle归档日志的脚本

某银行的数据中心,核心不是Orcale,今年在迁移到Oracle,为此我也做了大量的准备工作,当然这是题外话。这个数据中心可以说是整个行的数据集中地点,从初步搭建到目前的成型,大部分的Oracle数据库以及衍生的相关产品都有我手上实施以及维护的汗水,但是整个中心的配套项目并没有跟上系统的脚步,几十套系统上线,再更新,数据库换平台,性能问题,冗余问题,安全问题,一个个在日常的维护工作中发生。举个例子,有一批的40多套Oracle数据库,10g版本,由行里的工程师安装,在老鸟看来是很简单的工作,但是对于一个赶进度的经理来讲就是一个粗糙的担心过程,在最后一步2个脚本没执行,40多套清一色都没有执行!这在我后期升级数据库的版本工作中,带来不小的麻烦,因为2天之内要升级40多套小系统的Oracle版本!对没错,测试 + 生产!类似这类问题等,还有很多~

配套的设施不完善,比如由于没有备份系统,成型的备份机制,在多次报告(china 的流程)陈述严重性后,经过十多个月,终于要盼来备份系统了~但是这个还只是在招标。为此,我不得不为众多的Oracle Db考虑归档日志的事情(因为我把所有数据库置为归档模式了!TAT!小系统也不放过),客户对一些系统有设置exp的导出备份,由于众多因素,设备也好,人力也好,很多东西不是我们工程师能控制的,所以我都争取保证每个没有备份的db置为归档模式下,采取保留archivelog 最大时间的方式,一般视为空间而定(最多30天吧,也有设置rman备份保留机制,但是只被允许在部分系统上设置),这里就把我把通用的Oracle归档定时清楚脚本粘上来,算是一个小解决方案吧~

步骤一:
在root用户下设置crontab的任务,脚本方式。当然了如果配置了Oracle用户的crontab的执行权限也可以使用oracle相关用户。

0 2 * * * /oracle/delete_arch01.sh >> /oracle/log/`/bin/date +”%Y%m%d”`.log  2>&1

步骤二:
设置脚本delete_arch01.sh,这个脚本的作用是调动oralce用户的归档清除shell脚本,具体如下:

脚本1.
需要注意的是脚本的权限,目录的权限,该脚本为root用户拥有

#delete_arch01.sh
#user:root
#It will excute at am 02:00
#user for delete archivelog of oracle database
su - oracle -c /oracle/delete_arch02.sh

步骤三:
该脚本为oracle用户拥有
设置脚本delete_arch02.sh,这个脚本的作用是登陆rman,使用rman清除7天前的归档日志,
这样做和rm比起来,
一方面可以避开归档日志的刷选问题,
一方面可以将控制文件的相关物理信息更新(以避免dg或者rman中报错)

脚本2.

#delete_arch_02.sh
#user:oracle
#It used by delete_arch_01.sh.
#export ORACLE_SID=xybank
rman target / log=/oracle/log/rman/sxbank_`/bin/date +"%Y%m%d"`_rman.log < <eof
crosscheck archivelog all;
delete noprompt expired archivelog all;
#delete noprompt obsolete; 清除过期的备份
delete noprompt archivelog all completed before 'sysdate - 7';
exit;
EOF

 

重新编译存储过程中遭遇ORA-04021

在今晚的客户现场遭遇了另外一个客户的数据库紧急宕机,处理完毕后这边编译存储过程遭遇ORA-04021,这个错误在编译存储过程的时候比较常遇见,通常这类错误的出现是由于锁的问题导致,一开始运行UTLRP.sql修复整个库的invalid objects,但是修复完后发现还存在1个package body为invalid,
逐用alter方式修复,具体如下:

SQL> @?/rdbms/admin/utlrp.sql

PL/SQL procedure successfully completed.

Table created.

Table created.

Table created.

Index created.

Table created.

Table created.

View created.

View created.

Package created.

No errors.

Package body created.

No errors.

PL/SQL procedure successfully completed.

PL/SQL procedure successfully completed.

SQL> select owner,object_name,object_type from dba_objects where status=’INVALID’ order by owner;

OWNER OBJECT_NAME OBJECT_TYPE
—————————— —————————————- ——————
SYS DBMS_AQ PACKAGE BODY

SQL> alter package DBMS_AQ compile;
alter package DBMS_AQ compile
*
ERROR at line 1:
ORA-04021: timeout occurred while waiting to lock object SYS.DBMS_AQ

遇见这个问题基本上判断是由锁造成,而查锁时候并未发现由锁引起的等待,倒是发现了锁未释放的情况,重启数据库后,再次查询,此对象为valid的状态,由此可见是因为utlrp修复完之后,DBMS_AQ上的锁未释放,导致重新申请修复的时候引发04021