首页 » ORACLE 9i-23c » Oracle Internal BLOCK CHANGE TRACKING

Oracle Internal BLOCK CHANGE TRACKING

Oracle RMAN was able to take incremental backups already in 9i. However, prior to introduction of Oracle 10g block change
tracking (BCT), RMAN had to scan the whole datafile to and filter out the blocks that were not changed since base incremental
backup and overhead or incremental backup was as high as full backup. Oracle 10g new feature, block change tracking,
minimizes number of blocks RMAN needs to read to a strict minimum. With block change tracking enabled RMAN accesses
on disk only blocks that were changed since the latest base incremental backup.

METHODS AND TOOLS USED

X$ tables provide wealth of information about Oracle internals and block change tracking in particular. The tables starting
with X$KRC provide easy access to block change tracking file. Those tables are not simply exposing memory regions. When
selecting from X$KRC tables, block change tracking file is accessed behind the scenes.
Extended SQL tracing using event 10046 was used extensively on foreground sessions as well as background processes such as
DBWx, LGWR, CKPT, and CTWR. It’s worth to mention here that DBWR doesn’t post “db file parallel write” wait event with
Async IO enabled (Oracle 10.2.0.2 on Linux 32 bit). Here is where strace utility comes handy and let researcher see all system
calls. In addition to strace, lsof utility can show open file descriptors for a given process.
To match content of X$KRC tables to the content of block change tracking file, hex dump or hex editor such as bvi is handy.
There are two events reserved for block change tracking tracing – 19774 and 19775. ORADEBUG utility is also very helpful.

Without BCT enabled or in cases when change tracking information cannot be used, RMAN has to read every block in the
datafile during incremental backup. Each block contains last system change number (SCN) of its last modification. The block is
copied only if its SCN is higher or equal to the base backup SCN. To be precise, the backup SCN is a checkpoint SCN that was made right before the backup. Since, usually, only handful of blocks is changed between incremental backups, RMAN  does a lot of useless work reading the blocks not required for backup. Block change tracking provides a way to identify the blocks required for backup without scanning the whole datafile. After that RMAN need only read blocks that are really required for this incremental backup. However, improvement in incremental backup requires some sacrifice during normal database operations. According to Oracle this performance overhead is supposed to be minimal. Nevertheless, by default change tracking is disabled. Oracle 10g introduces a new special background process – Check Tracking Writer (CTWR). This process takes care of logging information about changed blocks in block change tracking file. Lets start with a closer look at this file.

BLOCK CHANGE TRACKING FILE

BCT file is one per database. In case of RAC database, change tracking file is shared amongst all instances. Thus, BCT file
must be on shared storage. By default, BCT file is created in the location defined by parameter DB_CREATE_FILE_DEST
as Oracle managed file (OMF). If parameter is not defined then location is platform specific and, usually, somewhere within
ORACLE_HOME.
You can enable change tracking with the following statement:

SQL> ALTER DATABASE ENABLE BLOCK CHANGE TRACKING;

Alternatively, you can specify location of block change tracking file:

SQL> ALTER DATABASE ENABLE BLOCK CHANGE TRACKING USING FILE '/DB1/bct.ora';

To disable:

SQL> ALTER DATABASE DISABLE BLOCK CHANGE TRACKING;

View V$BLOCK_CHANGE_TRACKING can be queried to find out the status of change tracking in the database.

BCT FILE STRUCTURE

Block change tracking file consists of blocks. Each block has usual Oracle block format except that some of the bytes are not
used, for example, block SCN. Block format code for BCT file is 0x22 in hex which is the second byte of every block. The
first byte is the block type.
Below are the block types of BCT file with respective X$ views providing interface to access information in those blocks:
• 0x29 – BCT file header (X$KRCFH)
• 0x2B – unknown (X$KRCCDE)
• 0x2C – unknown (X$KRCCDS)
• 0x2F – datafile descriptors extent header
• 0x30 – datafile descriptor block (X$KRCFDE)
• 0x33 – bitmap extent header (X$KRCFBH)
• 0x34 – bitmap block (X$KRCBIT)
• 0x36 – probably, empty filler block

