在今天的文章里,我想给你快速展示下当我们从表里删除记录时,在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('', 2000)
  5. ),
  6. (
  7. REPLICATE('', 2000)
  8. ),
  9. (
  10. REPLICATE('', 2000)
  11. ),
  12. (
  13. REPLICATE('', 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特权时,要考虑下这个情况了。使用合适的命令,这些程序还是能看到已经“删除”的数据。

感谢关注!

参考文章:

https://www.sqlpassion.at/archive/2014/02/11/delete-operations-on-tables/

表上的DELETE操作的更多相关文章

  1. 在SqlServer2008R2中,在一张表上加上insert、update、delete触发器(带游标)

    在日常工作中,在SqlServer2008R2中,需要向一张表上加上触发器,监控插入.更新.删除. --一个触发器内三种INSERT,UPDATE,DELETE状态 IF exists(select ...

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

    SELECT MAX(Scn) FROM Sys.Smon_Scn_Time WHERE Time_Dp < TO_DATE('2015-09-18', 'YYYY/MM/DD') select ...

  3. 请求部署在 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 解决 ...

  4. MySQL的数据库,数据表,数据的操作

    数据库简介 概念 什么是数据库?简单来说,数据库就是存储数据的"仓库", 但是,光有数据还不行,还要管理数据的工具,我们称之为数据库管理系统! 数据库系统 = 数据库管理系统 + ...

  5. PostgreSQL连接python,postgresql在python 连接,创建表,创建表内容,插入操作,选择操作,更新操作,删除操作。

    安装 PostgreSQL可以用Python psycopg2模块集成. sycopg2是Python编程语言的PostgreSQL数据库的适配器. 其程序代码少,速度快,稳定.不需要单独安装这个模块 ...

  6. MySql常用操作语句(2:数据库、表管理以及数据操作)

    本文主要内容转自一博文. 另外可供参考资源: SQL语句教程 SQL语法 1.数据库(database)管理  1.1 create 创建数据库 mysql> create database f ...

  7. 一起学HBase——总结HBase中的PUT、GET、DELETE操作

    传统的关系型数据库有CRUD增删改查操作,同样对于NoSQL列式数据库也有CRUD操作.本文对HBase中常用的Scan.GET.PUT.DELETE操作的用法做个总结. Put操作 Put相当于传统 ...

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

    veridata实验举例(4)验证veridata查找出updata.delete操作导致的不同步现象 续接:<veridata实验举例(3)验证veridata查找出insert操作导致的不同 ...

  9. Go语言学习教程:xorm表基本操作及高级操作

    在上节内容中,我们介绍了xorm框架表结构的映射规则和表结构的操作.本节课,继续来深入学习表结构基本操作和高级查询的相关功能. 表结构基本操作 对表结构的操作最常见的操作是查询和统计相关的方法,我们首 ...

随机推荐

  1. 【CUDA学习】共享存储器

    下面简单介绍一些cuda中的共享存储器和全局存储器 共享存储器,shared memory,可以被同一块中的所有线程访问的可读写存储器,生存期是块的生命期. Tesla的每个SM拥有16KB共享存储器 ...

  2. linux的库文件

    静态库和动态库 在windows中静态库是以 .lib 为后缀的文件,共享库是以.dll 为后缀的文件.在linux中静态库是以 .a 为后缀的文件,共享库是以 .so为后缀的文件. 以linux下的 ...

  3. android 6.0权限判断 音频 拍照 相册

    ------------------------------------------打开音频权限------------------------------------------------ if ...

  4. iOS中生成并导入基于Swift编程语言的Framework

    从iOS 8.0开始就引入了framework打包方式以及Swift编程语言.我们可以主要利用Swift编程语言将自己的代码打包成framework.不过当前Xcode 7.x在自动导入framewo ...

  5. 【转】关于TCP和UDP协议消息保护边界的介绍

    在 socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有一一成对的 socket,因此,发送端为了将多个发往接收端的包, ...

  6. 用Zim替代org-mode?

    三年前我玩过Zim,当时还写了一篇<Zim - 普通人的Org-mode>,当时还说我还是会坚持使用emacs org-mode.但最近我又在考虑是不是回头用Zim来写博客文章.整理知识库 ...

  7. Http 1.1协议

    HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间数据交换的过程. 1.Http1. ...

  8. android SDK Manager 上载失败

    android SDK Manager 下载失败如题,利用android SDK Manager 无法下载各个版本的SDK,是最近无法连接上谷歌的服务器吗?我用了网上说的在C:\WINDOWS\sys ...

  9. BaaS服务的定义、发展以及未来

    BaaS(Backend as a Service)是一种新型的云服务,旨在为移动和Web应用提供后端云服务,包括云端数据/文件存储.账户管理.消息推送.社交媒体整合等.BaaS是垂直领域的云服务,随 ...

  10. 2 个UserControl 的传值问题

    问题描述:有2个UserControl:UserControl1 里有一个Button,UserControl2 里面有一个TextBox,这2个控件都加载到了主窗体Form1 上.要求的是,点击 U ...