本文基于oracle 19c 做事务提交以及oracle脏数据落盘的相关解读
第一章 相关进程及组件介绍:
1.LGWR:
重做日志条目在系统全局区域 (SGA) 的重做日志缓冲区中生成。LGWR 按顺序将重做日志条目写入重做日志文件。如果数据库具有多重做日志,则 LGWR 会将重做日志条目写入一组重做日志文件。
2.DBWn:
数据库写入器进程 (DBW) 将数据库缓冲区的内容写入数据文件。DBW 进程将数据库缓冲区缓存中修改的缓冲区写入磁盘。
尽管一个数据库写入器进程 (DBW0) 对于大多数系统来说已经足够了,但您可以配置其他进程(DBW1 到 DBW9、DBWa 到 DBWz 以及 BW36 到 BW99),以便在系统大量修改数据时提高写入性能。这些额外的 DBW 进程在单处理器系统上没有用。
3.CKPT:
在特定时间,CKPT 通过向 DBWn 发送消息来启动检查点请求,以开始写入脏缓冲区。在完成单个检查点请求后,CKPT 会更新数据文件头和控制文件以记录最近的检查点。
CKPT 每 3 秒检查一次,查看内存量是否超过初始化参数的值,如果是,则执行“PGA_AGGREGATE_LIMIT”中描述的操作。
4 buffer cache:
数据库缓冲区高速缓存(也称为缓冲区高速缓存)是存储从数据文件中读取的数据块副本的内存区域。
缓冲区是一个主内存地址,缓冲区管理器在其中临时缓存当前或最近使用的数据块。并发连接到数据库实例的所有用户共享对缓冲区缓存的访问权限。
数据库缓冲区缓存的用途
Oracle 数据库使用缓冲区缓存来实现多个目标。
目标包括:
-
优化物理 I/O
数据库更新缓存中的数据块,并将有关更改的元数据存储在重做日志缓冲区中。之后,数据库将重做缓冲区写入联机重做日志,但不会立即将数据块写入数据文件。相反,数据库写入器 (DBW) 在后台执行延迟写入。
COMMIT
-
将经常访问的块保存在缓冲区缓存中,并将不经常访问的块写入磁盘
启用数据库智能闪存缓存(闪存缓存)后,部分缓冲区缓存可以驻留在闪存缓存中。此缓冲区缓存扩展存储在一个或多个闪存设备上,这些设备是使用闪存的固态存储设备。数据库可以通过在闪存中缓存缓冲区而不是从磁盘读取来提高性能。
使用 和 初始化参数配置多个闪存设备。缓冲区缓存跟踪每个设备,并将缓冲区均匀地分配给设备。
DB_FLASH_CACHE_FILE
DB_FLASH_CACHE_SIZE
缓冲区状态
翻译出来就是:
-
闲置
缓冲区可供使用,因为它从未使用过或当前未使用过。这种类型的缓冲区是数据库最容易使用的。
-
干净
此缓冲区以前使用过,现在包含截至某个时间点的块的读取一致性版本。该块包含数据,但“干净”,因此不需要检查点。数据库可以固定块并重用它。
-
脏
缓冲区包含尚未写入磁盘的已修改数据。数据库在重用块之前必须对块进行检查点。
第二章 事务提交
当事务提交时,将发生以下操作:
-
数据库为 .
COMMIT
关联撤消表空间的内部事务表记录了事务已提交的记录。事务的对应唯一SCN被分配并记录在事务表中。
-
日志写入器进程 (LGWR) 进程将重做日志缓冲区中剩余的重做日志条目写入联机重做日志,并将事务 SCN 写入联机重做日志。此原子事件构成事务的提交。
-
Oracle 数据库释放了对行和表的锁。
在未提交事务持有的锁上排队等待的用户可以继续他们的工作。
-
Oracle 数据库删除保存点。
在表 10-1 中,事务中不存在任何保存点,因此不会擦除任何保存点。
sal_update
-
Oracle 数据库执行提交清理。
第三章:redo从缓冲区记录到日志文件
在以下情况下,LGWR 会写入自上次写入以来已复制到缓冲区中的所有重做条目:
-
用户提交事务。
-
发生联机重做日志切换。
-
自 LGWR 上次写信以来已经过去了三秒钟。
-
重做日志缓冲区已满三分之一或包含 1 MB 的缓冲数据。
-
DBW 必须将修改后的缓冲区写入磁盘。
在 DBW 可以写入脏缓冲区之前,数据库必须将与缓冲区更改关联的重做记录(预写协议)写入磁盘。如果 DBW 发现某些重做记录尚未写入,它会向 LGWR 发出信号,将记录写入磁盘,并等待 LGWR 完成,然后再将数据缓冲区写入磁盘。
第四章 脏数据落盘:
脏数据落盘主要由DBWn进程来完成,我们来看下官网的解释:
Process Architecture (oracle.com)
在以下情况下,DBW 进程将脏缓冲区写入磁盘:
1.描缓冲区数的阈值数后找不到干净的缓冲区
当服务器进程在扫描缓冲区数的阈值数后找不到干净的可重用缓冲区时,它会向 DBW 发出写入信号。如果可能,DBW 在执行其他处理时将脏缓冲区异步写入磁盘。
这种情况下由参数_db_block_max_scan_pct决定。_db_block_max_scan_pct表示已经扫描的buffer header的个数占整个LRU链表上buffer header总数的百分比。
当进程在辅助LRU链表和主LRU链表上扫描以查找可以覆盖的buffer header(空闲缓冲区)时,如果已经扫描的buffer header的数量达到一定的限度(由隐藏参数:_db_block_max_scan_pct决定)时,触发DBWR进程。
如果主LRUW链表和辅助LRUW链表上的脏数据块的总数超过一定限度,也将触发DBWR进程。该限度由隐藏参数:_db_large_dirty_queue决定。
查询隐含参数的方法:
-- xxx是你想查找的参数名
SELECT ksppinm, ksppstvl, ksppdesc FROM x$ksppi x, x$ksppcv y WHERE x.indx = y.indx AND ksppinm like '%xxxx%';
2.定期启动
DBW 会定期写入缓冲区以推进检查点,检查点是重做线程中实例恢复开始的位置。检查点的日志位置由缓冲区缓存中最早的脏缓冲区确定。
在许多情况下,DBW 写入的块分散在整个磁盘中。因此,写入往往比 LGWR 执行的顺序写入慢。DBW 尽可能执行多块写入以提高效率。多块写入中写入的块数因操作系统而异。
这个定期启动在ckpt解释中可以找到,每三秒执行一次,检查点会触发DBWn进程。
3.其他(这些是在网上搜集的具体没有验证)
(1)将表空间设置为离线(offline)状态时触发DBWR。
(2)发出命令:alter tablespace … begin backup,从而将表空间设置为热备份状态时触发DBWR。
(3)将表空间设置为只读状态时,触发DBWR。
(4)删除对象时(比如删除某个表)会触发DBWR。
参考:Oracle DBWR,LGWR,CKPT,ARCH 触发条件 - 墨天轮 (modb.pro)