The block change tracking file block size is controlled by hidden parameter “_bct_file_block_size”. On Linux platform the BCT block size is by default 512 bytes. The default might be different on other platforms. Block size is stored in BCT file header as we will see later. Figure 1 depicts the sample structure of a block change tracking file and sequence of the blocks. This example is from Linux x86 32 bit platform.Note that the first block (or block zero if you wish) is often skipped just like with datafile but this might depend on the platform. There might be more than one chunk with datafile descriptors if they do not fit into one extent. The bulk of BCT file is occupied by bitmap extents. Bitmaps are the bread and butter of change tracking – bitmap blocks store bit flags for every block (every chunk to be precise) in Oracle database. This is what CTWR updates when blocks are changed and what RMAN reads to determine which blocks it needs to backup.

BCT FILE HEADER

Block type code is 0x29 Information form file header is presented via X$KRCFH table.
Most useful columns of X$KRCFH table:
• FHSWV – software version (10.2.0.2)
• FHCVN – BCT file compatibility version (10.0.0.0)
• FHDBI – DBID
• FHDBN – database name
• FHFSZ – BCT file size in blocks
• FHBSZ – block size in bytes (512)
• EXTBLKS – BCT file extent size in blocks (64 blocks = 32K)
• RSZ_NEWEXTCNT – BCT file increment size in extents ( 320 extents * 64 * 512 bytes = 10 MB)

There are many other columns that are not of so much practical interest or with less obvious purpose. For example,
RESETLOGS SCN, checkpoint SCN, number of version switches, the last allocated extent in BCT file and etc.

EXTENT MAP

The first 2176 blocks (including first unused block) have predefined layout. The rest of the BCT file is allocated in extents. On
Linux I observed extend size 32K or 64 blocks. It can be changed with hidden parameter “_bct_file_extent_size”. The first block
of an extent is extent header and the rest contain the data. View X$KRCEXT exposes extent map. Extent map only indicates
whether extent is used or not. X$KRCEXT view is very simple and there are two interesting columns:
BNO – extent header block number
USED – flag; 0 – unused and 1 – used
Note that there is not information about extent type.

DATAFILE DESCRIPTORS

Oracle allocates the whole extent for datafile descriptors. Header block has type 0x2F and other 63 blocks with type 0x30.
Information about datafile descriptors is externalized via X$KRCFDE fixed table.
One 512 byte block contains 4 datafile descriptors. Consequently, one extent with 63 useful blocks fits up to 252 descriptors.
Datafile descriptor extents are pre-allocated and formatted based on db_files init.ora parameter.
Below are the most important columns:

CTFBNO – change tracking file block number where descriptor is located
• FNO – absolute file number
• CHUNK – chunk size in database blocks (four 8K blocks for 32K chunk)
• CRESCN – datafile creation SCN
• CRETIME – datafile creation time
• CURR_LOWSCN – start SCN for the current version
• CURR_HIGHSCN – end SCN for the current version; for current version it’s set to max possible SCN – 248-1
• CURR_FIRST – header block number of the first bitmap extent for current version
• CURR_LAST – header block number of the first bitmap extent for current version
• CURR_EXTCNT – number of extents in the current version
• CURR_VERCNT – current version number
• CURR_VERTIME – current version time; time when the version started
• HIST_FIRST – header block number of the first bitmap extent for previous version
• HIST_LAST – header block number of the first bitmap extent for previous version
• HIST_EXTCNT – number of extents in the previous version
• HIST_VERCNT – current previous number
• HIST_VERTIME – previous version time
• OLDEST_LOW- start SCN for the oldest bitmap version available in BCT file

Oracle should have called the feature chunk change tracking because it keeps track of changes for the whole chunk and not
individual blocks. Chunk size seems is be default 32K but can be changed with underscore parameter “_bct_chunk_size”.
Consecutive blocks are joined in one chunk and it’s considered dirty if any of the blocks is changed. There are four 8K blocks
in one chunk, eight 4K blocks and one 32K block, for example. This approach, probably, simplifies implementation and
change tracking file sizing doesn’t depend on datafile block size. 32K seems to be chosen because this is the smallest chunk to
fit maximum Oracle block size on all platforms. It could be that on platforms with max block size less than 32, Oracle tracks
changes in smaller chunks, i.e. with higher granularity. Would be interesting to try setting chunk size to 16K and create
tablespace with 32K block size – interesting what error Oracle would throw.

