关于delete,drop,truncate的问题 (r6笔记第14天)

有一个很常规的问题大量出现在笔试面试中,就是delete,truncate和drop的区别,当然这个问题我们也可以升华一下,通过这个简单的问题其实可以关联到Oracle的一些特性。 我们先来看看常规的问题,常规的回答。 从网上也搜了一些答案,自己也略微做了改动。 相同点:

1.truncate和不带where子句的delete, 以及drop都会删除表内的数据。

2.drop,truncate都是DDL(数据定义语言)语句,执行后会自动提交。 不同点:

1. truncate和 delete只删除数据不删除表的结构(定义) drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的存储过程/函数将保留,但是变为invalid状态.

2.delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发. truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger. 3.delete语句不影响表所占用的extent, 高水线(high watermark)保持原位置不动 drop语句将表所占用的空间全部释放 truncate 语句缺省情况下将数据空间释放,除非使用reuse storage; truncate会将高水线复位(回到最开始). 4.速度,一般来说: drop> truncate > delete

5.安全性:

小心使用drop 和truncate,尤其没有备份的时候.使用上,想删除部分数据行用delete,注意带上where子句. 回滚段要足够大. 想删除表,当然用drop 想保留表而将所有数据删除. 如果和事务无关,用truncate即可. 如果和事务有关,或者想触发trigger,还是用delete. 如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据

6.对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不WHERE子句的DELETE语句。 这个问题可能主要的意图就是能够简单做一个区分即可,可能里面还是有一些细节的知识点一时不会想到。 我们不能止步于此,如果是一个dba面试,我们可以把这个问题升华一下, 如果没有备份,drop,delete,truncate是否能够恢复? 从直观的感觉来说,似乎这个问题没什么含量,既然都已经drop,或者truncate了,是一个ddl语句,数据应该是回不来了,如果是delete,并且做了commit,数据也应该回不来了。 对于这个问题,至少从Oracle的角度来说,答案是可能,而且某些情况下市很可能。我们来一个一个分析 首先是drop操作,在Oracle里面,默认情况下是有回收站的功能,就是把一个表做了drop操作之后,其实从物理上这个表并没有删除,而是简单换了一个很长的名字, 比如我们做一个简单的例子。

SQL> create table tt tablespace data as select *from cat;
Table created.
SQL> drop table tt;
Table dropped.
SQL> show recycle    
--这个时候去查看回收站就会看到drop的表起了一个别名,当然这个表我们不能继续做dml操作了,但是可以简单查询里面的数据。
ORIGINAL  NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP  TIME
---------------- ------------------------------ ------------  -------------------
TT               BIN$HEEa4lcomhDgUKjAgAMeeg==$0  TABLE        2015-08-01:21:42:18
--当然回收站的功能在系统级有一个参数配置。默认是开启的。
SQL> show parameter recyclebin
NAME                                 TYPE         VALUE
------------------------------------ -----------  ------------------------------
recyclebin                            string       on

所以这个时候我们能说drop的数据一定能够恢复呢,还是不一定,为什么,主要有几个原因可以考虑。 比如这个表所在的表空间资源紧张,很可能回收站里的这个表的数据就会被回收后存放其它的数据了。 或者说某个用户的配额(quota)本来就不足,这个时候也很可能使用回收站的资源就会受到限制, 或者说在某些场景下,你创建的表直接放在了system表空间下,这个时候哪怕空间充足,也是不能直接恢复回来的。

所以通过这些分析来看,drop操作还是有很多的可能,但是还是最开始的声明,是可能而不是肯定。 再来看看truncate操作,这个操作就算从数据恢复的角度来说,也是无能为力了。但是我们的答案还是可能,这个时候还是要说说flashback database这个特性了。 比如某个时间点truncate了一个很重要的表。我们可以在情况允许的情况下尝试flashback database 当然这个特性你也还是有一个系统级的设置,默认情况下,flashback database的特性是没有启用的,SQL> select flashback_on from v$database;

FLASHBACK_ON ------------------ NO 需要在数据库Mount阶段使用alter database flashback on来启用,因为闪回日志记录数据库级的一些数据变化,所以势必会对数据库的性能和资源造成一定的影响。不过在测试环境,非正式环境还是可以大胆使用的。 比如我们也不太确定truncate的时间,我们可以不断的闪回,直到找到满意的结果未知,比如下面的步骤,我们闪回了两次,给定了两个时间点。

