表上的DELETE操作

在今天的文章里,我想给你快速展示下当我们从表里删除记录时,在SQL Server里发生了什么。首先我们来创建一个简单的表,在8KB的页上刚好能插入4条记录。

1 -- Create a simple table where 4 records fit onto 1 page
2 CREATE TABLE TestTable
3 (
4     Col1 INT IDENTITY(1, 1),
5     Col2 CHAR(2000)
6 )
7 GO

接下来我们插入4条记录,这样的话一个页刚好全部填满。

 1 -- Insert 4 records
 2 INSERT INTO TestTable VALUES
 3 (
 4     REPLICATE(‘1‘, 2000)
 5 ),
 6 (
 7     REPLICATE(‘2‘, 2000)
 8 ),
 9 (
10     REPLICATE(‘3‘, 2000)
11 ),
12 (
13     REPLICATE(‘4‘, 2000)
14 )
15 GO

为了研究我们堆表的细节,我们使用DBCC PAGE命令来倾倒出分配的页面。因此我们还要启用3604跟踪标志,这样的话SQL Server从DBCC PAGE命令直接把结果输入到我们SSMS的会话窗口:

1 -- Enable the Trace Flag 3604
2 DBCC TRACEON(3604)
3 GO

我们可以使用DBCC IND命令返回所有分配给指定表或索引的页:

1 -- Retrieve all pages of the table
2 DBCC IND(DataModifications, TestTable, -1)
3 GO

从输出可以看到,2个页属于我们的表:数据页本身,还有IAM(索引分配图(index allocation map))页。

我这里的页号是118,通过DBCC PAGE命令倾倒出页面:

1 -- Dump out one specific page
2 DBCC PAGE (DataModifications, 1, 118, 2)
3 GO

当你使用选项2的第3个参数倾倒,SQL Server返回你16进制的页倾倒,包括在页尾所谓的行偏移数组(Row Offset Array),不以任何方式影响数据。

行偏移数组指向在页上的物理位置,即每条记录存储的地方。第1条记录总是直接存储在页头偏移量96(0x60h)的地方。你也会看到,行偏移数组是逆向增长的。现在让我们从表里删除第2条记录:

1 -- Delete a record from the table
2 DELETE FROM TestTable
3 WHERE Col1 = 2
4 GO

通常这里你会期待记录从页里删除。但事实上并不如此:当你再次执行DBCC PAGE命令时,你会看到在页上老记录的内容还是可以看到。在DELETE操作期间,SQL Server唯一做的是,在页尾行偏移数组里,对应的槽无效了。

如你所见,第2个槽的偏移量是0x0,这是无效的,意味着我们的记录被删除了。在页开始部分,你总会找到96 bytes的页头。现在让我们从表里删除其它的剩余3条记录。

1 -- Delete all the remaining records from the table
2 DELETE FROM TestTable
3 GO

当你再次用DBCC PAGE命令查看页,你会看到页全部内容还是没改变:每条记录的每个数据在页上还是物理存在的!但是在行偏移数据里每条记录都指向偏移量0x0,这意味着每条记录都被删除。这与你的表是否使用了聚集索引无关——老数据在页上一直存在。
现在的问题是,SQL Server什么时候会初始化页?当你现在插入新的记录,SQL Server会覆盖页的原始内容。但在我们的情况里,这只是物理部分,第1条记录存储的位置。你还是能看到其它“删除”的记录内容。当你在页尾看下行偏移数组,你会看到它已被SQL Server完全初始化了,也意味着你在行偏移数组里你现在只有1个槽了:

当你下次授权给程序sysadmin特权时,要考虑下这个情况了。使用合适的命令,这些程序还是能看到已经“删除”的数据。

感谢关注。

时间: 2024-10-09 17:44:57

表上的DELETE操作的相关文章

ORACLE 在重要的表上限制某些IP、用户的恶意操作

1,问题描述          oracle默认账号是没有限制ip的,这样的隐患就在于,如果我知道了oracle账号用户名密码,我只要能连接到db,就可以对db进行操作,这样对于线上的db来说是很危险的,因为有些非dba人员,比如开发人员.测试人员一不小心误删除了线上的数据,就惨了,坑太大不敢看.所以查了查,找到一种办法,在一些重要的表上加触发器来限制用户对线上db的表的操作. 2,触发器编写 如果开全局的sql审计,消耗性能太大,不太合适,想来只有在某些重要的表上做限制,初步解决问题了. 1)

