在 MySQL 和 Oracle 数据库中,事务提交后都无法回滚。
在 MySQL 中,恢复机制是通过回滚日志(undo log)实现的,所有事务进行的修改都会先记录到这个回滚日志中,然后在对数据库中的对应行进行写入。当事务已经被提交之后,就无法再次回滚了。
在 Oracle 数据库中,当一个事务执行成功后,数据库会将事务所做的改变持久化到磁盘中,这样就保证数据的安全性和一致性。而且一旦事务提交,数据库将不再保存旧的数据。由于磁盘上的数据是不可逆的,因此一旦数据写入成功,就无法再次修改。
所以并不是回滚,但是当我在pl dev软件中执行了某些修改,删除等操作,并手动提交事务之后,现在想要恢复原本的数据怎么办呢?
Oracle提供了闪回的功能,可以查询出来数据,在你某个时间节点之前的数据。 比如这样:
SELECT * FROM IMAE_T AS OF TIMESTAMP TO_TIMESTAMP('20231008 08:00:00','YYYYMMDD HH24:MI:SS')
WHERE IMAEENT = 88 AND IMAESITE = 'JHNL' AND IMAE001 LIKE '1004%' ORDER BY IMAE001
但是这个时间不能太长,否则会报错:
oracle数据库报错:ORA-01555: 快照过旧: 回退段号 10 (名称为 "_SYSSMU10_3550978943$") 过小
简单记录一下,可能就是因为写入的undo表空间的undo数据太大了,很有可能就是被固定周期内清除掉了这个数据。
ORA-01555
是 Oracle 数据库中的一个错误,表示在尝试读取数据库中的数据时,发现所需的回滚段已经回滚到一个不再包含所需数据版本的点。这通常发生在长时间运行的事务中,尤其是在使用读一致性的情况下。
错误消息中的一部分 “过小
” 暗示了回滚段的大小问题。当 Oracle 查询引擎尝试使用回滚段的过时版本时,可能由于回滚段不足以支持所需的读一致性而导致这个错误。
一些可能导致这个错误的常见原因包括:
-
长时间运行的事务:如果有一个持续运行的事务,可能会导致回滚段变得很小,无法支持所需的读一致性。
-
回滚段配置问题:如果回滚段配置不合理,也可能导致空间不足。
-
大量的并发事务:如果有大量的并发事务,可能会导致回滚段被频繁使用,使其难以维护。
解决这个问题的方法可能包括:
- 增加回滚段的大小或数量。
- 优化事务,确保它们不会在长时间内持有锁或在数据库中运行。
- 考虑使用更高级别的事务隔离级别,以减轻
ORA-01555
错误的发生。
当前还可以直接闪回一个表的数据到某个时间点。
-- 使用闪回将员工表恢复到1小时前的状态
FLASHBACK TABLE employees TO TIMESTAMP(sysdate-1/24);
在上述代码中,我们使用FLASHBACK语句将名为employees的表恢复到1小时前的状态。这意味着如果在过去1小时内进行了任何更改,则这些更改将被撤消。
它可以在不进行备份的情况下将数据库回滚到过去的某个时间点。
以下是详细步骤:
- 启用闪回功能:首先,需要确保数据库已经启用了闪回功能。这包括启用自动撤销管理(Automatic Undo Management)和设置回滚段(Rollback Segment)的保留时间。
- 使用闪回查询(Flashback Query):闪回查询允许您查询过去某个时间点的数据。要使用闪回查询,请使用以下语法:
SELECT *
FROM table_name AS OF timestamp
TO TIMESTAMP('2016-08-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS');
这里的 timestamp
是一个时间戳,表示要回滚到的时间点。
3. 使用闪回表(Flashback Table):闪回表允许您将当前表恢复到过去的某个状态。要启用闪回表,请使用以下语法:
ALTER TABLE table_name ENABLE ROW MOVEMENT;
- 使用闪回数据库(Flashback Database):闪回数据库允许您将整个数据库回滚到过去的某个时间点。这在需要恢复整个数据库的情况下非常有用。要使用闪回数据库,请使用以下语法:
FLASHBACK DATABASE TO TIMESTAMP('2016-08-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS');
需要注意的是,使用闪回功能可能会影响数据库的性能,因此建议谨慎使用。另外,闪回功能并不能替代备份,因此在日常维护中,还需要定期对数据库进行备份。
但是我的只是更改了几千条数据,并不是想要去动这个表的几万条数据。是有筛选条件的闪回。
所以不能使用整个表的闪回功能。
最终选择了手动去更新。
- 首先通过闪回筛选条件查出来变更前的数量单子
- 拷贝出来修改前的字段
- 查询sql语句 然后for update 直接进行拷贝粘贴
- 最后提交事务
这就是我通过闪回功能回滚数据的一次操作。
ok,我已经讲完。