[20150918]禁止用户truncate以及drop表.txt

[20150918]禁止用户truncate以及drop表.txt

--一个需求要求禁止用户truncate以及drop表,实际上很简单仅仅建立一个触发器就ok了.

CREATE OR REPLACE TRIGGER SYS.tri_prevent_drop_truncate
   BEFORE TRUNCATE OR DROP ON DATABASE
BEGIN
   IF ora_dict_obj_type = 'TABLE' AND ora_dict_obj_owner = 'SCOTT'
   THEN
      raise_application_error (-20000, 'YOU CAN NOT TRUNCATE or DROP ' || ora_dict_obj_name || ' TABLE!');
   END IF;
END;
/

--仔细想想存在什么问题吗?我首先想到的物化视图的刷新,有时候要执行truncate.当然看刷新的方式:

1.建立测试环境:

SCOTT@test> @ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.3.0     Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production

--建立触发器,脚本见上.

2.建立测试信息:

create table t (id number, name varchar2(30));
alter table t add constraint pk_t primary key (id);
create materialized view log on t;
--drop materialized view log on t;
create materialized view mv_t refresh complete as select count(*) from t;
insert into t select rownum, tname from tab;
commit;

SCOTT@test> exec dbms_mview.refresh('mv_t')
PL/SQL procedure successfully completed.
--可以发现这样没有问题.

SCOTT@test> select * from mv_t;
  COUNT(*)
----------
        49

--但是如果执行如下呢?
--11G物化视图刷新有1个参数atomic_refresh.
--如果为false,采用的方式是truncate,再使用/*+ append */ 提示insert。这样redo最少,但是刷新期间无法访问。
--如果为true,采用的方式是delete,再insert。这样产生许多redo与undo。这样在刷新期间访问没问题,最多有点慢。

--12c在这个基础上引入1个参数Out of place,刷新时先建立表在外部,刷新后通过类似分区交换的技术与之交换,这个刷新很形象的命名
--为out-of-place refresh.

SCOTT@test> exec dbms_mview.refresh('mv_t', atomic_refresh => false)
BEGIN dbms_mview.refresh('mv_t', atomic_refresh => false); END;

*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-20000: YOU CAN NOT TRUNCATE or DROP MV_T TABLE!
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2563
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2776
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2745
ORA-06512: at line 1

--因为是11g的缘故,无法测试out-of-place参数.不过应该不行.

3.还会有什么情况呢?
--重建索引.
SCOTT@test> ALTER INDEX SCOTT.PK_T REBUILD;
Index altered.

--再线重建索引呢?
SCOTT@test> ALTER INDEX SCOTT.PK_T REBUILD online;
ALTER INDEX SCOTT.PK_T REBUILD online
*
ERROR at line 1:
ORA-00604: error occurred at recursive SQL level 2
ORA-20000: YOU CAN NOT TRUNCATE or DROP SYS_JOURNAL_315614 TABLE!
ORA-06512: at line 4
ORA-00604: error occurred at recursive SQL level 2
ORA-20000: YOU CAN NOT TRUNCATE or DROP SYS_JOURNAL_315614 TABLE!
ORA-06512: at line 4

--再次执行会出现如下错误.
SCOTT@test> ALTER INDEX SCOTT.PK_T REBUILD online;
ALTER INDEX SCOTT.PK_T REBUILD online
*
ERROR at line 1:
ORA-08104: this index object 315614 is being online built or rebuilt

--可以发现使用online参数建立索引要建立一张SYS_JOURNAL_315614 IOT表(后面的数字对应PK_T索引的object_id),完成后再删除时
--由于触发器的限制报错!!也就是以上的脚本存在问题,必须排除这样情况.
--报ORA-08104错误处理可以参考许多网上的做法.删除SYS_JOURNAL_315614(关闭触发器先),执行如下:

DECLARE
   ret   BOOLEAN;
BEGIN
   ret := DBMS_REPAIR.ONLINE_INDEX_CLEAN (315614);
END;
/

--以sys用执行ok.

CREATE OR REPLACE TRIGGER SYS.tri_prevent_drop_truncate
   BEFORE TRUNCATE OR DROP ON DATABASE
BEGIN
   IF ora_dict_obj_type = 'TABLE' AND ora_dict_obj_owner = 'SCOTT' and ORA_DICT_OBJ_NAME like 'SYS_JOURNAL_%'
   THEN
      raise_application_error (-20000, 'YOU CAN NOT TRUNCATE or DROP ' || ora_dict_obj_name || ' TABLE!');
   END IF;
END;
/

4.顺便做一个测试看看,如果存在SYS_JOURNAL_315614表会出现什么情况?

SCOTT@test> create table SYS_JOURNAL_315614 as select * from t where 1=0;
Table created.

SCOTT@test> ALTER INDEX SCOTT.PK_T REBUILD online;
ALTER INDEX SCOTT.PK_T REBUILD online
*
ERROR at line 1:
ORA-08106: cannot create journal table SCOTT.SYS_JOURNAL_315614

SCOTT@test> host oerr ora 8106
08106, 00000, "cannot create journal table %s.%s"
// *Cause:  The online index builder could not create its journal table
// *Action: Rename the conflicting table or rerun the SQL statement. There
// *        may be a concurrent online index rebuild on the same object.
// *Action: rename your table in conflict or rerun the SQL statement
// *        there may be a concurrent online index rebuild on the same object.

--报ORA-08106错误,改名即可.

SCOTT@test> rename SYS_JOURNAL_315614 to txx;
Table renamed.