ios ASIHttpRequest库进行DELETE操作时delete带有参数表单的使用方法

1,普通的DELETE只需加上下述一句code: [request setRequestMethod:@"DELETE"]; 2,附带有参数表单的情况(一次删除请求): ASIFormDataRequest *request; NSURL *baseURL = [NSURL URLWithString:@"http://www.baidu.com/xx/"]; request = [ASIFormDataRequest requestWithURL:baseURL]

请求部署在 IIS7.5 上的 REST 服务的 Put/Post/Delete 操作发生 HTTP Error 405.0 - Method Not Allowed 错误之解决

背景 请求部署在 IIS7.5 上的 REST 服务的 Put/POST/DELETE 操作发生 HTTP Error 405.0 - Method Not Allowed 错误. Issue 解决 在 WebAPI 应用的 Web.config 中加入如下设置: <system.webServer> <modules> <remove name="WebDAVModule" /> </modules> <handlers>

背景:表A数据误操作,被delete了,恢复。

SELECT MAX(Scn) FROM Sys.Smon_Scn_Time WHERE Time_Dp < TO_DATE('2015-09-18', 'YYYY/MM/DD') select b.file_name 物理文件名, b.tablespace_name 表空间, b.bytes/1024/1024 大小M, (b.bytes-sum(nvl(a.bytes,0)))/1024/1024 已使用M, substr((b.bytes-sum(nvl(a.bytes,0)))/(b.b

LINQ体验(9)——LINQ to SQL语句之Insert/Update/Delete操作

我们继续讲解LINQ to SQL语句,这篇我们来讨论Insert/Update/Delete操作.这个在我们的程序中最为常用了.我们直接看例子. Insert/Update/Delete操作 插入(Insert) 1.简单形式 说明:new一个对象,使用InsertOnSubmit方法将其加入到对应的集合中,使用SubmitChanges()提交到数据库. NorthwindDataContext db = new NorthwindDataContext(); var newCustomer

Oracle 11G 监控单张表的增删改操作

前言:    线上oracle数据库有张表的数据有些乱,根据应用db的log和应用的log也没有检查出来谁修改了,所以决定把这张单表做个详细的insert.update.delete监控.一:使用数据库自带的审计功能1,查看审计功能是否启动SQL> show parameter audit NAME     TYPE VALUE------------------------------------ ----------- ------------------------------audit_

DDL——对数据库表的结构进行操作的练习

-- 这是DDL,对数据库表的结构进行操作的练习 -- 1 创建数据库 create database emp; -- 2,删除数据库 drop database emp; -- 3,显示数据库 show databases -- 4,显示数据库创建语句 show create DATABASE emp; -- 5,创建表 use emp; create table classinfo( cid int(11),-- '班级ID' cname VARCHAR(32),-- '班级名称' Actu

表上999个非聚集索引——你怎么看?

对于数据获取,如果查询优化器在执行计划里选择了索引,那么SQL Server里的每个索引可以提高你的查询性能.但在另一方面,每个索引也会伤及你的性能,因为在INSERT,UPDATE和DELETE期间,每个索引需要被维护.因此对于你的工作量,尽可能创建少的索引非常重要——不然在写操作期间,你会有巨大的性能问题. 当你在表上定义了最大999个索引,SQL Server会如何反应?我从未在表上创建多大999个索引,因此详细验证下这个行为,并讨论下它引入的所有副作用,会是个很好的锻炼. 我们来创建一个

veridata实验举例(4)验证veridata查找出updata、delete操作导致的不同步现象

veridata实验举例(4)验证veridata查找出updata.delete操作导致的不同步现象 续接:<veridata实验举例(3)验证veridata查找出insert操作导致的不同步现象>,地址:点击打开链接 环境: Item Source System Target System Platform Red Hat Enterprise Linux Server release 5.4 Red Hat Enterprise Linux Server release 5.4 Hos