BITMAP EXTENTS

Bitmap extent associated with a single datafile. One datafile has at least one bitmap extent for each bitmap version stored.
The first block is a bitmap extent header. Other 63 blocks contain bitmap. Each bit corresponds to a datafile chunk. When
chunk is not changes for particular version – the bit is 0. If any of the blocks in the chunk is changed, the bit is set to 1. So far
I mentioned bitmap version several times so it’s good place to describe it.

BITMAP VERSIONS

Oracle tracks which blocks (actually, chunks) are changed between two consecutive incremental backups of a datafile and not
only since the last backup. There are separate bitmaps covering each period between incremental backups. This timeframe and
associated bitmaps are called versions.

Every backup has checkpoint SCN associated with it. This is the SCN of the last checkpoint before the backup. Every change
tracking bitmap version has start SCN (or low SCN), which is equal to a checkpoint SCN of the previous backup. Every
version except current has end SCN (or high SCN) which is the checkpoint SCN of the next incremental backup. Current
version has end SCN set to maximum possible SCN value which is 248-1. Versions are associated with datafile and each
datafile has its own set of version even though they might be close to each other in terms of low and high SCN’s.
Every version has dedicated bitmaps and bitmap extents. We can now refine our understanding of bitmap – bits associated
with blocks that were changed between version’s low and high SCN’s are set to 1. Otherwise, they are zeroes.
Number of versions to keep is 8 by default and can be changed by hidden parameter “_bct_bitmaps_per_file”.
BITMAP EXTENT HEADER
Information from bitmap extent headers is externalized via X$KRCFBH fixed table. Some of its columns are described below:
• CTFBNO – header block number in change tracking file
• FNO – absolute file number of a datafile
• VERCNT – version number for bitmap in this extent
• VERTIME – timestamp when this version was started
• HIST_FIRST, HIST_LAST, HIST_EXTCNT, HIST_VERCNT, HIST_VERTIME – same as in X$KRCFDE
• LOWSCN – start SCN for the version
• HIGH – end SCN for the version
BITMAP BLOCK
Every 512 bytes block provides 488 bytes for bitmaps which represent 3904 bits and can, therefore, cover 3904 chunks. Recall that every chunk is 32K. One block can track changes for 122 MB of a datafile (3904 * 32K). The whole extent contains 63 bitmap blocks and covers up to 7686 MB of one datafile. Note that this is only for one version. If file is resized and doesn’t fit into existing number of extents, additional extents are allocated.
Bitmaps are externalized via X$KRCBIT fixed table. This X$ table contains row for every bit that is set to 1 and nothing for bits set to 0. This makes sense as only dirty chunks are of interests for backups. In other words, each row in X$KRCBIT represents a dirty chunk in one of the version.
X$KRCBIT has the following columns:
• CTFBNO – block number of extent header (X$KRCFBH)
• FNO – absolute file number of a datafile (X$KRCFBH)
• VERCNT – version number (X$KRCFBH)
• VERTIME – timestamp when this version was started (X$KRCFBH)
• BNO – first block number of a chunk in the datafile
• BCT – chunks size in datafile blocks (X$KRCFDE.CHUNK)
All the columns are carried over from the extent header or the datafile descriptor except the first block number of a chunk
that is inferred from bit offset.
BCT FILE SIZING
Minimal file size is about 11MB – 2176 initial blocks (1088K) + 320 extents (32K * 320 = 10 MB). 10 MB seems to be predefined increment for BCT file resizing. Out of those 320 extents, one is reserved for X$KRCCDR structure and at least one is reserved for datafile descriptors. Recall that one extent covers 252 files and they are pre-allocated based in init.ora parameter db_files. Thus, assuming that 8 versions for each datafile are kept, 318 extents can cover up to: 318 extents * 7686 MB / 8 version = 300 GB.
Note that in this case maximum number of existing datafiles can be up to: 318 extents / 8 version = 39 datafiles.

In real life, some datafiles are just few hundred megabytes and others sized in tens of megabytes so there is no simple formula
to fit all cases. Here is the complete statement that can be used to predict maximum BCT file size based in the current
database when all datafiles backed up with incremental backup at least 7 times:

SELECT((
(SELECT SUM(ceil(bytes /(7686 * 1024 * 1024))) * 8 bitmap_ext
FROM v$datafile) +
(SELECT ceil(VALUE / 252) file_descr_ext
FROM v$parameter
WHERE name = 'db_files') + 1)
* 32 + 1088) / 1024 bct_file_size_mb
FROM dual;

The statement is valid only for single instance. In RAC, every instance will use its own bitmap extents so number of bitmat extents should be multiplied by the number of RAC instance.

CHANGING BLOCKS
As I mentioned already, changes are tracked for 32K chunks of datafile so any block change in the chunk will render it dirty and bit must be set to 1. If the chunk was already dirty than nothing will change in the BCT file. Basically, if previous block SCN is more than corresponding to the datafile X$KRCFDE.CURR_LOWSCN.

DATAFILE INCREMENTAL BACKUP
When RMAN starts incremental backup of a datafile, it needs to create new version in change tracking file.
Current bitmap is marked as historical – XFLAG column of X$KRCFBH (bitmap headers) is set to 3 and HIGH column is set to the checkpoint SCN. Purge bitmaps that are older than 8 versions.
New extents are allocated and formatted. Bitmap extent header block is formatted but no version specific information is written. I.e.  querying X$KRCFBH we won’t see columns VERCNT, VERTIME, LOW, HIGH and etc. filled. This is because ofversion optimization – if blocks in datafile haven’t been changed between two incremental backup then new version is notcreated. Thus, version attributes are updated only when chunks are first marked as dirty.
Datafile descriptor is updated (X$KRCFDE) – attributes of current version and previous version are filled (CURR_% andHIST_% columns).
When some a chunk needs to be marked dirty for the first time after incremental backup, version information in bitmap extent
headers (X$KRCFBH) is initialized – XFLAGS is set to 2, CURR_VERCNT and CURR_VERTIME filled from datafile
descriptor. If file had no changes since last incremental backup – nothing is written to the bitmap.
There is no difference in handling different backup levels. Version is created in the same way whether its level 0, level 1 or
level 4 backup. By the way, it seems that Oracle 10g documentation officially mentions only support for levels 0 and 1.

PREDICT NUMBER OF BLOCKS READ AND BACKUP SIZE
Based on the bitmap content (X$KRCBIT) we can predict how many 32K chunks RMAN would read if incremental backup starts now. However, precise backup size prediction is only possible if database block size is 32K. Otherwise, a 32K chunk consists of multiple database blocks (2, 4, 8 or 16 depending on the block size). It’s quite possible that only one 8K block out of 4 in a chunk is changed. In this case RMAN will read the whole chunk but it needs to copy only one changed block. RMAN still can filter out blocks unchanged since last backup SCN based on block SCN just like it does for every block in case change tracking is not enabled.
The query below can be used to calculate how many kilobytes will be read by RMAN to backup datafile 7 based on last level 1
incremental backup (i.e. incremental level 1 or incremental cumulative level 2):