–Startup mount –Flashback database to timestamp xxxxx时间1; –Alter database open read only; –Shutdown immediate –Startup mount –Flashback database to timestamp xxxxx时间2; –Shutdown immediate –Startup mount –Alter database open resetlogs; 比如在某一个时间点我们发现数据是我们所期望的,我们就可以使用exp把数据给导出来,这就有点类似这些年来的所说的一个热词"穿越”,在数据库级我们级可以实现这样的穿越。 然后再需要的时候把数据给导进去。 当然了,这是一种默认的体系结构,如果想使用非常规手段,其实也可以做一些工作,因为在truncate的时候,其实数据文件里的数据块还没有立即清空,只是从数据字典级做了清空,同时把高水位线给降下来了。如果这个时候能够马上读取所在的数据文件,还是可能把数据给找回来,当然这是非常规方法了。但是也是一种思路。 所以看似不可能的truncate操作恢复也是有可能。 再来说说最后的delete操作,这个从Oracle层面来说,选项就更多了。 首先,delete操作会利用undo的资源,生成相应的Undo_sql,如果我们delete了数据之后做了,commit 其实可以从以下几个角度来考虑,当然都是闪回的一些特性了, 比如我们可以考虑flashback table这个特性,当然也是有一个开关,比如表名为test,则需要使用alter table test enable row movement来启用行移动,这个时候delete数据之后还是可能把数据通过闪回表给找回来。 比如我们可以这么做, flashback table test to timestamp to_timestamp('2015-08-01:14:09:37','yyyy-mm-dd:hh24:mi:ss'); 当然我们如果没有启用行移动,也没关系,我们可以使用flashback query. 这个特性从某种程度上来说,使用的欢迎程度要远高于flashback table,因为通用而且实用, 比如我们可以这么做。 select * from test as of timestamp to_timestamp('2015-08-01:14:09:37','yyyy-mm-dd:hh24:mi:ss'); 这个时候就会把那个时间点的数据都查出来了。还可以灵活调整时间,直到满意为止,这个时候可以略微改进一下。我们创建一个"临时表"把数据给持久下来。 create table xxxx select * from test as of timestamp to_timestamp('2015-08-01:14:09:37','yyyy-mm-dd:hh24:mi:ss'); 甚至在一些场景下,我们还可以使用flashback transaction,或者flashback version query来辅助完成一些特殊场景的数据恢复。 所以可以看到,闪回这个特性有不同的实现方式,数据的恢复还是有很多的可能。 从这个问题我们可以看到,有些问题我们略微改进一下,就会使得数据的恢复在一些场景下有一定的可能。

原文发布于微信公众号 - 杨建荣的学习笔记(jianrong-notes)

原文发表时间:2015-08-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏更流畅、简洁的软件开发方式

数据层应该分为两个部分,这样可以更好的“分工”,各自研究自己的功能

     数据层应该分为两个部分(并不是说一定要变成两层)第一个部分是处理SQL语句,包括存储过程的名称,存储过程的参数(一下的SQL语句都包含存储过程名称和存...

2226
来自专栏数据和云

故障分析:一则library cache lock问题处理

编辑手记:library cache lock 大家都并不陌生,在MOS上对该阻塞的一般成因描述为:一般可以理解的是alter table或者alter pac...

3725
来自专栏北京马哥教育

Mysql分库分表方案

为什么要分表 当一张表的数据达到几千万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询...

4446
来自专栏魏艾斯博客www.vpsss.net

修改 WP MEMORY LIMIT 和 php.ini 内存数值提高 WordPress 性能

2743
来自专栏大数据和云计算技术

hive拉链工具实战

这个丁延明同学写的一个实战工具,坚持用代码解决问题,推荐! 有相关业务的同学可以一起讨论,下面是正文。 ---- 1、背景 大家好 最近由于公司业务需要写了一篇...

3257
来自专栏思考的代码世界

Python网络数据采集之存储数据|第04天

存储媒体文件有两种主要的方式:只获取文件 URL 链接,或者直接把源文件下载下来。

4527
来自专栏文渊之博

SQL Server内存

背景 最近一个客户找到我说是所有的SQL Server 服务器的内存都被用光了,然后截图给我看了一台服务器的任务管理器。如图 ? 这里要说明一下任务管理器不会完...

3257
来自专栏数据和云

Real-time materialized view,面向开发者的12.2新特性

题记:在12.2之前,如果使用on command刷新物化视图,必须得有个job来定时的刷,那么,在一次job运行之后,下一次job到来之前,如果基表有数据变化...

3054
来自专栏idba

order by 主键id导致全表扫描的问题

一 简介 在检查某业务数据库的slowlog 时发现一个慢查询,查询时间 1.57s ,检查表结构 where条件字段存在正确的组合索引,正确的情况下优化器应...

1332
来自专栏PPV课数据科学社区

你用了吗?DBA必备的15款MySQL管理工具

如今,Web应用程序的响应速度是成功的关键法宝之一。它与用户互动,用户对网站的看法,甚至谷歌网站排名情况都有着密不可分的关系。数据库性能是响应速度最重要的因素之...

66211

扫码关注云+社区

领取腾讯云代金券