免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6359 | 回复: 1
打印 上一主题 下一主题

[数据库] delete,truncate和drop的区别 [复制链接]

论坛徽章:
3
数据库技术版块每日发帖之星
日期:2015-06-25 22:20:00数据库技术版块每日发帖之星
日期:2015-08-06 06:20:00数据库技术版块每日发帖之星
日期:2015-08-28 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-08-03 13:18 |只看该作者 |倒序浏览
delete,truncate和drop的区别
1、truncate和delete只删除数据不删除表的结构(定义),而drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的存储过程/函数将保留,但是变为invalid状态。
2、delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发。
3、truncate,drop是ddl,操作立即生效,原数据不放到rollback segment中,不能回滚,操作不触发trigger。
4、delete语句不影响表所占用的extent,高水线(high watermark)保持原位置不动,truncate 语句缺省情况下将数据空间释放,除非使用reuse storage; truncate会将高水线复位(回到最开始),drop语句将表所占用的空间全部释放。
5、语句执行速度,一般来说: drop> truncate > delete
6、小心使用drop 和truncate,尤其没有备份的时候,想删除部分数据行用delete,注意带上where子句。
7、想保留表而将所有数据删除,如果和事务无关,用truncate即可,如果和事务有关,或者想触发trigger,还是用delete。
8、如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据。
9、对于由FOREIGN KEY 约束引用的表,不能使用TRUNCATE TABLE,而应使用不WHERE子句的DELETE语句。

另外,如果没有备份,drop,delete,truncate是否能够恢复?
从直观的感觉来说,似乎这个问题没什么含量,既然都已经drop,或者truncate了,是一个ddl语句,数据应该是回不来了,如果是delete,并且做了commit,数据也应该回不来了。
对于这个问题,至少从Oracle的角度来说,答案是可能,而且某些情况下是很可能。我们来一个一个分析:
首先是drop操作,在Oracle里面,默认情况下是有回收站的功能,就是把一个表做了drop操作之后,其实从物理上这个表并没有删除,而是简单换了一个很长的名字
如果回收站是开启的(默认开启)
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的时间,我们可以不断的闪回,直到找到满意的结果未知
如果在某一个时间点我们发现数据是我们所期望的,我们就可以使用exp把数据给导出来,然后再需要的时候把数据给导进去。

最后说说delete操作,这个从Oracle层面来说,选项就更多了。
        delete操作会利用undo的资源,生成相应的undo_sql,如果我们delete了数据之后做了commit,此时我们可以考虑flashback table这个特性:
flashback table test to timestamp to_timestamp('2015-08-01:12:02:27','yyyy-mm-dd:hh24:mi:ss');
我们也可以把那个时间点的数据都查出来:
select * from test as of timestamp  to_timestamp('2015-08-01:12:02:27','yyyy-mm-dd:hh24:mi:ss');
然后再创建一个表,把查询出来的数据导入进去,这样数据就恢复啦。
更多精彩Oracle学习,请关注我:

论坛徽章:
9
2015年亚洲杯之中国
日期:2015-03-30 15:47:152015亚冠之布里斯班狮吼
日期:2015-09-24 09:24:52技术图书徽章
日期:2015-12-04 19:47:59数据库技术版块每日发帖之星
日期:2015-12-13 06:20:00CU十四周年纪念徽章
日期:2016-06-15 11:23:562017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之四川
日期:2020-01-02 09:33:04CU十四周年纪念徽章
日期:2020-01-14 21:07:5615-16赛季CBA联赛之江苏
日期:2020-04-28 13:59:15
2 [报告]
发表于 2015-08-05 22:46 |只看该作者
8、如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据。

从正式环境导出来的数据库(有些表保留数据,有些是无数据导出),做了几笔业务,表中有几条数据,然后表空间接近100%,是怎么回事?

表空间大小正常(即分配的表空间不是那种特别小,只能存放几条数据的)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP