Oracle数据回滚:一次错误的事务提交引发的灾难

柔情只为你懂 2023-07-22 05:56 99阅读 0赞

写下这篇文章的时候,我差点要吃速效救心丸了……

2小时前,我发布了一次程序更新,有部分历史数据必须手动在数据库用SQL进行处理,约几百条记录。按照惯例,先在本地开发环境进行测试,然后开始在线上环境测试。真的印证了墨菲定理,几分钟后意外发生了……

我执行了错误的SQL,还提交了事务!造成的后果就是,有4条脏数据插入了生产环境中有25W行记录的表中,最要命的是,插入的数据无法根据时间戳排序筛选出来,因为每秒几百行的插入和数千次的更新早让时间标记乱序了。4条数据在25W行中找出来,简直是大海捞针。

冷静3秒,我第一件想到的就是查询SQL执行的历史记录。对,历史记录可以查到刚才的SQL!
SELECT SQL_TEXT, LAST_ACTIVE_TIME,SQL_FULLTEXT FROM v$sql ORDER BY LAST_ACTIVE_TIME DESC 执行后,我发现我错了,我执行的那条错误的SQL和线上用户操作了程序功能后调用的SQL是一个类型的!结果就是,尽管找到了历史记录,也不能找到我误执行的那条!怎么办?手动查找?几十万条数据,有点不靠谱。

既然Oracle安全性出了名的好,那肯定有很多相关的数据保护机制。那就找找百度、搜狗、Google,网友的力量总是强大的嘛!功夫不负有心人,果然,Oracle是由flashback闪回机制的。通俗点讲,就是有个缓存区,会按照时间戳备份每张表的历史数据。指定一个时间,就可以查询到对应时间点之前,这张表的历史状态。
SELECT * FROM tableName AS OF TIMESTAMP TO_TIMESTAMP('20180822 11:00:00','YYYYMMDD HH24:MI:SS');

经过查询,直接找到了5分钟前的历史数据,但有个问题,数据还不够旧!调整了参数,发现了新的问题——因为Oracle的相关设置,我最多查到5分钟的……真是屋漏偏逢连夜雨……

在这里插入图片描述
还有什么办法?冷静下来想想,刚才的操作都是站在开发者的角度,站在用户的角度呢?对,客户端程序是有用户操作历史记录的!

通过客户端历史记录,结合时间戳筛查,把范围从25W缩小到了200条记录!然后,就没有然后了,手动找了下,5分钟,找到了那4条脏数据!

虽然最终没有利用Oracle的相关机制解决问题,但这次事故还是值得思考的。

复盘下操作,我发现,真是犯了连幼儿园小朋友都不会犯的错误,update条件不是确定的!
update table t set t.enable ='n' where t.enable=‘y’ and t.id in (select t.id from table t where t.enable='y' and t.id2 ='xxx')

update table t set t.enable ='y' where t.enable=‘n’ and t.id in (select t.id from table t where t.enable='n' and t.id2 ='xxx')

我要更新的数百条记录,没有用联合主键确定,而是使用了一个状态位y与n。执行了一次update后,状态已经发生了改变,再次执行,结果就会完全不一致!

总结下,生产环境操作时,头脑要清晰,别犯浑。不干活,养鱼呢?说的就是你!

参考:oracle闪回机制简介,https://www.jb51.net/article/130703.htm

发表评论

表情:
评论列表 (有 0 条评论,99人围观)

还没有评论,来说两句吧...

相关阅读

    相关 事务,提交,

    事务的四大特性: 1. 原子性:原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完