闪回事务处理-主外键约束

准备实验表

SQL> create table t_p(id number primary key,name varchar2(10));

 

Table created.

 

SQL> create table t_f(fid number,foreign key(fid) references t_p(id));

 

Table created.

 

T_P表

id number primary key

name varchar2(10)

 

T_F表

fid number references t_p(id)

 

准备事务

事务一(0A001C0046020000)

SQL> insert into t_p values(1,'a');

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from t_p;

 

ID NAME

---------- ----------

1 a

 

事务二(03001C00CF020000)

SQL> update t_p set name='a1';

 

1 row updated.

 

SQL> insert into t_p values(2,'b');

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from t_p;

 

ID NAME

---------- ----------

1 a1

2 b

 

事务三(05001300CB020000)

SQL> insert into t_f values(2);

 

1 row created.

 

SQL> insert into t_p values(3,'c');

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from t_p;

 

ID NAME

---------- ----------

1 a1

2 b

3 c

 

SQL> select * from t_f;

 

FID

----------

2

 

 

分析

欲闪回事务二

事务二,包含了两条DML

其中,insert 2 b这条记录

被事务三引用,insert 2这条记录通过主外键关系这种方式引用了

 

闪回,使用常规的手段,行不行?

cascade?

nonconflict_only?

 

 

尝试nocascade?

1 declare

2 v_xid xid_array;

3 begin

4 v_xid := sys.xid_array('03001C00CF020000');

5 dbms_flashback.transaction_backout(1,v_xid,dbms_flashback.nocascade);

6* end;

SQL> /

declare

*

ERROR at line 1:

ORA-55511: Flashback Transaction experienced error in executing undo SQL

ORA-02292: integrity constraint (ORA-02292: integrity constraint (SCOTT.SYS_C0011074)

violated - child record found

.) violated - child record found

ORA-06512: at "SYS.DBMS_FLASHBACK", line 37

ORA-06512: at "SYS.DBMS_FLASHBACK", line 70

ORA-06512: at line 5

 

尝试cascade

1 declare

2 v_xid xid_array;

3 begin

4 v_xid := sys.xid_array('03001C00CF020000');

5 dbms_flashback.transaction_backout(1,v_xid,dbms_flashback.cascade);

6* end;

SQL> /

declare

*

ERROR at line 1:

ORA-55511: Flashback Transaction experienced error in executing undo SQL

ORA-02292: integrity constraint (ORA-02292: integrity constraint (SCOTT.SYS_C0011074)

violated - child record found

.) violated - child record found

ORA-06512: at "SYS.DBMS_FLASHBACK", line 37

ORA-06512: at "SYS.DBMS_FLASHBACK", line 70

ORA-06512: at line 5

 

尝试nonconflict_only

1 declare

2 v_xid xid_array;

3 begin

4 v_xid := sys.xid_array('03001C00CF020000');

5 dbms_flashback.transaction_backout(1,v_xid,dbms_flashback.NONCONFLICT_ONLY);

6* end;

SQL> /

declare

*

ERROR at line 1:

ORA-55511: Flashback Transaction experienced error in executing undo SQL

ORA-02292: integrity constraint (ORA-02292: integrity constraint (SCOTT.SYS_C0011074)

violated - child record found

.) violated - child record found

ORA-06512: at "SYS.DBMS_FLASHBACK", line 37

ORA-06512: at "SYS.DBMS_FLASHBACK", line 70

ORA-06512: at line 5

 

 

思考为什么不行

此次与上一例有何不同

表与表之间存在引用

闪回事务,不论使用哪种方式,只能在同一个张表上,执行

这种多表的例子,若想闪回,如何处理?

SQL> select xid,operation,undo_sql from flashback_transaction_query

2 where table_name='T_P' order by START_TIMESTAMP;

 

XID OPERATION UNDO_SQL

-------------------- ---------- --------------------------------------------------

0A001C0046020000 INSERT delete from "SCOTT"."T_P" where ROWID = 'AAASPBAAE