SCOTT@test> ALTER INDEX SCOTT.PK_T REBUILD online;
Index altered.

--实际上上面的写法还存在问题,主要_的解析为任何字符,如果存在SYSaJOURNALa315614这样的对象一样能删除.
SCOTT@test> rename txx to SYSaJOURNALa315614;
Table renamed.

SCOTT@test> drop table SYSaJOURNALa315614 purge ;
Table dropped.

--如果写正则表达式还复杂1点,修改如下:

CREATE OR REPLACE TRIGGER SYS.TRI_PREVENT_DROP_TRUNCATE
   BEFORE TRUNCATE OR DROP ON DATABASE
BEGIN
   IF ora_dict_obj_type = 'TABLE' AND ora_dict_obj_owner = 'SCOTT' and ORA_DICT_OBJ_NAME not like 'SYS\_JOURNAL\_%' escape '\'
   THEN
      raise_application_error (-20000, 'YOU CAN NOT TRUNCATE or DROP ' || ora_dict_obj_name || ' TABLE!');
   END IF;
END;
/

5.其它还有什么情况呢?自己也想象不出来.只能等问题出现了.

时间: 2024-10-23 20:13:58

[20150918]禁止用户truncate以及drop表.txt的相关文章

[20131017]11G下truncate的新特性.txt

[20131017]11G下truncate的新特性.txt http://www.askmaclean.com/archives/know-high-water-mark-truncate.html 11.2.0.2中出现truncate的新特性,截断表目前有了新选项:即drop all storage. 测试看看:SCOTT@test> @verBANNER--------------------------------------------------------------------

truncate,delete,drop的异同点

 truncate,delete,drop的异同点 说明:本文摘自oracle技术用户讨论组 truncate,delete,drop的异同点  注意:这里说的delete是指不带where子句的delete语句   相同点:truncate和不带where子句的delete, 以及drop都会删除表内的数据  不同点:  1. truncate和 delete只删除数据不删除表的结构(定义)       drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索

JavaScript禁止用户多次提交的两种方法_javascript技巧

[当服务器超载时,会出现提交卡顿的现象,但是用户在操作时,会不停重复点击提交,会造成服务器压力更大.所以我们需要进行限制] [1]将提交按钮禁止 <html> <head> <script> //禁止默认行为 因为这里要模拟服务器超载的时候,所以需要先禁止掉submit按钮自动提交的功能 function preventDef(event){ event=event||window.event; if(event.preventDefault){ return even

通过trigger禁止用户删除或修改等DDL操作

有时,为了防止意外删除数据库中的表或者其他数据库对象,可以通过人为的增加一个trigger来实现.如下: create or replace trigger ddl_denybefore create or alter or drop or truncate on databasedeclare  l_errmsg varchar2(100):= 'You have no permission to this operation';begin  if ora_sysevent = 'CREATE

TRUNCATE 快速删除表中的所有数据

备注 与 DELETE 语句相比,TRUNCATE TABLE 具有以下优点: 所用的事务日志空间较少. DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一个条目.TRUNCATE TABLE 通过释放用于存储表数据的数据页来删除数据,并且在事务日志中只记录页释放. 使用的锁通常较少. 当使用行锁执行 DELETE 语句时,将锁定表中各行以便删除.TRUNCATE TABLE 始终锁定表和页,而不是锁定各行. 表中将毫无例外地不留下任何页. 执行 DELETE 语句后,表仍会包含

怎样禁止用户打开win7控制面板界面

  你仔细了解过控制面板吗?控制面板是Windows用户界面的一部分,它允许用户可以在上面进行基本的系统操作设置和控制,例如添加硬件或者删除软件之类的.什么是组策略,组策略其实就是修改注册表中的配置,使用组策略方便对ghost win7系统的管理与配置,比手动修改注册表更加方便些也更加简单些. 那么,禁止用户打开控制面板,可以在组策略里面进行设置.下面,小编为各位系统用户介绍如何在组策略中禁止用户打开控制面板. 步骤一:在win7 64位旗舰版桌面开始菜单"搜索程序和文件"处,输入gp

TRUNCATE 快速删除表中的所有数据_MsSql

备注 与 DELETE 语句相比,TRUNCATE TABLE 具有以下优点: 所用的事务日志空间较少. DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一个条目.TRUNCATE TABLE 通过释放用于存储表数据的数据页来删除数据,并且在事务日志中只记录页释放. 使用的锁通常较少. 当使用行锁执行 DELETE 语句时,将锁定表中各行以便删除.TRUNCATE TABLE 始终锁定表和页,而不是锁定各行. 表中将毫无例外地不留下任何页. 执行 DELETE 语句后,表仍会包含

truncate delete, drop 语句区别

truncate delete,  drop 语句区别 不同点: 1. truncate和 delete只删除数据不删除表的结构(定义)     drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的存储过程/函数将保留,但是变为invalid状态. 2.delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发.    truncate,dr

Nginx禁止用户真实IP访问的方法配置

做过面向公网WEB运维的苦逼们肯定见识过各种恶意扫描.拉取.注入等图谋不轨行为吧?对于直接对外的WEB服务器,我们可以直接通过 iptables . Nginx 的deny指令或者是程序来ban掉这些恶意请求.   而对于套了一层 CDN 或代理的网站,这些方法可能就失效了.尤其是个人网站,可能就一台VPS,然后套一个免费的CDN就行走在互联网了.并不是每个CDN都能精准的拦截各种恶意请求的,更闹心的是很多CDN还不支持用户在CDN上添加BAN规则,比如腾讯云CDN...   因此,就有了本文的