sec*_*age 5 sql-server transaction transaction-log
我是 SQL Server 的初学者,只是关于事务的一些问题。我的课本上说:
检查点是一种周期性操作,它强制将当前使用的数据库的所有脏页写入磁盘
我很困惑,检查点是否将所有脏页写入日志文件 .ldf?
假设我们写了一些代码:
BEGIN TRAN T1;
UPDATE table1
SET postcode = '9000'
WHERE CustomerID = 1;
...
...
COMMIT TRAN T1;
Run Code Online (Sandbox Code Playgroud)
因此,到执行“提交”时,table1 中的更新记录是否仍在缓存中并等待检查点将更新记录写入日志文件?将更新的记录写入磁盘(日志文件)后,如何将更新的记录写入到 mdf 文件中的真实物理页面?
我们可以将数据存储视为已发生的所有事件的列表insert row 1; insert row 2; update row 2; delete row 1
。为了找到当前值,我们只需相互重播所有事件,最终的结果就是答案。用当前的说法,这称为事件溯源。
然而,这也存在一些问题。性能是显而易见的,因为每次需要一个值时,都必须重新处理整个日志。
由于历史记录一旦记录就不会改变,因此一个明显的优化是在某个时间点拍摄快照并总结截至该点的所有事件。现在,可以通过此摘要以及自计算快照以来发生的小得多的事件集来回答查询。我们甚至可以保留这些摘要,以避免在启动时读取整个事件流。
此外,每个事件到达时都可以写入此摘要中,因此查询不需要读取事件流。实际上,这就是数据库服务器的工作方式。
在受控关闭时,这些摘要可以干净地保留下来,准备在启动时读取,并且所有值都是一致的。但是,如果系统崩溃或断电等不受控制的关闭怎么办?我们如何处理中断发生时尚未提交的事务?有些硬件太小,无法在内存中保存所有摘要,因此某些部分必须在磁盘上和磁盘上进行混洗。如何保持所有部件的一致性,无论其当前位置和交易状态如何?
这些问题有多种解决方案。一种是 SQL Server遵循的 Aries 协议。这将事件与摘要分开。事件进入日志文件(SQL Server 中的 ldf),摘要(即表)进入数据文件 (mdf)。日志记录在处理 SQL 语句时同步写入。根据系统的需要,表会偶尔异步写入。将表保存到磁盘称为检查点。何时处理 SQL 语句或提交事务与何时处理检查点之间没有直接关系。检查点是由后台系统任务写入的。我们经常决定检查点频率以满足系统的恢复时间目标(RTO)。
重要的是,即使表包含由尚未提交的事务写入的值,也可以对表进行检查点。Aries 在日志中存储了足够的信息来正确识别这种情况并从中恢复。
在白羊座下,数据的逻辑状态和物理状态是分开的。锁定一行是一个逻辑操作;保存该行的页可能在内存中,也可能不在内存中。提交事务是一个逻辑操作;该事务涉及的页面不需要立即持久化,或者可能已经被持久化。
当数据更改时,旧值和新值以及一些元数据将写入日志文件并刷新到磁盘。此写入是同步的。一旦这一点被确认,就会有一个永久的更改记录,可以在崩溃后进行检查,并用于使系统恢复到一致的状态。只有在日志被确认后,更改才会应用到数据页。这就是为什么它被称为预写日志记录。
每个事务的开始和结束也记录在日志中。事务可以启动,因为客户端明确请求事务(BEGIN TRANSACTION)。如果不存在显式事务,系统将启动自己的事务以确保每个 SQL 语句的原子性(ACID 中的“A”)。当事务提交时,仅记录该事实的日志记录保证被持久化。保存新写入值的数据页可能仅位于内存中,也可能已设置检查点。对于白羊座来说,情况如何并不重要。
恢复时,系统可以读取日志,查找最后一个检查点,删除未提交事务所做的更改并应用已提交事务所做的更改。
对于更新客户邮政编码的具体示例,我们假设有两个匹配的行。日志文件最终看起来有点像这样(在我编写的伪代码中)。
lsn:12345; begin transaction 1;
lsn:24680; transaction 1; object: table1; row:654: column: postcode; old: '3000'; new: '9000'
lsn:35791; transaction 1; object: table1; row:357: column: postcode; old: '3002'; new: '9000'
lsn:45678; commit transaction 1;
Run Code Online (Sandbox Code Playgroud)
当然,如果您在 ldf 上运行十六进制编辑器,它看起来不会像这样,但它说明了这一点。“LSN”是日志序列号,Aries 使用它来将数据页与日志事件相关联。其他用户的日志记录将与您的日志记录交错。我已经通过在 LSN 之间留出较大间隙来表明这一点。
表检查点日志记录可以出现在我所显示的内容之前、之间或之后,或者根本不出现。这对协议来说并不重要。
Aries 协议概念简单,但必须适应许多极端情况,这使得实现起来很复杂。有许多在线资源可以对其进行解释。我喜欢卡内基梅隆大学一位教授的这篇文章(YouTube )和这篇文章。
最近,SQL Server 引入了一种称为加速数据库恢复的新协议。它可以将恢复时间从几分钟缩短到几毫秒。
感谢@DanGuzman 在这方面的工作。
归档时间: |
|
查看次数: |
182 次 |
最近记录: |