AAAAIUAAA';

 

03001C00CF020000 INSERT delete from "SCOTT"."T_P" where ROWID = 'AAASPBAAE

AAAAIUAAB';

 

03001C00CF020000 UPDATE update "SCOTT"."T_P" set "NAME" = 'a' where ROWID

= 'AAASPBAAEAAAAIUAAA';

 

05001300CB020000 INSERT delete from "SCOTT"."T_P" where ROWID = 'AAASPBAAE

AAAAIUAAC';

 

SQL> select xid,operation,undo_sql from flashback_transaction_query

2 where table_name='T_F' order by START_TIMESTAMP;

 

XID OPERATION UNDO_SQL

-------------------- ---------- --------------------------------------------------

05001300CB020000 INSERT delete from "SCOTT"."T_F" where ROWID = 'AAASPDAAE

AAAAIkAAA';

 

对于主外键这种约束造成的闪回事务间冲突

无法使用单表上闪回事务处理的那些选项

必须,在两张表上,关于要闪回的事务相关的所有有冲突的事务,同步的进行闪回

在本例中,即同时,在t_p和t_f上,进行与事务二有关的所有事务的闪回

t_f上,有一个事务,是insert 2

这个事务,依赖于事务二,所以要对该表上这个事务也进行闪回

1 declare

2 v_xid xid_array;

3 begin

4 v_xid := sys.xid_array('03001C00CF020000','05001300CB020000');

5 dbms_flashback.transaction_backout(2,v_xid);

6* end;

SQL> /

 

PL/SQL procedure successfully completed.

 

SQL> select * from scott.t_p;

 

ID NAME

---------- ----------

1 a

 

SQL> select * from scott.t_f;

 

