Oracle Database

Prepare Oracle Database 19c,26ai for new time zones of British Columbia , Alberta and Manitoba

Photo by Luis Cortes on Unsplash

Problem Statement

British Columbia , Alberta and Manitoba are Canadian provinces which are adopting permanent daylight saving time starting November 1, 2026, ending seasonal clock changes. For an Oracle DBA this means applying a new time zone patch to the database be it 19c or 26ai . Its very rare to find resources on how to apply a timezone patch hence writing this blog for readers to get an idea around it.

1st thing to remember is the timezone patch that covers all these provinces is DSTv47 , read this article for accurate details KB933005 . This article highlights the need to apply RDBMS DSTv47 PATCH 40063528 and OJVM DSTv47 PATCH 40063583 to all supported versions of oracle.

Solution in a nutshell

If you are patching a 19c oracle home , you can apply below 3 patches in the same sequence , else for 26ai homes you can skip the 1st patch

Patch 27605010: DST UPGRADE SLOW (BEGIN_UPGRADE AND UPGRADE_DATABASE) EVEN WITH PATCH 19704999 (Only for 19c Homes)

Patch 40063528: RDBMS - DSTV47 UPDATE - TZDATA2026D & TZDATA2026E

Patch 40063583: DSTV47 UPDATE - TZDATA2026D & TZDATA2026E - NEED OJVM FIX

Implementation Steps

Simple glance at the Read Me files for the above would give you the basic steps for each

#Pro Tip: Backup your oracle home and database prior to the activity
$ORACLE_HOME/OPatch/opatch prereq CheckConflictAgainstOHWithDetail -ph ./
$ORACLE_HOME/OPatch/opatch apply

Note : There are some additional steps while applying the ojvm patch 40063583

cd 40063583
opatch apply 
* connect as SYS for non-CDB and for CDB connect to root container CDB$ROOT
SQL>startup
SQL>@?/javavm/admin/fixTZa.sql  
...
...
########################################################              
Bug is in fact present, so this patch is needed              
Proceed by restarting the database and running script              
fixTZb              
########################################################

# Only if you see above message follow below steps #

SQL>shut immediate
SQL>startup upgrade
SQL>@?/javavm/admin/fixTZb.sql    
...
...
########################################################              
Bug is no longer present. Patch succeeded.              
######################################################## 
SQL>shut immediate
SQL>startup

Once all the 3 patches have been applied you need to upgrade the timezone files as well as timezone data based on new time zone file . To achieve this we will be using the DBMS_DST package.

If you are at 19c Home the below steps needs to be run as SYS user . If you are at 26ai home , run the below steps for each container .

Step1:

-- Check the current timezone version
SQL> SELECT * FROM v$timezone_file;
FILENAME                          VERSION               CON_ID
-------------------- -------------------- --------------------
timezlrg_32.dat                        32                    0

SELECT tz_version FROM registry$database;
          TZ_VERSION
--------------------
                  32

COLUMN property_name FORMAT A30
COLUMN property_value FORMAT A20
SELECT property_name, property_value
FROM   database_properties
WHERE  property_name LIKE 'DST_%'
ORDER BY property_name;

PROPERTY_NAME                  PROPERTY_VALUE
------------------------------ --------------------
DST_PRIMARY_TT_VERSION         32
DST_SECONDARY_TT_VERSION       0
DST_UPGRADE_STATE              NONE

-- Check the latest timezone version available from the patch , this must show as 47
SQL>SELECT DBMS_DST.get_latest_timezone_version FROM   dual;  
GET_LATEST_TIMEZONE_VERSION
---------------------------
                         47

-- Start a prepare window
SQL>set timing on;
DECLARE
  l_tz_version PLS_INTEGER;
BEGIN
  l_tz_version := DBMS_DST.get_latest_timezone_version;
  DBMS_OUTPUT.put_line('l_tz_version=' || l_tz_version);
  DBMS_DST.begin_prepare(l_tz_version);
END;
/  
PL/SQL procedure successfully completed.


