理解1是正确的。SQL Server记录将数据更改为事务日志的每个操作。回滚是对数据的更改,因此它也将其记录到事务日志中。作为语句A运行,它将数据写入事务日志,并且还将保留事务日志中的数据,以防需要回滚语句A。B和C也是如此。回滚事务时,更多信息将被写入日志。
有很多方法可以看到此效果,因此下面是一个快速演示。这是我将用来查看写入日志的查询:
SELECT
COUNT(*) transaction_count
, SUM(database_transaction_log_bytes_used) used_bytes
, SUM(database_transaction_log_bytes_reserved) reserved_bytes
FROM sys.dm_tran_database_transactions
where database_id = 10;
我的桌子:
create table TLOGDEMO (FLUFF VARCHAR(1000));
BEGIN TRANSACTION
查询A使用最少的日志记录:
INSERT INTO TLOGDEMO WITH (TABLOCK)
SELECT REPLICATE('A', 1000)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
之后:
╔═══════════════════╦════════════╦════════════════╗
║ transaction_count ║ used_bytes ║ reserved_bytes ║
╠═══════════════════╬════════════╬════════════════╣
║ 1 ║ 24006640 ║ 175429451 ║
╚═══════════════════╩════════════╩════════════════╝
查询B不使用最少的日志记录:
INSERT INTO TLOGDEMO
SELECT REPLICATE('B', 1000)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
B之后:
╔═══════════════════╦════════════╦════════════════╗
║ transaction_count ║ used_bytes ║ reserved_bytes ║
╠═══════════════════╬════════════╬════════════════╣
║ 1 ║ 7352935708 ║ 1613986255 ║
╚═══════════════════╩════════════╩════════════════╝
查询C更改的数据较少:
INSERT INTO TLOGDEMO
SELECT REPLICATE('C', 1000)
FROM master..spt_values c;
C之后:
╔═══════════════════╦════════════╦════════════════╗
║ transaction_count ║ used_bytes ║ reserved_bytes ║
╠═══════════════════╬════════════╬════════════════╣
║ 1 ║ 7355821748 ║ 1614545331 ║
╚═══════════════════╩════════════╩════════════════╝
现在,我将发出a ROLLBACK
并在回滚发生时查询DMV。以下是一些快照的表:
╔═══════════════════╦════════════╦════════════════╗
║ transaction_count ║ used_bytes ║ reserved_bytes ║
╠═══════════════════╬════════════╬════════════════╣
║ 1 ║ 7393305528 ║ 1573797677 ║
║ 1 ║ 7458767420 ║ 1502635737 ║
║ 1 ║ 7682482356 ║ 1259440979 ║
║ 1 ║ 7803881368 ║ 1127471233 ║
║ ... ║ ... ║ ... ║
╚═══════════════════╩════════════╩════════════════╝
在期间ROLLBACK
,使用的字节增加,保留的字节数减少。这是因为SQL Server正在使用它在撤消事务之前预留的空间。要撤消事务,它必须更改数据,以便将更多数据写入日志。