SELECT count(distinct bno) * 32
FROM x$krcbit b
WHERE b.fno = 7 AND b.vercnt >=
(SELECT MIN(ver) FROM
(SELECT curr_vercnt ver, curr_highscn high, curr_lowscn low
FROM x$krcfde WHERE fno = 7
UNION ALL
SELECT vercnt ver, high, low
FROM x$krcfbh WHERE fno = 7)
WHERE (SELECT MAX(bd.checkpoint_change#)
FROM v$backup_datafile bd
WHERE bd.file# = 7
AND bd.incremental_level <= 1) between low and high);

Running incremental backups for a while it’s possible to collect historical ration between number of blocks read and number and size of the backup. This would as well account for compression. Note that the query above is just an example and it has the following limitations:
• Chunk size is hard coded to 32K (could it vary on different platforms?)
• First block overhead is not accounted for
• No special case when required bitmap version is not available (purged) and the whole datafile must be read
• No case with backup optimization for level 0 (v$datafile_backup.used_optimization)
• No case when no data blocks in datafile is changed (no bitmap version but the first block must be backed up anyway)
• Only single datafile
• No accounting for unavailable base incremental backup

CHANGE TRACKING INSIDE ORACLE INSTANCE

There is a new special process in Oracle 10g – Change Tracking WRiter (CTWR). As name suggests the job of this process is to write to the block change tracking file. In normal Oracle operations there is no other process that is writing to it. RMAN shadow process reads from as well as writes to the change tracking file during incremental backups. Any process in Oracle can read from change tracking file. When user session queries X$KRC% views, it access BCT file behind the scenes. Shadow process itself accesses CTWR file without communications to CTWR process.
WHO DOES WHAT WHEN BLOCKS ARE CHANGED
Let’s see what happens when processes change blocks.
Every change to the datafile blocks generates redo entry. The process first produces change vector and than this change vector is applied to the block. The change is not applied directly to the block on disk except for direct path writes. The block is first loaded into buffer cache in SGA and then change vector is applied changing the block content. The block in the buffer cache is now considered dirty and later one of the Database WRiter processes (DBWx) will flash it to disk.
Neither of these processes is writing to the change tracking file to mark chunks in the bitmaps as dirty. This is the job of Checkpointer process (CTWR) but how does it know which blocks are changed? The process that updates the block in buffer cache is responsible for passing information to the CTWR about which blocks were changed. At the time the process puts redo entry in the log buffer, it also updates special buffer in the SGA that is used by change tracing writer process later to update the bitmaps. The mechanism of asynchronous updates to the BCT file is somewhat similar to log buffer but not entirely the same. It also doesn’t require flushing pending changes to the BCT file on commits so foreground processes won’t wait on something similar to “log file sync”.
When does CTWR update the BCT file? This happens usually during checkpoint. CKPT process signals to CTWR process to flush pending changes to the BCT file. CKPT is waiting for confirmation that CTWR received the instruction. However, CTWR doesn’t update bitmaps to the BCT file immediately after the signal from CKPT. Instead, it posts back to the CKPT.
As soon as CKPT gets the signal from CTWR, it updates datafile headers and controlfile so checkpoint is completed. CTWR in the meantime proceeds with updating bitmaps in the block change tracking file.
What happens with direct path writes when blocks are updated by shadow processes and written directly on disk? The process is similar. Direct path writes still generate some redo – block invalidations. When these redo entries are written to the log buffer, information is written to the change tracking buffer in SGA and CTWR process will update the bitmaps in BCT file later during the next “CTWR heartbeat” or checkpoint.
WHO DOES WHAT DURING RMAN INCREMENTAL BACKUP
When incremental datafile backup is started, RMAN shadow process in Oracle instance reads from the BCT file and then updates the BCT file header as well the block 2176 exposed via X$KRCCDR fixed table. The next step for RMAN is to signal to the CTWR process that new version needs to be created. At this point RMAN waits for CTWR to finish its business. CTWR creates the new version including allocation of new extents and purging old bitmaps as needed. After that, CTWR posts back to the RMAN shadow process. RMAN shadow process can now read all required past bitmaps and identify which chunks are required for backup. Finally, RMAN gets to its main part – reading dirty chunks and writing changed blocks to the backup piece.

CTWR WAIT EVENTS
CTWR process performs updates to the block 18 of the BCT file about every 20-60 seconds – I call it “CTWR heartbeat”.
During this heartbeat CTWR reads and writes block 18 posting sequentially two short wait events – “change tracking file synchronous read” and “change tracking file synchronous write”. When updating the BCT file, CTWR process also performs some IO against controlfile (“control file sequential read” and “control file parallel write”). Reads and writes to the BCT file itself are instrumented with “change tracking file synchronous read” and “change tracking file synchronous write”. However, updates of the bitmap blocks are NOT instrumented.

Several new enqueues related to block change tracking mechanism name like ‘enq: CT%’
HIDDEN PARAMETERS
• _bct_public_dba_buffer_size – total size of all public change tracking dba buffers, in
• _bct_initial_private_dba_buffer_size – initial number of entries in the private change tracking dba buffers

_bct_bitmaps_per_file – number of bitmaps to store for each datafile
• _bct_file_block_size – block size of change tracking file, in bytes
• _bct_file_extent_size – extent size of change tracking file, in bytes
• _bct_chunk_size – change tracking datafile chunk size, in bytes
• _bct_crash_reserve_size – change tracking reserved crash recovery SGA space, in bytes
• _bct_buffer_allocation_size – size of one change tracking buffer allocation, in bytes
• _bct_buffer_allocation_max – maximum size of all change tracking buffer allocations, in bytes
• _bct_buffer_allocation_min_extents – mininum number of extents to allocate per buffer allocation
• _bct_fixtab_file – change tracking file for fixed tables

There is a hidden parameter _bct_bitmaps_per_file set to 8 by default but no officially supported way to change number of versions.

BCT FILE corruption

if the BCT file gets corrupted due to whatever reason (bug, media corruption, human factor), it can be easily recreated online by disabling and re-enabling block change tracking. Again, don’t forget that all versioning information is lost in this case and next incremental backup will have to scan all blocks.

 

I’m going to start with a simple example.
First I’m going to turn on block change tracking, and then check the File# for my database files.

SQL> alter database enable block change tracking using file '/home/oracle/app/oracle/oradata/BSG18/bct.dbf';

SQL>
TABLESPACE_NAME                   FILE_ID
------------------------------ ----------
USERS                                   7
UNDOTBS1                                4
SYSTEM                                  1
SYSAUX                                  3


I am going to use 2 internal structures to walk through the BCT information. X$KRCFH - This structure contains the lowscn of the BCT file.  It is used by RMAN to determine                       the beginning SCN of the BCT file.  If no changes have been captured for a datafile,                       then RMAN knows at which point it can make that assumption. X$KRCFBH - This structure contains the versions of block changes available to use for backups.                          This structure contains a row for each datafile, and each version.                          This row points to a bitmap containing the block changes associated with the version.                           The key columns I am interested in to explain how it works are                                 FNO          - File number                                 VERCNT - Version number identifying the change records.                                                     This starts at 1 and increases over the life of the BCT file.                                  LOW        - Low SCN of the block changes. It is 0 for the first record                                                      indicating that it not complete                                  HIGH        - High SCN of the block changes. The last SCN number                                                       identifying the block changes. I am going to look the internal structure X$KRCFBH to view what's in the block change tracking.
select (select tablespace_name from dba_data_files where file_id=fno) tablespace_name,vercnt,to_char(vertime,'mm/dd/yy hh24:mi:ss') vertime,low, high from x$krcfbh
   where fno in (select file_id from dba_data_files);
SQL> SQL>   2
TABLESPACE     VERCNT VERTIME                  LOW       HIGH
---------- ---------- ----------------- ---------- ----------
SYSTEM              1 07/29/19 09:21:17          0          0
SYSAUX              1 07/29/19 09:21:18          0          0
UNDOTBS1            1 07/29/19 09:21:18          0          0
USERS               1 07/29/19 09:21:18          0          0

 I can see that there are entries for all my tablespaces, with a "version count" of 1 and low/high time of 0.  This is telling me that that no backups have been executed yet usingthe BCT. I am also going to look at X$KRCFH to see what the starting SCN is for the BCT file.
select lowscn from X$KRCFH;

LOWSCN
----------
8361930
Now I am going to execute a full backup and see what happens.

TABLESPACE     VERCNT VERTIME                  LOW       HIGH
---------- ---------- ----------------- ---------- ----------
SYSTEM              1 07/29/19 09:21:17          0    8362001
SYSAUX              1 07/29/19 09:21:18          0    8362001
UNDOTBS1            1 07/29/19 09:21:18          0    8362001
USERS               1 07/29/19 09:21:18          0    8362001


You can see that the high SCN set to 8362001.
Now I am going to look at the RMAN backup (USERS tablespace) to see what the Checkpoint SCN number was for the backup.

  File LV Type Ckp SCN    Ckp Time          Abs Fuz SCN Sparse Name
  ---- -- ---- ---------- ----------------- ----------- ------ ----
  7    0  Incr 8362002    07/29/19 09:46:59              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_users_fz01zl49_.dbf

Ahhh.. Now I can see how it fits together. The high SCN for the BCT file is SCN number right before the checkpoint taken with the backup. Now let's execute an incremental backup and see what happens.
TABLESPACE     VERCNT VERTIME                  LOW       HIGH
---------- ---------- ----------------- ---------- ----------
SYSAUX              1 07/29/19 09:21:18          0    8362001
SYSTEM              1 07/29/19 09:21:17          0    8362001
UNDOTBS1            1 07/29/19 09:21:18          0    8362001
USERS               1 07/29/19 09:21:18          0    8362001
SYSAUX              2 07/29/19 09:46:59    8362001    8363961
SYSTEM              2 07/29/19 09:46:59    8362001    8363961
UNDOTBS1            2 07/29/19 09:46:59    8362001    8363961

1    0  Incr 8362002    07/29/19 09:46:59              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf
1    1  Incr 8363962    07/29/19 10:04:00              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf
  
 By looking at the SYSTEM tablespace (file 1) I can see exactly what is happening with the BCT file. The first version marks the starting SCN prior to the first backup after creating the file. The second version marks the checkpoint SCN of the first backup (low), and the SCN prior to the second backup(high). These marks, LOW/HIGH SCN, can be used to identify the blocks that changed between the backups. Now I am going to perform a few more incremental backups with a few changes to the USERS tablespace and see what happens to the SYSTEM and USERS tablespaces versions. First here is my query. col tablespace_name format a10 select (select tablespace_name from dba_data_files where file_id=fno) tablespace_name,vercnt,to_char(vertime,'mm/dd/yy hh24:mi:ss') vertime,low, high from x$krcfbh    where fno in (select file_id from dba_data_files)     order by 1,2;
Now let’s see what what my backups look for File 1 (SYSTEM tablespace).
List of Backup Sets
===================
  File LV Type Ckp SCN    Ckp Time          Abs Fuz SCN Sparse Name
  ---- -- ---- ---------- ----------------- ----------- ------ ----
  1    0  Incr 8362002    07/29/19 09:46:59              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf
  1    1  Incr 8363962    07/29/19 10:04:00              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf
  1    1  Incr 8364371    07/29/19 10:13:21              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf
  1    1  Incr 8364482    07/29/19 10:15:19              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf
  1    1  Incr 8364637    07/29/19 10:16:38              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf
  1    1  Incr 8365075    07/29/19 10:26:23              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf
  1    1  Incr 8365373    07/29/19 10:29:13              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf
  1    1  Incr 8365578    07/29/19 10:30:21              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf
  1    1  Incr 8365763    07/29/19 10:30:58              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_system_fz01xnqo_.dbf

Let’s see what my backups look like for File 7 (USERS tablespace)

List of Backup Sets
===================
  File LV Type Ckp SCN    Ckp Time          Abs Fuz SCN Sparse Name
  ---- -- ---- ---------- ----------------- ----------- ------ ----
    7    0  Incr 8362002    07/29/19 09:46:59              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_users_fz01zl49_.dbf
    7    1  Incr 8363962    07/29/19 10:04:00              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_users_fz01zl49_.dbf
    7    1  Incr 8364371    07/29/19 10:13:21              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_users_fz01zl49_.dbf
    7    1  Incr 8364482    07/29/19 10:15:19              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_users_fz01zl49_.dbf
    7    1  Incr 8364637    07/29/19 10:16:38              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_users_fz01zl49_.dbf
    7    1  Incr 8365075    07/29/19 10:26:23              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_users_fz01zl49_.dbf
    7    1  Incr 8365373    07/29/19 10:29:13              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_users_fz01zl49_.dbf
    7    1  Incr 8365578    07/29/19 10:30:21              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_users_fz01zl49_.dbf
    7    1  Incr 8365763    07/29/19 10:30:58              NO    /home/oracle/app/oracle/oradata/BSG/datafile/o1_mf_users_fz01zl49_.dbf

 My backups for both of these match. They have the same Ckp SCN. Notice that I performed an Incremental level 0 backup, and then 8 Incremental level 1 backups. I actually performed both differential backups and cumulative backups but it didn't matter. Now let's look at the block change tracking file for these 2 tablespaces (system and users)
TABLESPACE     VERCNT VERTIME                  LOW       HIGH
---------- ---------- ----------------- ---------- ----------
SYSTEM              3 07/29/19 10:04:00    8363961    8364370
SYSTEM              4 07/29/19 10:13:21    8364370    8364481
SYSTEM              5 07/29/19 10:15:19    8364481    8364636
SYSTEM              6 07/29/19 10:16:38    8364636    8365074
SYSTEM              7 07/29/19 10:26:23    8365074    8365372
SYSTEM              8 07/29/19 10:29:13    8365372    8365577
SYSTEM              9 07/29/19 10:30:20    8365577    8365762
USERS               1 07/29/19 09:21:18          0    8362001
USERS               2 07/29/19 09:46:59    8362001    8364481
USERS               3 07/29/19 10:15:19    8364481    8364636

Very interesting.. Since I only made few changes to the users tablespace it has 3 versions, the oldest of which is the full backup.
The system tablespace has gone over 7 versions and it no longer has the original version from the level 0 backup.
Now let’s see if it used the BCT files for the backups.

     FILE# Creation Time     INCREMENTAL_LEVEL INCREMENTAL_CHANGE# CHECKPOINT_CHANGE# USED BCT
---------- ----------------- ----------------- ------------------- ------------------ ---
         1 07/29/19 09:47:24                 0                   0            8362002 YES
         1 07/29/19 10:04:02                 1             8362002            8363962 YES
         1 07/29/19 10:13:21                 1             8363962            8364371 YES
         1 07/29/19 10:15:19                 1             8364371            8364482 YES
         1 07/29/19 10:16:38                 1             8364482            8364637 YES
         1 07/29/19 10:26:24                 1             8364637            8365075 YES
         1 07/29/19 10:29:14                 1             8362002            8365373 YES
         1 07/29/19 10:30:22                 1             8362002            8365578 YES
         1 07/29/19 10:31:10                 1             8362002            8365763 NO

         7 07/29/19 09:47:00                 0                   0            8362002 YES
         7 07/29/19 10:04:02                 1             8362002            8363962 YES
         7 07/29/19 10:13:21                 1             8364300            8364371 YES
         7 07/29/19 10:15:19                 1             8364371            8364482 YES
         7 07/29/19 10:16:38                 1             8364482            8364637 YES
         7 07/29/19 10:26:24                 1             8364637            8365075 YES
         7 07/29/19 10:29:14                 1             8362002            8365373 YES
         7 07/29/19 10:30:22                 1             8362002            8365578 YES
         7 07/29/19 10:30:59                 1             8362002            8365763 YES

WOW…  Notice that the system tablespace (FILE #1) could not use the BCT file for the last backup, but the backup of the user tablespace (FILE #7) could because there were no changes between a few of the backups.

I also noticed the creation time of the RMAN backup, and the creation time of the BCT file record.  The new BCT file record (if changes occured) is created BEFORE the backup begins.

Finally, I can also see that the high SCN for users, 8364636,is older than the high SCN for system.

I am going to change users, and perform an incremental to see what happens to the LOW/HIGH scn in the next version.

TABLESPACE     VERCNT VERTIME                  LOW       HIGH
---------- ---------- ----------------- ---------- ----------
USERS               1 07/29/19 09:21:18          0    8362001
USERS               2 07/29/19 09:46:59    8362001    8364481
USERS               3 07/29/19 10:15:19    8364481    8364636
USERS               4 07/29/19 10:16:38    8364636    8366975

After the backup, there is no gap in the SCN numbers.  It created a new version that contained the changes between the previous version HIGH and the SCN of the incremental backup.

So what have we learned about the BCT ?

  1. The BCT has a structure that contains the starting SCN of changes captured.
  2. The BCT file creates version records associated with block changes before the backup begins.
  3. If no BCT changes are captured for a datafile, it is assumed that no changes occured since the starting SCN of the BCT file.
  4. The BCT file keeps a bit map of changes between 2 SCN numbers
  5. The BCT file keeps changes on a datafile level.
  6. If a datafile didn’t change between backups, it doesn’t create a new record in the BCT file.  It doesn’t matter if the backup is an incremental or full backup.
  7. By default 7 versions are kept for EACH DATAFILE. After 7 days of backups, some datafiles may still use the BCT if they haven’t changed.

References

Alex Gorbachev wrote a great paper and MOS note explaining it all.  ORACLE 10G BLOCK CHANGE TRACKING INSIDE OUT (Doc ID 1528510.1)

 

打赏

对不起,这篇文章暂时关闭评论。