-- This must show the secondary timezone version as 47 , primary should be lesser than this
COLUMN property_name FORMAT A30
COLUMN property_value FORMAT A20
SELECT property_name, property_value
FROM   database_properties
WHERE  property_name LIKE 'DST_%'
ORDER BY property_name;
PROPERTY_NAME                  PROPERTY_VALUE
------------------------------ --------------------
DST_PRIMARY_TT_VERSION         32
DST_SECONDARY_TT_VERSION       47
DST_UPGRADE_STATE              PREPARE


-- Count(*) for both the tables should be '0' if not truncate them both
select count(*) from sys.dst$affected_tables;
select count(*) from  sys.dst$error_table;


-- Find the tables which will be affected by the new timezone date
SQL>EXEC DBMS_DST.find_affected_tables;

-- Check which tables are affected , if there is any data in sys.dst$error_table check with oracle support
SQL>select * from sys.dst$affected_tables;
SQL>select * from  sys.dst$error_table;

--End the prepare window
SQL>EXEC DBMS_DST.end_prepare;

-- After ending the upgrade state should reflect back to none
SELECT property_name, property_value
FROM   database_properties
WHERE  property_name LIKE 'DST_%'
ORDER BY property_name;  
PROPERTY_NAME                  PROPERTY_VALUE
------------------------------ --------------------
DST_PRIMARY_TT_VERSION         32
DST_SECONDARY_TT_VERSION       0
DST_UPGRADE_STATE              NONE

If you are on a 19c home run Step2 ,skip Step3 and proceed next to Step4

Step2:

SQL>shut immediate 

SQL>startup upgrade

If you are on a 26ai home skip Step2 , proceed to Step3 and Step4 onwards

Step3:

-- For homes above 21c 
SQL> ALTER SYSTEM SET TIMEZONE_VERSION_UPGRADE_ONLINE = TRUE containers=ALL;

-- This means you donot have to restart database in upgrade mode

Step4:

SQL> set timing on
SET SERVEROUTPUT ON
DECLARE
l_failures   PLS_INTEGER;
BEGIN
  DBMS_DST.upgrade_database(l_failures);
  DBMS_OUTPUT.put_line('DBMS_DST.upgrade_database : l_failures=' || l_failures);
SQL>   DBMS_DST.end_upgrade(l_failures);
  DBMS_OUTPUT.put_line('DBMS_DST.end_upgrade : l_failures=' || l_failures);
END;
/

...
...
DBMS_DST.upgrade_database : l_failures=0
An upgrade window has been successfully ended.
DBMS_DST.end_upgrade : l_failures=0

-- It should show the new timezone version
SQL> COLUMN property_name FORMAT A30
COLUMN property_value FORMAT A20
SELECT property_name, property_value
FROM   database_properties
WHERE  property_name LIKE 'DST_%'
ORDER BY property_name;
PROPERTY_NAME                  PROPERTY_VALUE
------------------------------ --------------------
DST_PRIMARY_TT_VERSION         47
DST_SECONDARY_TT_VERSION       0
DST_UPGRADE_STATE              NONE

-- This should show the upgrade_in_progress column as "No" for all the tables , if any table is still in upgrade state contact oracle support
SQL> COLUMN owner FORMAT A30
COLUMN table_name FORMAT A30
SELECT con_id,
       owner,
       table_name,
       upgrade_in_progress
FROM   cdb_tstz_tables
ORDER BY 1,2,3; 

SQL> SELECT * FROM v$timezone_file;

-- compile all the packages
SQL> @?/rdbms/admin/utlrp.sql

-- Check if all the registry components are valid
SQL> SET LINES 1000
COLUMN COMPONENT FORMAT A40
SELECT comp_name AS component, version, status
FROM dba_registry;

For a 19c Home this is it and your database timezone has been upgraded

For a 26ai Home , this step is complete for the root container CDB$ROOT , now switch to your pdb ( SQL> ALTER SESSION SET CONTAINER = MYPRODPDB; ) and rerun all the steps (Step1-> Step3 -> Step4 ) skipping Step2 .

Note :- There are multiple bugs in 19c home for using the DBMS_DST package in various versions , consider checking the oracle knowledge article KB86566 before prcoeeding.

References

Updating the RDBMS DST version in 12c Release 1 (12.1.0.1 and up) using DBMS_DST (KB86566)

Applying the DSTv47 update for the Oracle Database

Upgrade the Database Time Zone File Using the DBMS_DST Package

Leave a Reply