12 sql-server
我经常看到sql server log之类的语句记录了每一个交易和操作。
但我感到困惑,当交易最终会发生什么滚 回去。
假设一个显式事务有 3 个语句:statement A
, statement B
, statement C
,最后是 a rollback
statement D
。
现在说当执行还没有到达时rollback statement D
,是否statements A through C
会记录到sql server日志中产生的修改?
理解1:
语句 A 到 D 都被记录下来。无论如何,SQL Server 都会记录一切。
理解二:修改只存储在内存中的某处,只有在SQL Server看到commit
语句时才记录到日志中。如果结果是一个rollback
语句,SQL Server 会简单地忽略事务,不会写入日志,因为它没有任何用途。换句话说,SQL Server时,有一个记录净结果之前和之后的交易。
两者似乎都合乎逻辑,至少对我而言,但它们不可能都是对的。谢谢你的帮助。
Joe*_*ish 12
理解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;
Run Code Online (Sandbox Code Playgroud)
我的表:
create table TLOGDEMO (FLUFF VARCHAR(1000));
BEGIN TRANSACTION
Run Code Online (Sandbox Code Playgroud)
查询 A 使用最少的日志记录:
INSERT INTO TLOGDEMO WITH (TABLOCK)
SELECT REPLICATE('A', 1000)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
Run Code Online (Sandbox Code Playgroud)
之后:
???????????????????????????????????????????????????
? transaction_count ? used_bytes ? reserved_bytes ?
???????????????????????????????????????????????????
? 1 ? 24006640 ? 175429451 ?
???????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
查询 B 不使用最少日志记录:
INSERT INTO TLOGDEMO
SELECT REPLICATE('B', 1000)
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
Run Code Online (Sandbox Code Playgroud)
B后:
???????????????????????????????????????????????????
? transaction_count ? used_bytes ? reserved_bytes ?
???????????????????????????????????????????????????
? 1 ? 7352935708 ? 1613986255 ?
???????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
查询 C 更改较少的数据:
INSERT INTO TLOGDEMO
SELECT REPLICATE('C', 1000)
FROM master..spt_values c;
Run Code Online (Sandbox Code Playgroud)
C之后:
???????????????????????????????????????????????????
? transaction_count ? used_bytes ? reserved_bytes ?
???????????????????????????????????????????????????
? 1 ? 7355821748 ? 1614545331 ?
???????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
现在我将ROLLBACK
在回滚发生时发出并查询 DMV。下面是一些快照的表格:
???????????????????????????????????????????????????
? transaction_count ? used_bytes ? reserved_bytes ?
???????????????????????????????????????????????????
? 1 ? 7393305528 ? 1573797677 ?
? 1 ? 7458767420 ? 1502635737 ?
? 1 ? 7682482356 ? 1259440979 ?
? 1 ? 7803881368 ? 1127471233 ?
? ... ? ... ? ... ?
???????????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
期间ROLLBACK
,使用的字节数增加,保留的字节数减少。这是因为 SQL Server 正在使用它之前预留的空间来撤消事务。要撤消事务,它必须更改数据,以便将更多数据写入日志。
对数据库表的修改首先写入日志文件,然后写入表本身,首先在内存中,然后通过称为 的异步过程CHECKPOINT
写入磁盘。这种机制被称为WAL(Write-Ahead Logging),对于所有关系数据库都是通用的。
日志本身首先写入内存(准确地说是日志缓冲区),然后写入磁盘,但在日志写入磁盘之前,不会对数据库表进行任何操作。
这种机制允许在恢复过程中前滚已提交的事务和回滚未提交的事务。关于您的示例,如果之后发生了不好的事情statement C
并且您有一个commit
而不是一个rollback
(您不能提前知道这一点),如果不保存事务中的每一步,RDBMS 将无法以一致的方式恢复数据库方式和交易将不满足D
(持久性)中的ACID
。
当某些操作回滚时,接收净更改的是数据文件(通过CHECKPOINT
),而不是日志文件。
归档时间: |
|
查看次数: |
1435 次 |
最近记录: |