时间:2021-05-02
误区 #19:Truncate表的操作不会被记录到日志
错误
在用户表中的操作都会被记录到日志。在SQL Server中唯一不会被记录到日志的操作是TempDB中的行版本控制。
Truncate Table语句会将整个表中的所有数据删除。但删除的方式并不是一行一行的删除,而是将组成表的数据页释放,将组成表的相关页释放的操作交给一个后台的线程进行队列处理的过程被称为deferred-drop。使用后台线程处理deferred-drop的好处是这个操作不会使得其所在的事务需要执行很长时间,因此也就不需要大量的锁。在SQL Server 2000SP3之前的版本(这个版本引入了deferred-drop)在Truncate Table的时候出现过多的锁耗尽内存的事是家常便饭。
下面是测试代码:
复制代码 代码如下:
CREATE DATABASE TruncateTest;
GO
USE TruncateTest;
GO
ALTER DATABASE TruncateTest SET RECOVERY SIMPLE;
GO
CREATE TABLE t1 (c1 INT IDENTITY, c2 CHAR (8000) DEFAULT 'a');
CREATE CLUSTERED INDEX t1c1 on t1 (c1);
GO
SET NOCOUNT ON;
GO
INSERT INTO t1 DEFAULT VALUES;
GO 1280
CHECKPOINT;
GO
复制代码 代码如下:
SELECT COUNT (*) FROM fn_dblog (NULL, NULL);
GO
复制代码 代码如下:
TRUNCATE TABLE t1;
GO
SELECT COUNT (*) FROM fn_dblog (NULL, NULL);
GO
复制代码 代码如下:
SELECT
[Current LSN], [Operation], [Context],
[Transaction ID], [AllocUnitName], [Transaction Name]
FROM fn_dblog (NULL, NULL);
通过日志可以看出第一条显式开始Truncate Table事务,最后一条开始DeferredAlloc。正如你所见,Truncate操作仅仅是释放了构成表的页和区。
下面这个代码可以查看日志具体所做操作的描述:
复制代码 代码如下:
SELECT
[Current LSN], [Operation], [Lock Information], [Description]
FROM fn_dblog (NULL, NULL);
GO
你可以看出为了快速恢复的目的而加的相关锁(你可以在我的博文:Lock logging and fast recovery中了解更多)。
由上面日志看出,这个操作会对8个页加相关的锁,然后整个区一次性释放。释放过后会对相关的区加IX锁,也就是不能再被使用,当事务提交后才会进行deferred-drop,因此也就保证了Truncate table操作可以回滚。
另外,如果表上存在非聚集索引.那么操作方式也是类似,都是交给一个后台线程然后释放表和索引的页。释放的最小单位就是每个分配单元。按照上面步骤你自己尝试一下就应该能明白我的意思了。
PS:还有一个关于Truncate Table操作不能回滚的误区,我在:Search Engine Q&A #10: When are pages from a truncated table reused?这篇文章中进行了详细的解释。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文导读:删除表中的数据的方法有delete,truncate,其中TRUNCATETABLE用于删除表中的所有行,而不记录单个行删除操作。TRUNCATETA
误区#28:有关大容量事务日志恢复模式的几个误区28a)常见的DML操作可以被“最小记录日志”不是。在大容量事务日志恢复模式下只有一小部分批量操作可以被“最小记
删除表中的数据的方法有delete,truncate,其中TRUNCATETABLE用于删除表中的所有行,而不记录单个行删除操作。TRUNCATETABLE与没
本文导读:删除表中的数据的方法有delete,truncate,其中TRUNCATETABLE用于删除表中的所有行,而不记录单个行删除操作。TRUNCATETA
本文实例讲述了Yii框架日志操作。分享给大家供大家参考,具体如下:将日志记录到文本中.Yii::log("test");//写入测试日志//找到配置文件comp