no rows selected

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
T-SQL中级教程,包括PPT、学习笔记及课后作业,非常经典的教程 --建库之前先建路径的代码 exec xp_cmdshell'mkdir d:\mydata', --也可以用exec xp_cmdshell'md d:\mydata' no_output exec xp_cmdshell'rd d:\mydata' --删除目录 --查看先前建的文件夹是否成功创建 exec xp_cmdshell'dir d:\' ---------------------------------------------------------------------------------------------------------------- /*切换数据库*/ use master go /*开启master表来判断要新建的数据库是否已经存在*/ if exists (select * from sysdatabases where name='stuDB') /*存在就先删除*/ drop database stuDB /*创建数据库*/ create database stuDB /*创建数据库文件*/ on primary ( name='stuDB_data_1', --数据库逻辑名 filename='d:\mydata\stuDB_data_1.mdf', --数据库路径及名称 size=10mb, --数据库初始大小 maxsize=100mb, --数据库最大大小 filegrowth=15% --数据库增长 ), /*创建次要数据库文件*/ ( name='stuDB_data_2', --数据库逻辑名 filename='d:\mydata\stuDB_data_2.ndf', --数据库路径及名称 size=10mb, --数据库初始大小 maxsize=100mb, --数据库最大大小 filegrowth=15% --数据库增长 ) /*创建日志文件*/ log on ( name='stuDB_log_1', --数据库逻辑名 filename='d:\mydata\stuDB_log_1.LDF', --数据库路径及名称 size=10mb, --数据库初始大小 maxsize=100mb, --数据库最大大小 filegrowth=15% --数据库增长 ), /*创建日次要志文件*/ ( name='stuDB_log_2', --数据库逻辑名 filename='d:\mydata\stuDB_log_2.ldf', --数据库路径及名称 size=10mb, --数据库初始大小 maxsize=100mb, --数据库最大大小 filegrowth=15% --数据库增长 ) /*如果有多个,请用,()来创建*/ /*批处理的结束 go*/ go ---------------------------------------------------------------------------------------------------------------- /*开始建表*/ /*-创建学员信息表-*/ use stuDB --将当前数据库设置为stuDB go --判断要创建的表是否存在,如果存在就删除 if exists(select * from sysobjects where name='stuInfo') drop table stuInfo --建表 create table stuInfo ( stuName varchar(20) not null, --姓名,非空(必填) stuNo char(6) not null, --学号,非空(必填) stuAge int not null, --年龄,INT类型默认为4个字节 stuID numeric(18,0), --身份证号 代表18位数字,小数位数为0 stuSeat smallint identity(1,1), --座位号,自动编号 起始量为1,自增长1 stuAddress text --住址,允许为空,即可选输入 ) go /*学生成绩表*/ if exists(select * from sysobjects where name='stuMarks') drop table stuMarks create table stuMarks ( examNo char(7) not null, --考号 stuNo char(6) not null, --学号 writtenExam int not null, --笔试成绩 LabExam int not null --机试成绩 ) go --查看表的字段 select * from stuMarks select * from stuInfo ---------------------------------------------------------------------------------------------------------------- /*建约束的格式*/ /** 键约束(Primary Key Constraint):要求键列数据唯一,并且不允许为空 唯一约束(Unique Constraint):要求该列唯一,允许为空,但只能出现一个空值。 检查约束(Check Constraint):某列取值范围限制、格式限制等,如有关年龄的约束 默认约束(Default Constraint):某列的默认值,如我们的男性学员较多,性别默认为“男” 外键约束(Foreign Key Constraint):用于两表间建立关系,需要指定引用表的哪列 */ /*添加约束的语法*/ alter table 表名 add constraint 约束名 约束类型 具体的约束说明 /*删除约束的语法*/ alter table 表名 drop constraint 约束名 ---------------------------------------------------------------------------------------------------------------- /*为stuInfo表添加约束*/ alter table stuInfo add constraint PK_stuNo primary key(stuNo) --添加键约束 alter table stuInfo add constraint UQ_stuId unique(stuId) --添加唯一约束 alter table stuInfo add constraint DF_stuAddress default('地址不详') for stuAddress --添加默认约束 alter table stuInfo add constraint CK_stuAge check(stuAge between 10 and 40) --检查约束 /*为stuMarks表添加约束*/ alter table stuMarks add constraint FK_stuNo foreign key(stuNo) references stuInfo(stuNo) --添加外键约束键为stuMarks表的stuNo键,外键为stuInfo表的stuNo键) alter table stuMarks add constraint CK_writtenExam check(writtenExam between 0 and 100) --检查约束,成绩只能是0到100之间的数 alter table stuMarks add constraint CK_LabExam check(LabExam between 0 and 100) --检查约束,成绩只能是0到100之间的数 ---------------------------------------------------------------------------------------------------------------- /*安全模型*/ exec --专门用来调用存储过程 exec sp_grantlogin '域名\用户名' --创建window用户 sp_grantdbaccess '登录账户名','数据库用户' --grant授权 访问数据库 grant 权限[on 表名] to 数据库用户 --为用户授权 USE stuDB GO /*--为zhangsanDBUser分配对表stuInfo的select, insert, update权限--*/ GRANT select, insert, update ON stuInfo TO zhangsanDBUser -------------------------------------------------------------------------------------------------------------------- /*第一关:创建SQL登陆账户*/ use master --切换到数据库 exec sp_addlogin 'admin','888888' --创建SQL登陆账户 /*第二关:创建数据库用户*/ --首先切换到要分配权限的数据库 use stuDB --exec sp_grantdbaccess '登陆账户','数据库账户' exec sp_grantdbaccess 'admin','stuDB' --grant授权 访问数据库 /*第三关:为数据库用户分配权限*/ --grant 权限 on 表名 to 数据库用户 grant select on stuInfo to stuDB --为数据库用户名赋予查询权限 --收回查找权限 revoke 权限 on 表名 from public --为用户删除权限 revoke select on stuInfo from stuDB exec sp_revokedbaccess 'stuDB' --删除数据库用户stuDB对数据库的访问权限 exec sp_droplogin 'admin'

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值