一、执行DML语句,但还没commit,用rollback命令即可。
1、rollback
二、闪回:flashback
1、作用
(1)将commit的DML结果进行撤销(即撤销已提交的事务)
(2)还原删除的表(非sys用户删除,因sys删除的表不经回收站)
(3)获取表上的历史数据
2、类型
(1)闪回表中的数据
(2)闪回删除的表
(3)闪回事务查询:undo_sql
(4)闪回数据库
(5)闪回归档日志
3、查看闪回参数:要用sys用户
show parameter undo
(1)参数undo_retention的值是900表示,若闪回缓冲区已满,需要闪回的数据在缓冲区外,则需要在900秒内进行闪回,否则无力回天。
(2)可把undo_retention设置得更大
alter system set undo_retention=1800
也可以指定参数:
both: 重启库不重启库都生效
memory: 在内存中,当前库生效,重启库后就无效了
spfile: 放在文件里,当前库无效,只有重启库后才有效。
alter system set undo_retention=1800 scope=both|memory|spfile
三、案例1:闪回表的数据
1、闪回操作,必须知道时间点,
即SCN(system change number)
select timestamp_to_scn(sysdate) from dual;
2、步骤
(1)记录原表数据的empno=7369
(2)记录SCN时间点1488391
(3)删除empno=7369的数据
SQL> delete from myemp where empno=7369;
已删除 1 行。
(4)提交
SQL> commit;
提交完成。
(5)检查
(6)闪回
flashback table myemp to scn 1488391
(7)此时发现有错,需要开启行移动功能(当前普通用户即可)
alter table myemp enable row movement
(8)重新flashback
flashback table myemp to scn 1488391
闪回成功!
注意1:此时有可能当前用户没有权限,需要切回sys用户授权。
忘记是什么权限时,可先从all_table中查到相关权限表
SELECT * FROM all_tables WHERE table_name LIKE ‘%PRIV%’;
然后找到SYSTEM_PRIVILEGE_MAP表中有FLASH相关的权限
SELECT * FROM SYSTEM_PRIVILEGE_MAP WHERE name LIKE ‘%FLASH%’;
即FLASHBACK ANY TABLE
此时授权
GRANT FLASHBACK ANY TABLE TO SCOTT
注意2:闪回的数据表结构要前后一致,不然也闪回不了,报“ORA-001466:无法读取数据-表定义已经更改”的错误。
四、案例:删除已删除表(非sys用户删除的表)
1、sys用户删除的表不进回收站,所以闪回不了。
2、闪回的表也包括表中的数据。
3、步骤
(1)建测试表
(2)两种方式查看回收站,可知该用户下的回收站没东西。
(3)删表
(4)查看回收站,此时发现刚才删除的TEST表在回收站里。
(5)闪回:flashback table test to before drop;
(6)检查,发现表已经在库,且回收站里没东西了。闪回成功。
3、万一删除后,库里重新建了该表怎么办?
此时可考虑重命名了
flashback table test to before drop rename to mytest;
4、那万一回收站中有多次被删除的同一个表,我想闪回具体一个,怎么办呢?
此时不能用TEST表名了,而要用回收站中"RECYCLEBIN NAME"列的具体内容,且此列值有特殊符号,要用双引号括起来。
5、清空回收站:purge recyclebin
6、删除表不经过回收站
DROP TABLE TEST PURGE
可知,前后show recyclebin显示回收站都没内容。
五、案例:闪回事务查询 undo_sql
1、之前闪回数据时,根据SCN时间点闪回,但忘记时间点了怎么办呢?要用闪回事务查询,好像版本一样,闪回哪个版本(哪一次)的数据。
2、如何定位提交了几次呢?则要进行“闪回版本”查询。
3、bug:若每次插入+commit太快,oracle有可能在tb_version抓不到版本号。
4、步骤
(1)准备表
CREATE TABLE INFO(NAME VARCHAR2(40), AGE NUMBER(3))
(2)开启额外日志(只有开启记录日志,才有undo的信息)
alter database add supplemental log data;
提示权限不足,则切到sys用户执行,然后再切回普通用户scott
(3)准备数据(注意要慢慢执行,不然oracle的bug会记录不到版本,为空)
INSERT INTO info VALUES(‘Lucy01’, 1);
INSERT INTO info VALUES(‘Lucy02’, 2);
INSERT INTO info VALUES(‘Lucy03’, 3);
COMMIT;
INSERT INTO info VALUES(‘Lucy04’, 4);
INSERT INTO info VALUES(‘Lucy05’, 5);
INSERT INTO info VALUES(‘Lucy06’, 6);
COMMIT;
INSERT INTO info VALUES(‘Lucy07’, 7);
INSERT INTO info VALUES(‘Lucy08’, 8);
INSERT INTO info VALUES(‘Lucy09’, 9);
(4)查询该表的版本信息等
select name,age,versions_xid,versions_operation,versions_starttime,versions_endtime from info;
咦?什么情况?不是说这几个字段versions_xid,versions_operation,versions_starttime,versions_endtime是伪列么?怎么还说“标识符无效”?
琢磨了好久,原来是这样写的
select name,age,versions_xid,versions_operation,versions_starttime,versions_endtime from info ***VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALU***E ;
是后面“VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE”的伪列。
(5)那undo_sql存放在哪?存在字典flashback_transaction_query中
先看看字典flashback_transaction_query的数据结构
desc flashback_transaction_query
(6)那看看第二批提交的数据(Lucy04/Lucy05/Lucy06)对应的undo_sql是什么
SELECT * FROM FLASHBACK_TRANSACTION_QUERY;
又权限不足,记不信怎么办?查
哪个表会存放权限相关的呢?
SELECT TABLE_NAME FROM all_tables WHERE TABLE_NAME LIKE ‘%PRI%’
哪个表又存放事务(TRANSACTION)相关的呢?
SELECT name FROM SYSTEM_PRIVILEGE_MAP WHERE name LIKE ‘%TRANS%’
看起来有点像这个SELECT ANY TRANSACTION
切到sys用户授权再说
grant SELECT ANY TRANSACTION to scott;
再查来看看
select * from flashback_transaction_query;
(此时会把历史操作过commit的东西都查出来,太多了,没必要,我们只要案例中的版本05000100E7040000即可
SELECT XID,OPERATION ,TABLE_NAME ,UNDO_SQL FROM FLASHBACK_TRANSACTION_QUERY WHERE XID = ‘05000100E7040000’;
delete from “SCOTT”.“INFO” where ROWID = ‘AAASPbAAEAAAAIcAAF’;
delete from “SCOTT”.“INFO” where ROWID = ‘AAASPbAAEAAAAIcAAE’;
delete from “SCOTT”.“INFO” where ROWID = ‘AAASPbAAEAAAAIcAAD’;
(7)取出一个undo_sql来执行
delete from “SCOTT”.“INFO” where ROWID = ‘AAASPbAAEAAAAIcAAE’;
(8)查询
SELECT * FROM INFO;
此时发现Lucy05记录没有了!!!
事务闪回成功!
(9)那undo_sql与直接删除如
DELETE FROM INFO WHERE NAME = 'Lucy05’有什么区别呢?
1)undo_sql是撤销历史数据,即删除的是历史数据。
2)而直接删,删除的是现在的数据,即新作了一次dml
效果一样,作用域不一样!