Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
oracle_guard_upgrade [2020/10/16 16:07] – created andonovj | oracle_guard_upgrade [2020/10/16 16:12] (current) – andonovj | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | < | ||
- | #!/bin/sh | ||
- | # Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. | + | Usage |
- | # | + | |
- | # Disclaimer: | + | |
- | # | + | |
- | # EXCEPT WHERE EXPRESSLY PROVIDED OTHERWISE, THE INFORMATION, | + | |
- | # PROVIDED ON AN \"AS IS\" AND \"AS AVAILABLE\" | + | |
- | # ALL WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT | + | |
- | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, | + | |
- | # PURPOSE AND NON-INFRINGEMENT. ORACLE MAKES NO WARRANTY THAT: (A) THE RESULTS | + | |
- | # THAT MAY BE OBTAINED FROM THE USE OF THE SOFTWARE WILL BE ACCURATE OR | + | |
- | # RELIABLE; OR (B) THE INFORMATION, | + | |
- | # EXPECTATIONS. ANY CONTENT, MATERIALS, INFORMATION OR SOFTWARE DOWNLOADED OR | + | |
- | # OTHERWISE OBTAINED IS DONE AT YOUR OWN DISCRETION AND RISK. ORACLE SHALL HAVE | + | |
- | # NO RESPONSIBILITY FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR LOSS OF DATA THAT | + | |
- | # RESULTS FROM THE DOWNLOAD OF ANY CONTENT, MATERIALS, INFORMATION OR SOFTWARE. | + | |
- | # | + | |
- | # ORACLE RESERVES THE RIGHT TO MAKE CHANGES OR UPDATES TO THE SOFTWARE AT ANY | + | |
- | # TIME WITHOUT NOTICE. | + | |
- | # | + | |
- | # Limitation of Liability: | + | |
- | # | + | |
- | # IN NO EVENT SHALL ORACLE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | + | |
- | # SPECIAL OR CONSEQUENTIAL DAMAGES, OR DAMAGES FOR LOSS OF PROFITS, REVENUE, | + | |
- | # DATA OR USE, INCURRED BY YOU OR ANY THIRD PARTY, WHETHER IN AN ACTION IN | + | |
- | # CONTRACT OR TORT, ARISING FROM YOUR ACCESS TO, OR USE OF, THE SOFTWARE. | + | |
- | + | <Code:bash|Usage of the script> | |
- | ############################################################################### | + | ./physru.sh sys |
- | ############ | + | c01n01:1521/c01orcl_DGMGRL.example.com |
- | ############################################################################### | + | c02n01:1521/c02orcl_DGMGRL.example.com c01orcl c02orcl 12.1.0.1.0 |
- | VERSION=0001 | + | </Code> |
- | MAX_RPCOUNT=2000 | + | |
- | PHYSRU_DEBUG=0 | + | |
- | + | ||
- | # Customizable settings (proceed with caution) | + | |
- | LOC_BACKUP_FILES=" | + | |
- | + | ||
- | LOG_PHYSRU_ENABLED=1 | + | |
- | LOG_PHYSRU_FILE=" | + | |
- | LOG_SQL_ERRORS=1 | + | |
- | LOG_SQL_EXETMP=" | + | |
- | LOG_UNSUPP_FILE=" | + | |
- | + | ||
- | LSP_APPLY_LAG=30 | + | |
- | LSP_APPLY_LAG_TIMEOUT=30 | + | |
- | LSP_DICT_LOAD_INTERVAL=10 | + | |
- | LSP_DICT_LOAD_TIMEOUT=30 | + | |
- | LSP_START_TIMEOUT=10 | + | |
- | LSP_START_INTERVAL=5 | + | |
- | + | ||
- | MRP_APPLY_LAG=30 | + | |
- | MRP_APPLY_LAG_TIMEOUT=30 | + | |
- | MRP_REDO_PROG_INTERVAL=15 | + | |
- | MRP_START_INTERVAL=5 | + | |
- | MRP_START_TIMEOUT=10 | + | |
- | MRP_UPGRADE_TIMEOUT=15 | + | |
- | # | + | |
- | RPFX=PRU | + | |
- | + | ||
- | STB_APPLY_LAG_INTERVAL=30 | + | |
- | STB_EOR_INTERVAL=10 | + | |
- | STB_EOR_TIMEOUT=15 | + | |
- | STB_EOR_RESTART_AFTER=5 | + | |
- | STB_VIEW_INIT_INTERVAL=3 | + | |
- | + | ||
- | + | ||
- | + | ||
- | ############################################################################### | + | |
- | # NAME: autopru | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # This is the main entry point of the script. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: tns service name to primary | + | |
- | # $3: tns service name to physical standby | + | |
- | # $4: db_unique_name of primary (or any identifying string) | + | |
- | # $5: db_unique_name of standby (or any identifying string) | + | |
- | # $6: target rdbms version | + | |
- | # | + | |
- | # | + | |
- | # $user $db1tns $db2tns $db1name $db2name $stage $task | + | |
- | # | + | |
- | # RETURN: | + | |
- | # 0: Success 1: Error | + | |
- | # | + | |
- | ############################################################################### | + | |
- | autopru() | + | |
- | { | + | |
- | + | ||
- | # Save tty settings | + | |
- | origstty=`stty -g` | + | |
- | + | ||
- | # Declare signal handler | + | |
- | trap ' | + | |
- | + | ||
- | # We need all 6 parameters | + | |
- | if [ " | + | |
- | display_usage | + | |
- | echo -e " | + | |
- | exit 1 | + | |
- | fi | + | |
- | + | ||
- | # Display Oracle banner | + | |
- | # display_banner | + | |
- | + | ||
- | # Prompt for password | + | |
- | stty -echo | + | |
- | echo " | + | |
- | read passwd | + | |
- | stty $origstty | + | |
- | + | ||
- | # Global variables | + | |
- | user=$1 | + | |
- | db1tns=$2 | + | |
- | db2tns=$3 | + | |
- | db1name=$4 | + | |
- | db2name=$5 | + | |
- | upgver=$6 | + | |
- | stage=0 | + | |
- | task=1 | + | |
- | suppress=0 | + | |
- | suppresst=0 | + | |
- | suppressl=0 | + | |
- | db1iname="" | + | |
- | db2iname="" | + | |
- | db1iid=0 | + | |
- | db2iid=0 | + | |
- | db1version=" | + | |
- | db2version=" | + | |
- | db1ver=" | + | |
- | db2ver=" | + | |
- | sql_out="" | + | |
- | + | ||
- | S0_initialization | + | |
- | while [ " | + | |
- | do | + | |
- | case " | + | |
- | 1) S1_backup;; | + | |
- | 2) S2_physical_to_logical;; | + | |
- | + | ||
- | # | + | |
- | + | ||
- | 3) S3_post_upgrade_validation;; | + | |
- | 4) S4_switchover;; | + | |
- | 5) S5_primary_to_physical;; | + | |
- | + | ||
- | # | + | |
- | + | ||
- | 6) S6_recover_through_upgrade;; | + | |
- | 7) S7_switchback;; | + | |
- | 8) S8_statistics;; | + | |
- | *) break;; | + | |
- | esac | + | |
- | + | ||
- | # Proceed to the next stage | + | |
- | stage=`expr $stage + 1` | + | |
- | task=1 | + | |
- | + | ||
- | done | + | |
- | S9_cleanup | + | |
- | + | ||
- | display_raw " | + | |
- | } | + | |
- | + | ||
- | + | ||
- | ############################################################################### | + | |
- | ############ | + | |
- | ############################################################################### | + | |
- | + | ||
- | + | ||
- | ############################################################################### | + | |
- | # NAME: S0_initialization | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # In this stage we decide if we should start the rolling upgrade from scratch | + | |
- | # or resume where the last invocation was interrupted. | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # prior invocation, this routine will set the stage and task global variables | + | |
- | # so that control is transfered to the appropriate point of execution. | + | |
- | # | + | |
- | # A word about resuming... we achieve this by using guaranteed flashback | + | |
- | # | + | |
- | # is encoded with a stage id and a task id which identifies a block of code | + | |
- | # in this script. | + | |
- | # the most recent restore point to initialize its execution. | + | |
- | # | + | |
- | # with the version number of the authoring script. | + | |
- | # if an executing script has a matching version number. | + | |
- | # | + | |
- | # N.B.: It might seem overkill to bother with version, but I can easily | + | |
- | # | + | |
- | # down a more recent release of the script. | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # $user $passwd $db1tns $db2tns $db1name $db2name $stage $task $VERSION | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | S0_initialization() | + | |
- | { | + | |
- | display_raw "\n### Initialize script to either start over or resume execution" | + | |
- | isready=1 | + | |
- | runningon=0 | + | |
- | + | ||
- | # | + | |
- | # Fetch primary and standby rdbms version | + | |
- | # | + | |
- | display " | + | |
- | + | ||
- | get_rdbms_version $user $passwd $db1tns $db1name | + | |
- | db1version=$l_grv_val | + | |
- | display " | + | |
- | + | ||
- | get_rdbms_version $user $passwd $db2tns $db2name | + | |
- | db2version=$l_grv_val | + | |
- | display " | + | |
- | + | ||
- | # Save short form of database version (assume 2-digit major 1-digit minor) | + | |
- | db1ver=`echo $db1version | cut -d ' | + | |
- | db2ver=`echo $db2version | cut -d ' | + | |
- | + | ||
- | # | + | |
- | # Fetch primary and standby db unique names | + | |
- | # | + | |
- | get_db_unique_name $user $passwd $db1tns $db1name | + | |
- | if [ " | + | |
- | db1name=$l_dun_val | + | |
- | fi | + | |
- | get_db_unique_name $user $passwd $db2tns $db2name | + | |
- | if [ " | + | |
- | db2name=$l_dun_val | + | |
- | fi | + | |
- | + | ||
- | # | + | |
- | # Fetch primary and standby instance names | + | |
- | # | + | |
- | get_instance_name $user $passwd $db1tns $db1name | + | |
- | db1iname=$l_gin_val | + | |
- | + | ||
- | get_instance_name $user $passwd $db2tns $db2name | + | |
- | db2iname=$l_gin_val | + | |
- | + | ||
- | # | + | |
- | # Flashback database must be enabled at both db1 and db2 | + | |
- | # | + | |
- | display " | + | |
- | is_flashback_enabled $user $passwd $db1tns $db1name | + | |
- | if [ " | + | |
- | display " | + | |
- | isready=0 | + | |
- | fi | + | |
- | is_flashback_enabled $user $passwd $db2tns $db2name | + | |
- | if [ " | + | |
- | display " | + | |
- | isready=0 | + | |
- | fi | + | |
- | + | ||
- | # Flashback retention is of sufficient size (is this predictable??? | + | |
- | + | ||
- | # | + | |
- | # Enough free restore point entries available to accommodate our use of them | + | |
- | # | + | |
- | display " | + | |
- | get_flashback_restore_count $user $passwd $db1tns $db1name | + | |
- | if [ " | + | |
- | display " | + | |
- | isready=0 | + | |
- | fi | + | |
- | + | ||
- | get_flashback_restore_count $user $passwd $db2tns $db2name | + | |
- | if [ " | + | |
- | display " | + | |
- | isready=0 | + | |
- | fi | + | |
- | + | ||
- | # | + | |
- | # The Data Guard Broker must be disabled | + | |
- | # | + | |
- | display " | + | |
- | is_dg_enabled $user $passwd $db1tns $db1name | + | |
- | if [ " | + | |
- | display " | + | |
- | isready=0 | + | |
- | fi | + | |
- | is_dg_enabled $user $passwd $db2tns $db2name | + | |
- | if [ " | + | |
- | display " | + | |
- | isready=0 | + | |
- | fi | + | |
- | + | ||
- | # | + | |
- | # Exit now if one or more warnings have been found | + | |
- | # | + | |
- | if [ " | + | |
- | display " | + | |
- | exit 1 | + | |
- | fi | + | |
- | + | ||
- | # | + | |
- | # Check if we are to resume the rolling upgrade from the last invocation. | + | |
- | # any resume state exists, an initial restore point will exist with the script | + | |
- | # version embedded in the name. | + | |
- | # | + | |
- | resuming=1 | + | |
- | display " | + | |
- | get_resume_version $user $passwd $db2tns $db2name | + | |
- | resumever=`echo $l_grv_val | awk ' | + | |
- | scriptver=`echo $VERSION | awk ' | + | |
- | if [ " | + | |
- | if [ " | + | |
- | # | + | |
- | # The script versions do not match. | + | |
- | # upgrade attempt has failed, and the user is now re-attempting the rolling | + | |
- | # upgrade with a new version of this script. | + | |
- | # user must revalidate their setup, and start from scratch. | + | |
- | # | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | prompt " | + | |
- | if [ " | + | |
- | display " | + | |
- | # Set flag to indicate start from scratch | + | |
- | resuming=0 | + | |
- | else | + | |
- | display " | + | |
- | exit | + | |
- | fi | + | |
- | + | ||
- | else | + | |
- | # Fetch the stage and task that was last completed | + | |
- | get_resume_state $user $passwd $db2tns $db2name | + | |
- | resume_stage=`echo $l_grs2_stage | awk ' | + | |
- | resume_task=`echo $l_grs2_task | awk ' | + | |
- | + | ||
- | # If found, the next task is where we want to start | + | |
- | if [ " | + | |
- | display "last completed stage [${resume_stage}-${resume_task}] using script version $l_grv_val" | + | |
- | + | ||
- | # Resuming from other than these two states implies an error had occurred | + | |
- | prompt_user=1 | + | |
- | if [ " | + | |
- | prompt_user=0 | + | |
- | fi | + | |
- | if [ " | + | |
- | prompt_user=0 | + | |
- | fi | + | |
- | + | ||
- | # Prompt user | + | |
- | if [ " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | prompt "Enter your selection" | + | |
- | if [ " | + | |
- | resuming=1 | + | |
- | else | + | |
- | if [ " | + | |
- | resuming=0 | + | |
- | break | + | |
- | else | + | |
- | if [ " | + | |
- | exit | + | |
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | else | + | |
- | # A stage of 0 is possible if the script' | + | |
- | resuming=0 | + | |
- | fi | + | |
- | fi | + | |
- | else | + | |
- | resuming=0 | + | |
- | fi | + | |
- | + | ||
- | # Script will resume at the next task | + | |
- | if [ " | + | |
- | display " | + | |
- | stage=$resume_stage | + | |
- | task=$resume_task | + | |
- | task=`expr $task + 1` | + | |
- | else | + | |
- | # Script will start from scratch | + | |
- | purge_resume_state $user $passwd $db1tns $db1name | + | |
- | purge_resume_state $user $passwd $db2tns $db2name | + | |
- | display " | + | |
- | stage=1 | + | |
- | task=1 | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | + | ||
- | ############################################################################### | + | |
- | # NAME: S1_backup | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # In this stage, we ensure that the user will be able to cleanly recover if | + | |
- | # they wish to abandon the rolling upgrade. | + | |
- | # | + | |
- | # and standby databases. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # $user $passwd $db1tns $db2tns $db1name $db2name $task $VERSION | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | S1_backup() | + | |
- | { | + | |
- | display_stage " | + | |
- | + | ||
- | # | + | |
- | # Step through each task | + | |
- | # | + | |
- | while [ " | + | |
- | do | + | |
- | case " | + | |
- | + | ||
- | 1) # Create initial restore point and backup control files | + | |
- | + | ||
- | # Stop media recovery since we're about to create a restore point | + | |
- | stop_media_recovery $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Create initial restore point on standby | + | |
- | create_restore_point $user $passwd $db2tns $db2name ${RPFX}_0000_${VERSION} | + | |
- | + | ||
- | # Create a backup control file on standby | + | |
- | create_backup_ctlfile $user $passwd $db2tns $db2name ${RPFX}_${VERSION}_${db2name}_f.f | + | |
- | + | ||
- | # Create initial restore point on primary | + | |
- | create_restore_point $user $passwd $db1tns $db1name ${RPFX}_0000_${VERSION} | + | |
- | + | ||
- | # Create a backup control file on primary | + | |
- | create_backup_ctlfile $user $passwd $db1tns $db1name ${RPFX}_${VERSION}_${db1name}_f.f | + | |
- | + | ||
- | # Remind user of these safepoints | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | ;; | + | |
- | + | ||
- | *) break;; | + | |
- | esac | + | |
- | + | ||
- | # Checkpoint our completion of the current task | + | |
- | checkpoint | + | |
- | + | ||
- | # Proceed to next task | + | |
- | task=`expr $task + 1` | + | |
- | done | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: S2_physical_to_logical | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # In this stage the physical standby is converted into a transient logical | + | |
- | # | + | |
- | # | + | |
- | # If found, these datatypes are written to an output log, so the user can | + | |
- | # | + | |
- | # | + | |
- | # The actual conversion into a transient logical is achieved via the | + | |
- | # | + | |
- | # in a special mode responsible which looks specifically for the dictionary. | + | |
- | # The section in the script below which performs this may perform multiple | + | |
- | # | + | |
- | # the possibility that recovery was run by the user beyond the dictionary, | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # $user $passwd $db1tns $db2tns $db1name $db2name $task | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | S2_physical_to_logical() | + | |
- | { | + | |
- | display_stage " | + | |
- | + | ||
- | # | + | |
- | # RAC standbys must be reduced to a single instance for the duration of the | + | |
- | # instantiation. | + | |
- | # | + | |
- | l_s2_hint=" | + | |
- | if [ " | + | |
- | while [ " | + | |
- | do | + | |
- | display " | + | |
- | is_rac_database $user $passwd $db2tns $db2name | + | |
- | if [ " | + | |
- | break | + | |
- | fi | + | |
- | + | ||
- | l_s2_hint=" | + | |
- | display_rac_demote $user $passwd $db2tns $db2name $db2iname " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | prompt "Are you ready to continue?" | + | |
- | if [ " | + | |
- | display " | + | |
- | else | + | |
- | display " | + | |
- | exit | + | |
- | fi | + | |
- | done | + | |
- | fi | + | |
- | + | ||
- | # | + | |
- | # Step through each task | + | |
- | # | + | |
- | while [ " | + | |
- | do | + | |
- | case " | + | |
- | + | ||
- | 1) # Prerequisites | + | |
- | isready=1 | + | |
- | + | ||
- | # db1 should be the primary and db2 should be a physical standby | + | |
- | display " | + | |
- | is_database_role $user $passwd $db1tns $db1name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | is_database_role $user $passwd $db2tns $db2name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | # Physical standby must be mounted | + | |
- | display " | + | |
- | is_open_mode $user $passwd $db2tns $db2name " | + | |
- | if [ " | + | |
- | display " | + | |
- | isready=0; | + | |
- | fi | + | |
- | + | ||
- | # We do not allow maximum protection mode | + | |
- | display " | + | |
- | get_protection_mode $user $passwd $db1tns $db1name | + | |
- | if [ " | + | |
- | display " | + | |
- | isready=0 | + | |
- | fi | + | |
- | + | ||
- | # Exit if any requirements not met | + | |
- | if [ " | + | |
- | display " | + | |
- | exit 1 | + | |
- | fi | + | |
- | + | ||
- | # Check for unsupported datatypes | + | |
- | display " | + | |
- | l_ptl1_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(*) from dba_logstdby_unsupported; | + | |
- | exit;" | + | |
- | sql_exec $user $passwd $db1tns " | + | |
- | chkerr $? " | + | |
- | + | ||
- | # Write out unsupported datatypes | + | |
- | l_ptl1=`echo $sql_out` | + | |
- | if [ " | + | |
- | l_ptl2_sql=" | + | |
- | set pagesize 50000 linesize 165 feedback off verify off heading on echo off tab off | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | set heading on | + | |
- | select * from dba_logstdby_unsupported; | + | |
- | spool off; | + | |
- | exit;" | + | |
- | sql_exec $user $passwd $db1tns " | + | |
- | chkerr $? " | + | |
- | + | ||
- | # Ask permission to continue | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | prompt "Are you ready to proceed with the rolling upgrade?" | + | |
- | if [ " | + | |
- | display " | + | |
- | else | + | |
- | display " | + | |
- | exit | + | |
- | fi | + | |
- | fi | + | |
- | ;; | + | |
- | + | ||
- | 2) # Logical build and recover to logical standby | + | |
- | + | ||
- | # N.B.: We bundle the build and recover together since it's possible a | + | |
- | # | + | |
- | # build marker. | + | |
- | # | + | |
- | # | + | |
- | + | ||
- | is_database_role $user $passwd $db2tns $db2name " | + | |
- | if [ " | + | |
- | + | ||
- | # Stop media recovery in case it was left running | + | |
- | stop_media_recovery $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Start media recovery | + | |
- | start_media_recovery $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Switch logs on the primary | + | |
- | switch_logs $user $passwd $db1tns $db1name | + | |
- | + | ||
- | # Wait for media recovery to catch up to a recent scn | + | |
- | minimize_apply_lag $user $passwd $db1tns $db1name $db2tns $db2name $db2ver $MRP_APPLY_LAG $MRP_APPLY_LAG_TIMEOUT | + | |
- | + | ||
- | # Stop media recovery | + | |
- | stop_media_recovery $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Dump the logminer dictionary | + | |
- | start_logical_build $user $passwd $db1tns $db1name | + | |
- | + | ||
- | # Recover to logical standby | + | |
- | recover_to_logical $user $passwd $db2tns $db2name | + | |
- | fi | + | |
- | ;; | + | |
- | + | ||
- | 3) # Open transient logical standby database | + | |
- | + | ||
- | # N.B.: A bug in v$dataguard_stats apply lag prevents direct open | + | |
- | if [ " | + | |
- | shutdown_database $user $passwd $db2tns $db2name | + | |
- | mount_database $user $passwd $db2tns $db2name | + | |
- | fi | + | |
- | + | ||
- | # Instance must be in mounted mode | + | |
- | is_open_mode $user $passwd $db2tns $db2name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | # Open the transient logical database | + | |
- | open_database $user $passwd $db2tns $db2name | + | |
- | ;; | + | |
- | + | ||
- | 4) # Configure and startup logical standby | + | |
- | + | ||
- | # NOTE: If <task> is assigned a new number from 4, the code in | + | |
- | # | + | |
- | # | + | |
- | # redo, must be modified to consider the new resulting | + | |
- | # | + | |
- | + | ||
- | # Instance must be open read write | + | |
- | is_open_mode $user $passwd $db2tns $db2name "READ WRITE" | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | # Stop logical standby (in case an error left it running) | + | |
- | stop_logical_apply $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Set rolling upgrade parameters | + | |
- | set_rolling_upgrade_params $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Start logical standby | + | |
- | start_logical_apply $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Wait until dictionary load has finished | + | |
- | wait_logical_dictload $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Switch logs on the primary | + | |
- | switch_logs $user $passwd $db1tns $db1name | + | |
- | + | ||
- | # Wait until apply lag is within 5 minutes | + | |
- | minimize_apply_lag $user $passwd $db1tns $db1name $db2tns $db2name $db2ver $LSP_APPLY_LAG $LSP_APPLY_LAG_TIMEOUT | + | |
- | + | ||
- | # Force a checkpoint since we're about to exit | + | |
- | checkpoint | + | |
- | + | ||
- | # Display message that we're ready for them to ugprade. | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | # Display instructions on how to re-enable RAC | + | |
- | display_rac_promote $user $passwd $db2tns $db2name $db2iname " | + | |
- | + | ||
- | exit | + | |
- | ;; | + | |
- | + | ||
- | *) break;; | + | |
- | esac | + | |
- | + | ||
- | # Checkpoint our completion of the current task | + | |
- | checkpoint | + | |
- | + | ||
- | # Proceed to next task | + | |
- | task=`expr $task + 1` | + | |
- | + | ||
- | done | + | |
- | } # S2_physical_to_logical() | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: S3_post_upgrade_validation | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # When this stage is entered, the user has already completed the manual | + | |
- | # | + | |
- | # this stage, the upgraded physical standby is validated to be on the | + | |
- | # newer binary, and no longer upgrading. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | S3_post_upgrade_validation() | + | |
- | { | + | |
- | display_stage " | + | |
- | + | ||
- | # | + | |
- | # Step through each task | + | |
- | # | + | |
- | while [ " | + | |
- | do | + | |
- | case " | + | |
- | 1) # Validation | + | |
- | + | ||
- | # Database is no longer in open migrate mode | + | |
- | is_open_mode $user $passwd $db2tns $db2name "OPEN MIGRATE" | + | |
- | if [ " | + | |
- | fail "$4 must not be in OPEN MIGRATE mode" | + | |
- | fi | + | |
- | display " | + | |
- | + | ||
- | # Database is on correct target version | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | display " | + | |
- | + | ||
- | # Future: EDS trigger deletion | + | |
- | ;; | + | |
- | + | ||
- | *) break;; | + | |
- | esac | + | |
- | + | ||
- | # Checkpoint our completion of the current task | + | |
- | checkpoint | + | |
- | + | ||
- | # Proceed to next task | + | |
- | task=`expr $task + 1` | + | |
- | done | + | |
- | } # S3_post_upgrade_validation | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: S4_switchover | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # In this stage, the primary and upgraded, transient logical standby switch | + | |
- | # | + | |
- | # back and converted into a physical standby which will then recover the | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | S4_switchover() | + | |
- | { | + | |
- | display_stage " | + | |
- | + | ||
- | # | + | |
- | # Step through each task | + | |
- | # | + | |
- | while [ " | + | |
- | do | + | |
- | case " | + | |
- | 1) # Preparing logical standby for switchover | + | |
- | + | ||
- | is_database_role $user $passwd $db1tns $db1name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | is_database_role $user $passwd $db2tns $db2name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | is_open_mode $user $passwd $db1tns $db1name "READ WRITE" | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | is_open_mode $user $passwd $db2tns $db2name "READ WRITE" | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | display " | + | |
- | switch_logs $user $passwd $db1tns $db1name | + | |
- | start_logical_apply $user $passwd $db2tns $db2name | + | |
- | minimize_apply_lag $user $passwd $db1tns $db1name $db2tns $db2name $db2ver $LSP_APPLY_LAG $LSP_APPLY_LAG_TIMEOUT | + | |
- | ;; | + | |
- | + | ||
- | 2) # Switch $db1name to the logical standby role | + | |
- | switch_primary_to_logical $user $passwd $db1tns $db1name | + | |
- | ;; | + | |
- | + | ||
- | 3) # Confirm $db2name has witnessed the role change | + | |
- | wait_standby_eor $user $passwd $db2tns $db2name $db2ver | + | |
- | ;; | + | |
- | + | ||
- | 4) # Switch $db2name to the primary role | + | |
- | switch_logical_to_primary $user $passwd $db2tns $db2name | + | |
- | ;; | + | |
- | + | ||
- | *) break;; | + | |
- | esac | + | |
- | + | ||
- | # Checkpoint our completion of the current task | + | |
- | checkpoint | + | |
- | + | ||
- | # Proceed to next task | + | |
- | task=`expr $task + 1` | + | |
- | done | + | |
- | + | ||
- | } # S4_switchover | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: S5_primary_to_physical | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # In this stage, the former primary (now a logical standby as the result of a | + | |
- | # | + | |
- | # | + | |
- | # up the physical standby using the newer binary. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | S5_primary_to_physical() | + | |
- | { | + | |
- | display_stage " | + | |
- | + | ||
- | # | + | |
- | # db1 must be reduced to a single instance for the conversion to a physical | + | |
- | # | + | |
- | if [ " | + | |
- | is_rac_database $user $passwd $db1tns $db1name | + | |
- | if [ " | + | |
- | while [ " | + | |
- | do | + | |
- | display " | + | |
- | display_rac_demote $user $passwd $db1tns $db1name $db1iname " | + | |
- | if [ " | + | |
- | break | + | |
- | else | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | prompt "Are you ready to continue?" | + | |
- | if [ " | + | |
- | display " | + | |
- | else | + | |
- | display " | + | |
- | exit | + | |
- | fi | + | |
- | fi | + | |
- | done | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | # | + | |
- | # Step through each task | + | |
- | # | + | |
- | l_s5_db1israc=0 | + | |
- | while [ " | + | |
- | do | + | |
- | case " | + | |
- | 1) # After the last switchover, db1 should be a logical standby | + | |
- | is_database_role $user $passwd $db1tns $db1name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | # After the last switchover, db2 should be the new primary | + | |
- | is_database_role $user $passwd $db2tns $db2name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | # Restart database in mounted mode | + | |
- | shutdown_database $user $passwd $db1tns $db1name | + | |
- | mount_database $user $passwd $db1tns $db1name | + | |
- | ;; | + | |
- | + | ||
- | 2) # Flashing back former primary to pre-upgrade restore point | + | |
- | is_open_mode $user $passwd $db1tns $db1name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | flashback_database $user $passwd $db1tns $db1name ${RPFX}_0000_${VERSION} | + | |
- | ;; | + | |
- | + | ||
- | 3) # Converting primary to physical standby database | + | |
- | convert_to_physical $user $passwd $db1tns $db1name | + | |
- | ;; | + | |
- | + | ||
- | 4) # Save RAC status prior to shutting down the database | + | |
- | is_rac_database $user $passwd $db1tns $db1name | + | |
- | l_s5_db1israc=$? | + | |
- | + | ||
- | # Shutting down database $db1name | + | |
- | shutdown_database $user $passwd $db1tns $db1name | + | |
- | + | ||
- | # Force a checkpoint since we're about to exit | + | |
- | checkpoint | + | |
- | + | ||
- | # User must restart db1 with the new oracle binary | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | if [ " | + | |
- | display_rac_promote $user $passwd $db1tns $db1name $db1iname " | + | |
- | else | + | |
- | display_raw " " | + | |
- | fi | + | |
- | exit | + | |
- | ;; | + | |
- | + | ||
- | *) break;; | + | |
- | esac | + | |
- | + | ||
- | # Checkpoint our completion of the current task | + | |
- | checkpoint | + | |
- | + | ||
- | # Proceed to next task | + | |
- | task=`expr $task + 1` | + | |
- | done | + | |
- | + | ||
- | } # S5_primary_to_physical | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: S6_recover_through_upgrade | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # In this stage, the former primary (now a physical standby on a newer binary) | + | |
- | # is monitored as it recovers up to and through the upgrade redo. During | + | |
- | # this stage, media recovery' | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | S6_recover_through_upgrade() | + | |
- | { | + | |
- | display_stage "Run media recovery through upgrade redo" | + | |
- | + | ||
- | # Nothing to do if task 3 was the last completed task | + | |
- | if [ " | + | |
- | return; | + | |
- | fi | + | |
- | + | ||
- | # Defer exiting so the user gets as much repair context as possible up front | + | |
- | l_rtu_ready=1 | + | |
- | + | ||
- | # db1 must be physical standby, mounted, and on the upgrade version | + | |
- | is_database_role $user $passwd $db1tns $db1name " | + | |
- | if [ " | + | |
- | display " | + | |
- | l_rtu_ready=0 | + | |
- | fi | + | |
- | is_open_mode $user $passwd $db1tns $db1name " | + | |
- | if [ " | + | |
- | display " | + | |
- | l_rtu_ready=0 | + | |
- | fi | + | |
- | if [ " | + | |
- | display " | + | |
- | l_rtu_ready=0 | + | |
- | fi | + | |
- | + | ||
- | # db2 must be a primary, open read write, and on the upgrade version | + | |
- | is_database_role $user $passwd $db2tns $db2name " | + | |
- | if [ " | + | |
- | display " | + | |
- | l_rtu_ready=0 | + | |
- | fi | + | |
- | is_open_mode $user $passwd $db2tns $db2name "READ WRITE" | + | |
- | if [ " | + | |
- | display " | + | |
- | l_rtu_ready=0 | + | |
- | fi | + | |
- | if [ " | + | |
- | display " | + | |
- | l_rtu_ready=0 | + | |
- | fi | + | |
- | + | ||
- | # Exit if any unsatisfied requirements | + | |
- | if [ " | + | |
- | display " | + | |
- | exit 1; | + | |
- | fi | + | |
- | + | ||
- | # Wait for media recovery to recover through upgrade | + | |
- | # Obtain the scn boundaries which define the upgrade region. | + | |
- | # use of the scns associated with the restore points created at | + | |
- | # stage 2, task 4 and stage 3, task 1 to define the upgrade region. | + | |
- | + | ||
- | # Get scn where upgrade starts | + | |
- | get_flashback_scn $user $passwd $db2tns $db2name " | + | |
- | l_rtu_begscn=$l_gfs_val | + | |
- | + | ||
- | # Get scn where upgrade ends | + | |
- | get_flashback_scn $user $passwd $db2tns $db2name " | + | |
- | l_rtu_endscn=$l_gfs_val | + | |
- | + | ||
- | # Use the start/end range as the scale for media recovery' | + | |
- | sql_eval $user $passwd $db2tns $db2name "( ${l_rtu_endscn} - ${l_rtu_begscn} )" | + | |
- | l_rtu_range=$l_se_val | + | |
- | display " | + | |
- | + | ||
- | # Switch logs on the primary | + | |
- | switch_logs $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Start media recovery | + | |
- | start_media_recovery $user $passwd $db1tns $db1name | + | |
- | + | ||
- | # Wait until v$recovery_progress has been initialized | + | |
- | display " | + | |
- | l_rtu_status=1 | + | |
- | l_rtu_curtime=`perl -e 'print int(time)' | + | |
- | l_rtu_exptime=`expr $MRP_START_TIMEOUT " | + | |
- | l_rtu_maxtime=`expr $l_rtu_curtime + $l_rtu_exptime` | + | |
- | while [ " | + | |
- | do | + | |
- | get_recovery_scn $user $passwd $db1tns $db1name $db1ver | + | |
- | l_rtu_curscn=$l_grs_val | + | |
- | if [ " | + | |
- | l_rtu_status=0 | + | |
- | break | + | |
- | fi | + | |
- | sleep $STB_VIEW_INIT_INTERVAL | + | |
- | l_rtu_curtime=`perl -e 'print int(time)' | + | |
- | done | + | |
- | chkerr $l_rtu_status "timed out after $MRP_START_TIMEOUT minutes of inactivity" | + | |
- | l_rtu_lsttime=$l_rtu_curtime | + | |
- | l_rtu_lstscn=$l_rtu_curscn | + | |
- | + | ||
- | # Incur one wait interval before taking the next snapshot | + | |
- | sleep $MRP_REDO_PROG_INTERVAL | + | |
- | + | ||
- | # Report on the MRP's progress | + | |
- | display " | + | |
- | l_rtu_status=1 | + | |
- | l_rtu_curtime=`perl -e 'print int(time)' | + | |
- | l_rtu_numrate=0 | + | |
- | l_rtu_totrate=0 | + | |
- | l_rtu_lstprog=0 | + | |
- | while [ " | + | |
- | do | + | |
- | # Get media recovery' | + | |
- | get_recovery_scn $user $passwd $db1tns $db1name $db1ver | + | |
- | l_rtu_curscn=$l_grs_val | + | |
- | + | ||
- | if [ " | + | |
- | display " | + | |
- | fi | + | |
- | + | ||
- | # Validate the just fetched recovery scn and time | + | |
- | # N.B.: I've seen this on few occasions return dirty values (either 0 or an | + | |
- | # scn less than the previously fetched scn). In either case, discard | + | |
- | # the values and try at the next interval. | + | |
- | if [ " | + | |
- | + | ||
- | # A 0 scn could indicate the MRP is no longer active. | + | |
- | if [ " | + | |
- | display " | + | |
- | + | ||
- | # Wait for the MRP to become active | + | |
- | wait_mrp_active $user $passwd $db1tns $db1name | + | |
- | else | + | |
- | display "WARN: last applied scn of $l_rtu_curscn is less than $l_rtu_lstscn" | + | |
- | fi | + | |
- | + | ||
- | # Wait until the next interval for the next snapshot | + | |
- | sleep $MRP_REDO_PROG_INTERVAL | + | |
- | l_rtu_curtime=`perl -e 'print int(time)' | + | |
- | continue | + | |
- | fi | + | |
- | + | ||
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | # Increment samples counter since we know we'll use the scn/time values | + | |
- | l_rtu_numrate=`expr $l_rtu_numrate + 1` | + | |
- | + | ||
- | # MRP is beyond upgrade redo end | + | |
- | if (sql_gt $user $passwd $db1tns " | + | |
- | if [ " | + | |
- | task=3 | + | |
- | checkpoint | + | |
- | task=`expr $task + 1` | + | |
- | fi | + | |
- | + | ||
- | display "media recovery has finished recovering through upgrade" | + | |
- | l_rtu_status=0 | + | |
- | break | + | |
- | else | + | |
- | # MRP is before upgrade redo start | + | |
- | if (sql_lt $user $passwd $db1tns " | + | |
- | if [ " | + | |
- | checkpoint | + | |
- | task=`expr $task + 1` | + | |
- | fi | + | |
- | + | ||
- | if [ " | + | |
- | display "last applied scn $l_rtu_curscn is approaching upgrade redo start scn $l_rtu_begscn" | + | |
- | fi | + | |
- | else | + | |
- | # MRP is currently recovering upgrade redo | + | |
- | if [ " | + | |
- | task=2 | + | |
- | checkpoint | + | |
- | task=`expr $task + 1` | + | |
- | fi | + | |
- | + | ||
- | # Calculate average apply rate | + | |
- | sql_eval $user $passwd $db2tns $db2name "(( ${l_rtu_curscn} - ${l_rtu_lstscn} ) / ( ${l_rtu_curtime} - ${l_rtu_lsttime} ))" | + | |
- | l_rtu_currate=$l_se_val | + | |
- | l_rtu_totrate=`expr $l_rtu_totrate + $l_rtu_currate` | + | |
- | l_rtu_avgrate=`expr $l_rtu_totrate / \( $l_rtu_numrate \)` | + | |
- | + | ||
- | # Calculate estimated time of completion | + | |
- | sql_eval $user $passwd $db2tns $db2name "(( ${l_rtu_endscn} - ${l_rtu_curscn} ) / ${l_rtu_avgrate} )" | + | |
- | l_rtu_sectime=$l_se_val | + | |
- | l_rtu_dattime=`date "+%b %d %R:%S" -d " | + | |
- | + | ||
- | # Report progress | + | |
- | sql_eval $user $passwd $db2tns $db2name "((( ${l_rtu_curscn} - ${l_rtu_begscn} ) * 100 ) / ${l_rtu_range} )" | + | |
- | l_rtu_curprog=$l_se_val | + | |
- | l_rtu_strprog=`printf %02d $l_rtu_curprog` | + | |
- | if [ " | + | |
- | display " | + | |
- | fi | + | |
- | l_rtu_lstprog=$l_rtu_curprog | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | # Reset timeout if scn has changed from last check | + | |
- | if [ " | + | |
- | l_rtu_maxtime=`expr $l_rtu_curtime + $l_rtu_exptime` | + | |
- | fi | + | |
- | + | ||
- | # Retain apply scn and apply time | + | |
- | l_rtu_lstscn=$l_rtu_curscn | + | |
- | l_rtu_lsttime=$l_rtu_curtime | + | |
- | + | ||
- | # Sleep before we check again | + | |
- | sleep $MRP_REDO_PROG_INTERVAL | + | |
- | l_rtu_curtime=`perl -e 'print int(time)' | + | |
- | done | + | |
- | chkerr $l_rtu_status "timed out after $MRP_UPGRADE_TIMEOUT minutes of inactivity" | + | |
- | + | ||
- | # Checkpoint our completion of the current task | + | |
- | checkpoint | + | |
- | + | ||
- | } # S6_recover_through_upgrade | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: S7_switchback | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # In this stage, the physical standby and primary databases switch roles to | + | |
- | # | + | |
- | # stage is entered, both databases have been fully upgraded. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | S7_switchback() | + | |
- | { | + | |
- | display_stage " | + | |
- | + | ||
- | if [ " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | prompt "Do you want to perform a switchover?" | + | |
- | checkpoint | + | |
- | if [ " | + | |
- | display " | + | |
- | task=2 | + | |
- | else | + | |
- | display " | + | |
- | # Set task to switchover-end state | + | |
- | task=7 | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | # | + | |
- | # Both db1 and db2 must be reduced to single instances for physical switchover | + | |
- | # | + | |
- | if [ " | + | |
- | while [ " | + | |
- | do | + | |
- | # Init flag which indicates prompt is needed | + | |
- | l_s7_db1prompt=0 | + | |
- | l_s7_db2prompt=0 | + | |
- | + | ||
- | # Determine if db2 (the current primary) is a RAC | + | |
- | is_rac_database $user $passwd $db2tns $db2name | + | |
- | if [ " | + | |
- | display " | + | |
- | display_rac_demote $user $passwd $db2tns $db2name $db2iname " | + | |
- | l_s7_db2prompt=$? | + | |
- | fi | + | |
- | + | ||
- | # Only on 11.1 must db1 (the physical standby) reduce to a single instance | + | |
- | if [ " | + | |
- | is_rac_database $user $passwd $db1tns $db1name | + | |
- | if [ " | + | |
- | display " | + | |
- | display_rac_demote $user $passwd $db1tns $db1name $db1iname " | + | |
- | l_s7_db1prompt=$? | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | # Prompt user if either db1 or db2 needs to be reduced | + | |
- | if [ " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | prompt "Are you ready to continue?" | + | |
- | if [ " | + | |
- | display " | + | |
- | else | + | |
- | display " | + | |
- | exit | + | |
- | fi | + | |
- | else | + | |
- | # Not necessary to prompt | + | |
- | break | + | |
- | fi | + | |
- | done | + | |
- | fi | + | |
- | + | ||
- | while [ " | + | |
- | do | + | |
- | case " | + | |
- | 2) # Preparing media recovery for switchover | + | |
- | + | ||
- | is_database_role $user $passwd $db2tns $db2name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | is_database_role $user $passwd $db1tns $db1name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | is_open_mode $user $passwd $db2tns $db2name "READ WRITE" | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | is_open_mode $user $passwd $db1tns $db1name " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | # Start media recovery (typically it's already running) | + | |
- | switch_logs $user $passwd $db2tns $db2name | + | |
- | start_media_recovery $user $passwd $db1tns $db1name | + | |
- | minimize_apply_lag $user $passwd $db2tns $db2name $db1tns $db1name $db1ver $MRP_APPLY_LAG $MRP_APPLY_LAG_TIMEOUT | + | |
- | ;; | + | |
- | + | ||
- | 3) # Switch $db2name to the physical standby role | + | |
- | switch_primary_to_physical $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Restart only if we've just switched | + | |
- | if [ " | + | |
- | shutdown_database $user $passwd $db2tns $db2name | + | |
- | mount_database $user $passwd $db2tns $db2name | + | |
- | fi | + | |
- | ;; | + | |
- | + | ||
- | 4) # Confirm $db1name has witnessed the role change | + | |
- | wait_standby_eor $user $passwd $db1tns $db1name $db1ver | + | |
- | ;; | + | |
- | + | ||
- | 5) # Switch $db1name to the primary role | + | |
- | switch_physical_to_primary $user $passwd $db1tns $db1name | + | |
- | + | ||
- | # Open only if we've just switched | + | |
- | if [ " | + | |
- | open_database $user $passwd $db1tns $db1name | + | |
- | fi | + | |
- | ;; | + | |
- | + | ||
- | 6) # Start media recovery | + | |
- | # N.B.: We omit the ' | + | |
- | # to reprocess the EOR log file | + | |
- | start_media_recovery $user $passwd $db2tns $db2name "using current logfile disconnect" | + | |
- | + | ||
- | # Display a relevant message regarding how to startup the remaining RAC instances on db1 | + | |
- | is_rac_database $user $passwd $db1tns $db1name | + | |
- | if [ " | + | |
- | if [ " | + | |
- | # db1 was reduced to a single instance | + | |
- | display_rac_promote $user $passwd $db1tns $db1name $db1iname " | + | |
- | else | + | |
- | # db1 has one open instance while peer instances are still mounted | + | |
- | display_rac_promote $user $passwd $db1tns $db1name $db1iname " | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | # Display a relevant message regarding how to startup the remaining RAC instances on db2 | + | |
- | is_rac_database $user $passwd $db2tns $db2name | + | |
- | if [ " | + | |
- | # db2 was reduced to a single instance | + | |
- | display_rac_promote $user $passwd $db2tns $db2name $db2iname " | + | |
- | fi | + | |
- | ;; | + | |
- | + | ||
- | 7) # This task is a place-holder task which indicates switchover completion. | + | |
- | # necessary since this particular checkpoint also represents the end of the script. | + | |
- | ;; | + | |
- | + | ||
- | *) break;; | + | |
- | esac | + | |
- | + | ||
- | # Checkpoint our completion of the current task | + | |
- | checkpoint | + | |
- | + | ||
- | # Proceed to next task | + | |
- | task=`expr $task + 1` | + | |
- | done | + | |
- | + | ||
- | } # S7_switchback | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: S8_statistics | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # In this stage, this script produces statistics regarding the upgrade. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | S8_statistics() | + | |
- | { | + | |
- | display_stage " | + | |
- | + | ||
- | # | + | |
- | # Step through each task | + | |
- | # | + | |
- | while [ " | + | |
- | do | + | |
- | case " | + | |
- | 1) # Display physical rolling upgrade statistics | + | |
- | display_stats $user $passwd $db2tns $db2name | + | |
- | ;; | + | |
- | + | ||
- | *) break;; | + | |
- | esac | + | |
- | + | ||
- | # Checkpoint our completion of the current task | + | |
- | checkpoint | + | |
- | + | ||
- | # Proceed to next task | + | |
- | task=`expr $task + 1` | + | |
- | done | + | |
- | + | ||
- | } # S8_statistics | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: S9_cleanup | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # In this stage, the script purges both databases of flashback restore points | + | |
- | # that it created to maintain its execution state. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | S9_cleanup() | + | |
- | { | + | |
- | # For now just suppress all output related to cleanup | + | |
- | suppress=1 | + | |
- | display_stage " | + | |
- | + | ||
- | # | + | |
- | # Step through each task | + | |
- | # | + | |
- | while [ " | + | |
- | do | + | |
- | case " | + | |
- | 1) # With checkpointing no longer necessary, ensure MRP is left running | + | |
- | is_database_role $user $passwd $db2tns $db2name " | + | |
- | if [ " | + | |
- | start_media_recovery $user $passwd $db2tns $db2name "using current logfile disconnect" | + | |
- | fi | + | |
- | ;; | + | |
- | + | ||
- | 2) # Purge restore points from test script | + | |
- | purge_resume_state $user $passwd $db1tns $db1name | + | |
- | purge_resume_state $user $passwd $db2tns $db2name | + | |
- | + | ||
- | # Delete temp files | + | |
- | rm $LOG_SQL_EXETMP | + | |
- | ;; | + | |
- | + | ||
- | *) break;; | + | |
- | esac | + | |
- | + | ||
- | # No checkpoint since we've purged all restore points | + | |
- | + | ||
- | # Proceed to next task | + | |
- | task=`expr $task + 1` | + | |
- | done | + | |
- | + | ||
- | suppress=0 | + | |
- | } # S9_cleanup | + | |
- | + | ||
- | + | ||
- | ############################################################################### | + | |
- | ############ | + | |
- | ############################################################################### | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: checkpoint | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # $user $passwd $db1tns $db2tns $db2name $stage $task $RPFX | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | checkpoint() | + | |
- | { | + | |
- | stagestr=`printf %02d $stage` | + | |
- | taskstr=`printf %02d $task` | + | |
- | l_checkpoint_rpname=" | + | |
- | + | ||
- | suppress=1 | + | |
- | stop_media_recovery $user $passwd $db2tns $db2name | + | |
- | create_restore_point $user $passwd $db2tns $db2name $l_checkpoint_rpname | + | |
- | suppress=0 | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: chkerr | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Check if $1 is non-zero, and if so, output the message supplied in $2 and | + | |
- | # exit immediately. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: status code | + | |
- | # $2: error message | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | chkerr() | + | |
- | { | + | |
- | if [ " | + | |
- | fail " | + | |
- | exit $1 | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: convert_to_physical | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # into a physical standby. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | ############################################################################### | + | |
- | convert_to_physical() | + | |
- | { | + | |
- | display " | + | |
- | # Convert the flashed back logical standby to a physical standby | + | |
- | l_ctp_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database convert to physical standby; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? "faied to convert to physical standby" | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: create_backup_ctlfile | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: name of backup control file | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | create_backup_ctlfile() | + | |
- | { | + | |
- | display " | + | |
- | + | ||
- | # Delete the old backup controlfile to avoid an ORA-27038 | + | |
- | if [ -f " | + | |
- | rm ${LOC_BACKUP_FILES}${5} | + | |
- | fi | + | |
- | + | ||
- | # Create a new backup control file | + | |
- | l_cbc_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database backup controlfile to ' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | display " | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: create_restore_point | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: restore point name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | create_restore_point() | + | |
- | { | + | |
- | display " | + | |
- | l_crp_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | create restore point $5 guarantee flashback database; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: display | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # if set, will suppress all output. | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: message to display | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | display() | + | |
- | { | + | |
- | if [ " | + | |
- | return 0 | + | |
- | else | + | |
- | ts=`date "+%b %d %R:%S %Y"` | + | |
- | if [ " | + | |
- | echo -e "$ts [$stage-$task] $1" | + | |
- | fi | + | |
- | if [ " | + | |
- | if [ " | + | |
- | echo -e "$ts [$stage-$task] $1" >> $LOG_PHYSRU_FILE | + | |
- | fi | + | |
- | fi | + | |
- | return 0 | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: display_banner | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | display_banner() | + | |
- | { | + | |
- | echo "" | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: display_rac_demote | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # of four possible states where it may be necessary to reduce the RAC. These | + | |
- | # | + | |
- | # | + | |
- | # to primary switchover. | + | |
- | # | + | |
- | # This routine returns a 1 to indicate instructions were displayed, and 0 | + | |
- | # | + | |
- | # | + | |
- | # This routine assumes that the caller has already verified the specified | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: instance name | + | |
- | # $6: context - " | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # 0: Instructions were not displayed | + | |
- | # 1: Instructions were displayed | + | |
- | # | + | |
- | ############################################################################### | + | |
- | display_rac_demote() | + | |
- | { | + | |
- | # Variable for instruction number | + | |
- | i=0 | + | |
- | + | ||
- | # Variable for return value | + | |
- | l_drd_val=0 | + | |
- | + | ||
- | # Create a list of RAC instance peers that need to be shutdown | + | |
- | get_instance_peers $1 $2 $3 $4 $5 | + | |
- | l_drd_instcnt=$l_gip_val | + | |
- | l_drd_instlst=" | + | |
- | + | ||
- | # Instantiation requires RAC to be disabled | + | |
- | if [ " | + | |
- | + | ||
- | # Display instructions to user | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | # Only indicate shutdown if one or more peer instances is active | + | |
- | if [ " | + | |
- | i=`expr $i + 1` | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | fi | + | |
- | + | ||
- | # cluster_database needs to be set to FALSE | + | |
- | i=`expr $i + 1` | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | i=`expr $i + 1` | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | # Restart in target mode | + | |
- | i=`expr $i + 1` | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | l_drd_val=1 | + | |
- | + | ||
- | # Conversion to a physical standby requires the RAC to be reduced to a single instance | + | |
- | else if [ " | + | |
- | + | ||
- | # Only indicate shutdown message if one or more peer instances are active | + | |
- | if [ " | + | |
- | + | ||
- | # Display instructions to user | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | i=`expr $i + 1` | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | l_drd_val=1 | + | |
- | fi | + | |
- | + | ||
- | # A switchover to physical requires the primary peer instances to be shutdown | + | |
- | # during the switchover. | + | |
- | # instances to be shutdown only on Oracle version 11.1. In 11.2 and higher, the | + | |
- | # instances may remain active. | + | |
- | else if [ " | + | |
- | + | ||
- | # Display instructions only if peer instances are active | + | |
- | if [ " | + | |
- | i=`expr $i + 1` | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | if [ " | + | |
- | display_raw " | + | |
- | else | + | |
- | if [ " | + | |
- | display_raw " | + | |
- | fi | + | |
- | fi | + | |
- | l_drd_val=1 | + | |
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | return $l_drd_val | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: display_rac_promote | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # The $6 argument identifies the context from which this routine is called. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: instance name | + | |
- | # $6: context - " | + | |
- | # $7: hint (optional) - " | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | display_rac_promote() | + | |
- | { | + | |
- | # | + | |
- | # $6: db2upgrade | + | |
- | # | + | |
- | # In this state, db2 has completed the physical to transient logical setup and | + | |
- | # is now ready to be upgraded. | + | |
- | # it for the instantiation. | + | |
- | # | + | |
- | if [ " | + | |
- | + | ||
- | # N.B.: $7 is a hint which allows us to present a more user-friendly message. | + | |
- | # | + | |
- | # | + | |
- | # way of knowing, and will present a generic suggestion to enable the RAC. | + | |
- | if [ " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | else if [ " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # $6: db1upgrade | + | |
- | # | + | |
- | # In this state, db1 has completed the flashback and conversion to physical standby, | + | |
- | # and has been shutdown in preparation for startup on the newer version binary. | + | |
- | # | + | |
- | else if [ " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # $6: primary11.1 | + | |
- | # | + | |
- | # In this state, db1 has switched back to the primary role from a physical standby on a | + | |
- | # target version of 11.1.X. | + | |
- | # to a single instance. As a result, all that is needed is the startup of the inactive | + | |
- | # instances. | + | |
- | # | + | |
- | else if [ " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # $6: primary | + | |
- | # | + | |
- | # In this state, db1 has switched back to the primary role from a physical standby on a | + | |
- | # target version of 11.2 or higher. | + | |
- | # need to be reduced to a single instance in order to switchover. | + | |
- | # however is that upon switchover, the instance on which the switchover DDL was issued will | + | |
- | # be opened in READ/WRITE mode while the peer instances will remain in mounted mode. Since | + | |
- | # there is no direct way to open a database from the mounted state using srvctl, we instruct | + | |
- | # the user to 1) shutdown the peer instances and then 2) start the database (which will | + | |
- | # start only the inactive instances). | + | |
- | # | + | |
- | else if [ " | + | |
- | # Variable for instruction number | + | |
- | i=0 | + | |
- | + | ||
- | # Get a list of the peer instances | + | |
- | get_instance_peers $1 $2 $3 $4 $5 | + | |
- | l_drp_instcnt=$l_gip_val | + | |
- | l_drp_instlst=" | + | |
- | + | ||
- | # Display a message specific to one or more active peer instances | + | |
- | if [ " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | i=`expr $i + 1` | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | else | + | |
- | # Display a message specific to no active peer instances | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | fi | + | |
- | + | ||
- | i=`expr $i + 1` | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # $6: physical | + | |
- | # | + | |
- | # In this state, db2 has switched back to a physical standby role from the primary role. | + | |
- | # Unlike the physical to primary switchover, in order to switchover the primary was | + | |
- | # required to be reduced to a single instance. | + | |
- | # | + | |
- | else if [ " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | display_raw " | + | |
- | display_raw " | + | |
- | + | ||
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: display_raw | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: message to display | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | display_raw() | + | |
- | { | + | |
- | if [ " | + | |
- | return 0 | + | |
- | else | + | |
- | if [ " | + | |
- | echo -e " | + | |
- | fi | + | |
- | if [ " | + | |
- | if [ " | + | |
- | echo -e " | + | |
- | fi | + | |
- | fi | + | |
- | return 0 | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: display_stage | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # it only produces output when task == 1. This is to avoid multiple messages | + | |
- | # since a stage routine may be re-entered numerous times if there are | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: message describing stage | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | display_stage() | + | |
- | { | + | |
- | if [ " | + | |
- | return 0 | + | |
- | else | + | |
- | # Only produce stage header if first time entered | + | |
- | if [ " | + | |
- | if [ " | + | |
- | echo -e "\n### Stage $stage: $1" | + | |
- | fi | + | |
- | if [ " | + | |
- | if [ " | + | |
- | echo -e "\n### Stage $stage: $1" >> $LOG_PHYSRU_FILE | + | |
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: display_stats | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # it makes about what event occurs for a given [stage-task]. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name of original physical standby | + | |
- | # $4: database unique name of original physical standby | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | display_stats() | + | |
- | { | + | |
- | # | + | |
- | # script start time | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_sst=$l_gft_val | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # script finish time | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_sft=$l_gft_val | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # total script execution time | + | |
- | # | + | |
- | get_interval_time $1 $2 $3 " | + | |
- | l_ds_set=$l_git_val | + | |
- | display_raw "total script execution time: | + | |
- | + | ||
- | # | + | |
- | # user upgrade time | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_uut1=$l_gft_val | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_uut2=$l_gft_val | + | |
- | get_interval_time $1 $2 $3 " | + | |
- | l_ds_uut=$l_git_val | + | |
- | display_raw "wait time for user upgrade: | + | |
- | + | ||
- | # | + | |
- | # user startup former primary as physical on new binary wait time | + | |
- | # | + | |
- | + | ||
- | # | + | |
- | # active script execution time | + | |
- | # | + | |
- | l_ds_ase_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select cast((to_dsinterval(' | + | |
- | as interval day(2) to second(0)) from dual; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_ds_ase=`echo $sql_out` | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # logical instantiation start time | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_lis=$l_gft_val | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # logical instantiation finish time | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_lif=$l_gft_val | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # primary switchover to logical start time | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_pls=$l_gft_val | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # logical switchover to primary finish time | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_lpf=$l_gft_val | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # total time primary services were offline | + | |
- | # | + | |
- | get_interval_time $1 $2 $3 " | + | |
- | l_ds_pso=$l_git_val | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # total time former primary was a physical standby | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_fpp1=$l_gft_val | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_fpp2=$l_gft_val | + | |
- | get_interval_time $1 $2 $3 " | + | |
- | l_ds_fpp=$l_git_val | + | |
- | display_raw "total time former primary in physical role: $l_ds_fpp" | + | |
- | + | ||
- | # | + | |
- | # time to reach upgrade redo | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_bfp1=$l_gft_val | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_bfp2=$l_gft_val | + | |
- | get_interval_time $1 $2 $3 " | + | |
- | l_ds_bfp=$l_git_val | + | |
- | display_raw "time to reach upgrade redo: $l_ds_bfp" | + | |
- | + | ||
- | # | + | |
- | # time to recover through upgrade redo | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_rtu1=$l_gft_val | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_rtu2=$l_gft_val | + | |
- | get_interval_time $1 $2 $3 " | + | |
- | l_ds_rtu=$l_git_val | + | |
- | display_raw "time to recover upgrade redo: $l_ds_rtu" | + | |
- | + | ||
- | # | + | |
- | # no more stats if the final switchover wasn't performed | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_ppf=$l_gft_val | + | |
- | if [ " | + | |
- | return 0 | + | |
- | fi | + | |
- | + | ||
- | # | + | |
- | # primary switchover to physical start time | + | |
- | # | + | |
- | get_flashback_time $1 $2 $3 $4 " | + | |
- | l_ds_pps=$l_gft_val | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # physical switchover to primary finish time | + | |
- | # | + | |
- | display_raw " | + | |
- | + | ||
- | # | + | |
- | # total time primary services were offline | + | |
- | # | + | |
- | get_interval_time $1 $2 $3 " | + | |
- | l_ds_pso2=$l_git_val | + | |
- | display_raw " | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: display_usage | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | display_usage() | + | |
- | { | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | echo -e " | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: sql_comp | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: num1 | + | |
- | # $5: operator = { < > <= >= != } | + | |
- | # $6: num2 | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | sql_comp() | + | |
- | { | + | |
- | l_comp_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select case when (${4} ${5} ${6}) then 0 else 1 end from dual; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | l_comp_val=`echo $sql_out | awk ' | + | |
- | return $l_comp_val | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # lt == less than, eq == equals) comparison between $4 and $5. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: num1 | + | |
- | # $5: num2 | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | sql_gt() | + | |
- | { | + | |
- | sql_comp $1 $2 $3 $4 ">" | + | |
- | l_gt_val=$? | + | |
- | return $l_gt_val | + | |
- | } | + | |
- | + | ||
- | sql_lt() | + | |
- | { | + | |
- | sql_comp $1 $2 $3 $4 "<" | + | |
- | l_lt_val=$? | + | |
- | return $l_lt_val | + | |
- | } | + | |
- | + | ||
- | sql_eq() | + | |
- | { | + | |
- | sql_comp $1 $2 $3 $4 " | + | |
- | l_eq_val=$? | + | |
- | return $l_eq_val | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: sql_eval | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: expression | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | sql_eval() { | + | |
- | l_se_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select trunc(${5}) from dual; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_se_val=`echo $sql_out | awk ' | + | |
- | } | + | |
- | + | ||
- | + | ||
- | ############################################################################### | + | |
- | # NAME: fail | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: error message | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | fail() | + | |
- | { | + | |
- | errormsg=" | + | |
- | display " | + | |
- | exit 1 | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: flashback_database | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: restore point name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | flashback_database() | + | |
- | { | + | |
- | display " | + | |
- | l_fd_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | flashback database to restore point $5; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_applied_scn | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Get the last applied scn of the LSP. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_applied_scn() { | + | |
- | l_gas_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select nvl(applied_scn, | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_gas_val=`echo $sql_out | awk ' | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_db_unique_name | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Gets the db_unique_name for the database. | + | |
- | # in l_dun_val, and 0 is returned from this routine. | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name (passed to script) | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # 0: db_unique_name was found, l_dun_val: db_unique_name | + | |
- | # 1: db_unique_name not found | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_db_unique_name() { | + | |
- | l_dun2_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(db_unique_name) from v\$database; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_dun2_val=`echo $sql_out` | + | |
- | if [ " | + | |
- | return 1 | + | |
- | else | + | |
- | l_dun_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select db_unique_name from v\$database; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_dun_val=`echo $sql_out` | + | |
- | return 0 | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_primary_scn | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Get the current scn on the specified database. | + | |
- | # value obtained from v$database.current_scn. | + | |
- | # used to obtain a starting point on the primary from which to measure the | + | |
- | # time until the redo is recovered or applied. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_primary_scn() { | + | |
- | l_gps_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select nvl(current_scn, | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_gps_val=`echo $sql_out | awk ' | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_flashback_restore_count | + | |
- | # DESCRIPTION: | + | |
- | # Get the total number of flashback restore point entries on the specified | + | |
- | # | + | |
- | # there are enough free entries for this script' | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_flashback_restore_count() { | + | |
- | l_gfr_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(1) from v\$restore_point; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_gfr_val=`echo $sql_out` | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_flashback_scn | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Get the scn associated with a flashback restore point. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: restore point name | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_flashback_scn() { | + | |
- | l_gfs_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select nvl(max(scn), | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_gfs_val=`echo $sql_out | awk ' | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_flashback_time | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Get the time associated with a flashback restore point. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: restore point name | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_flashback_time() { | + | |
- | l_gft_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select to_char(time, | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_gft_val=`echo $sql_out` | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_instance_id | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Gets the instance id from the instance specified at $3. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_instance_id() | + | |
- | { | + | |
- | l_gii_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select instance_number from v\$instance; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_gii_val=`echo $sql_out` | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_instance_name | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Gets the instance name from the specified database. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_instance_name() | + | |
- | { | + | |
- | l_gin_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select instance_name from v\$instance; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_gin_val=`echo $sql_out` | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_instance_peers | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Gets a comma delimited list of instances that are peers with instance $5 | + | |
- | # which is supplied to this routine. | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: instance name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | #select instance_name from gv\$instance where instance_name != ' | + | |
- | ############################################################################### | + | |
- | get_instance_peers() | + | |
- | { | + | |
- | l_gip_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select instance_name from gv\$instance where instance_name != ' | + | |
- | order by instance_number; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_gip_lst=`echo $sql_out | tr ' | + | |
- | l_gip_lst=`echo $l_gip_lst` | + | |
- | l_gip_val=`echo $l_gip_lst | wc -w` | + | |
- | l_gip_lst=`echo $l_gip_lst | tr ' ' ',' | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_interval_time | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: timestamp 1 | + | |
- | # $5: timestamp 2 | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_interval_time() | + | |
- | { | + | |
- | l_git_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select cast((to_timestamp(' | + | |
- | - to_timestamp(' | + | |
- | as interval day(2) to second(0)) from dual; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_git_val=`echo $sql_out` | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_protection_mode | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Get database protection mode for the specified database. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_protection_mode() { | + | |
- | l_gpm_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select protection_mode from v\$database; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_gpm_val=$sql_out | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_rdbms_version | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Get the software version of the Oracle RDBMS | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_rdbms_version() { | + | |
- | l_grv_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select version from v\$instance; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_grv_val=`echo $sql_out` | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_recovery_scn | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Get the last applied scn of the MRP. If the v$recovery_progress view has | + | |
- | # not been initialized, | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: database version | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_recovery_scn() { | + | |
- | + | ||
- | if [ " | + | |
- | l_grs_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select to_number(nvl(max(sofar), | + | |
- | where item = 'Last Applied Redo' and timestamp = (select max(timestamp) from | + | |
- | v\$recovery_progress where item = 'Last Applied Redo' | + | |
- | exit;" | + | |
- | else | + | |
- | l_grs_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select to_number(nvl(substr(max(comments), | + | |
- | where item = 'Last Applied Redo' and timestamp = (select max(timestamp) from | + | |
- | v\$recovery_progress where item = 'Last Applied Redo' | + | |
- | exit;" | + | |
- | fi | + | |
- | + | ||
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | + | ||
- | l_grs_val=`echo $sql_out | awk ' | + | |
- | if [ " | + | |
- | display " | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_resume_state | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Get the stage and task values which identifies the last completed operation. | + | |
- | # These values are parsed from the restore point name composed in the | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_resume_state() { | + | |
- | l_grs2_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select nvl(substr(max(name), | + | |
- | from v\$restore_point where time = (select max(time) from v\$restore_point | + | |
- | where name like ' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_grs2_stage=`echo $sql_out | cut -b 1-2` | + | |
- | l_grs2_task=`echo $sql_out | cut -b 3-4` | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: get_resume_version | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Get the script version # from the oldest script-related restore point on | + | |
- | # the specified database. | + | |
- | # | + | |
- | # | + | |
- | # < | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | get_resume_version() { | + | |
- | l_grv_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select nvl(substr(max(name), | + | |
- | name like ' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_grv_val=$sql_out | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: inthandler | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # This routine traps SIGINTs during the script. | + | |
- | # the handler is to restore the tty back to its original state. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | inthandler() | + | |
- | { | + | |
- | stty $origstty | + | |
- | exit 1 | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: is_database_role | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Check if the database_role in v$database for the specified database | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: database role string (eg: PRIMARY, LOGICAL STANDBY, PHYSICAL STANDBY) | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # 0: database role does not match | + | |
- | # 1: database role matches | + | |
- | # | + | |
- | ############################################################################### | + | |
- | is_database_role() { | + | |
- | l_idr_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(1) from v\$database where database_role=' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_idr_val=`echo $sql_out` | + | |
- | return $l_idr_val | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: is_dg_enabled | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Check if the specified database has an enabled DG Broker. | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # RETURN: | + | |
- | # 0: DG Broker is disabled | + | |
- | # 1: DG Broker is enabled | + | |
- | # | + | |
- | ############################################################################### | + | |
- | is_dg_enabled() { | + | |
- | l_ide_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(1) from v\$parameter where name=' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_ide_val=`echo $sql_out` | + | |
- | return $l_ide_val | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: is_flashback_enabled | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Check if flashback database is enabled on the specified database. | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # 0: flashback is not enabled | + | |
- | # 1: flashback is enabled | + | |
- | # | + | |
- | ############################################################################### | + | |
- | is_flashback_enabled() { | + | |
- | l_ife_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(1) from v\$database where flashback_on = ' | + | |
- | flashback_on = ' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_ife_val=`echo $sql_out` | + | |
- | return $l_ife_val | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: is_lsp_running | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Check if logical standby apply is running. | + | |
- | # on which it is running is returned. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # 0: lsp0 is not running on any instance | + | |
- | # N: the instance id on which the lsp0 is running | + | |
- | # | + | |
- | ############################################################################### | + | |
- | is_lsp_running() { | + | |
- | l_ilr_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(1) from v\$logstdby_state where state != 'SQL APPLY NOT ON'; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_ilr_val=`echo $sql_out` | + | |
- | return $l_ilr_val | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: is_mrp_running | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Check if media recovery is running on any instance in the specified | + | |
- | # | + | |
- | # If not running, a 0 is returned. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # 0: mrp is not running on any instance | + | |
- | # N: the instance id on which the mrp is running | + | |
- | # | + | |
- | ############################################################################### | + | |
- | is_mrp_running() { | + | |
- | l_imr_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select nvl(max(inst_id), | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_imr_val=`echo $sql_out` | + | |
- | return $l_imr_val | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: is_rac_database | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Check if the specified instance is a RAC database. | + | |
- | # if the instance is in a RAC, and 0 otherwise. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # RETURN: | + | |
- | # 0: instance is in a RAC | + | |
- | # 1: instance is not in a RAC | + | |
- | # | + | |
- | ############################################################################### | + | |
- | is_rac_database() { | + | |
- | l_ird_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(1) from v\$instance where PARALLEL=' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_ird_val=`echo $sql_out` | + | |
- | return $l_ird_val | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: is_open_mode | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Check if the specified database is in an open mode matching $5. Typically | + | |
- | # the open_mode in v$database is compared against $5. The exception to this | + | |
- | # is 'OPEN MIGRATE' | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: open mode (eg: OPEN, MOUNTED, OPEN MIGRATE) | + | |
- | # | + | |
- | # RETURN: | + | |
- | # 0: open mode does not match | + | |
- | # 1: open mode matches | + | |
- | # | + | |
- | ############################################################################### | + | |
- | is_open_mode() { | + | |
- | if [ " | + | |
- | l_iom_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(1) from v\$instance where status = ' | + | |
- | exit;" | + | |
- | else | + | |
- | l_iom_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(1) from v\$database where open_mode=' | + | |
- | exit;" | + | |
- | fi | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_iom_val=`echo $sql_out` | + | |
- | return $l_iom_val | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: mount_database | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | mount_database() | + | |
- | { | + | |
- | display " | + | |
- | l_md_sql=`sqlplus -L -s $1/$2@$3 as sysdba << EOF > /dev/null | + | |
- | set pagesize 0 feedback off verify off heading off echo off tab off | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | startup mount; | + | |
- | exit; | + | |
- | EOF` | + | |
- | chkerr $? " | + | |
- | is_open_mode $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | fail "$4 is not in MOUNTED mode" | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: open_database | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Opens the specified database. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | open_database() | + | |
- | { | + | |
- | display " | + | |
- | l_od_sql=`sqlplus -s $1/$2@$3 as sysdba << EOF > /dev/null | + | |
- | set pagesize 0 feedback off verify off heading off echo off tab off | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database open; | + | |
- | exit; | + | |
- | EOF` | + | |
- | chkerr $? " | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: purge_resume_state | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | purge_resume_state() { | + | |
- | display " | + | |
- | l_prs_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | declare | + | |
- | cursor curs is | + | |
- | select name from v\$restore_point where name like ' | + | |
- | begin | + | |
- | for r_curs in curs loop | + | |
- | execute immediate 'drop restore point ' || r_curs.name; | + | |
- | end loop; | + | |
- | end; | + | |
- | / | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: recover_to_logical | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | recover_to_logical() | + | |
- | { | + | |
- | display " | + | |
- | + | ||
- | l_rtl_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database recover to logical standby keep identity; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | + | ||
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Wait for the 'apply lag' to fall below $5 seconds. | + | |
- | # apply lag in v$dataguard_stats, | + | |
- | # takes the current scn at the primary to be processed by media recovery or | + | |
- | # or the apply process, depending on the standby type. If the time to apply | + | |
- | # the redo exceeds the specified threshold, this procedure will retry for up | + | |
- | # to $9 minutes, after which it will return an error. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name to primary | + | |
- | # $4: database unique name of primary | + | |
- | # $5: tns service name to standby | + | |
- | # $6: database unique name of standby | + | |
- | # $7: database version of standby | + | |
- | # $8: apply lag target in seconds | + | |
- | # $9: timeout in minutes | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | minimize_apply_lag() | + | |
- | { | + | |
- | # Don't perform the wait if on 11.1 (see 14174798) | + | |
- | if [ " | + | |
- | return | + | |
- | fi | + | |
- | + | ||
- | display " | + | |
- | + | ||
- | # Determine the database role of the standby | + | |
- | is_database_role $1 $2 $5 $6 " | + | |
- | if [ " | + | |
- | l_mal_dbtype=" | + | |
- | else | + | |
- | is_database_role $1 $2 $5 $6 " | + | |
- | if [ " | + | |
- | l_mal_dbtype=" | + | |
- | else | + | |
- | fail " | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | # Loop until within apply delay or timeout | + | |
- | l_mal_curtime=0 | + | |
- | l_mal_maxtime=1 | + | |
- | l_mal_reset=1 | + | |
- | l_mal_status=1 | + | |
- | while [ " | + | |
- | do | + | |
- | # Reset the timeouts | + | |
- | if [ " | + | |
- | l_mal_curtime=`perl -e 'print int(time)' | + | |
- | l_mal_exptime=`expr $9 " | + | |
- | l_mal_engtime=`expr $l_mal_curtime + 60` | + | |
- | l_mal_maxtime=`expr $l_mal_curtime + $l_mal_exptime` | + | |
- | l_mal_reset=0 | + | |
- | fi | + | |
- | + | ||
- | # Grab the base time from which to measure the apply delay | + | |
- | l_mal_basetime=`perl -e 'print int(time)' | + | |
- | + | ||
- | # Grab the current scn associated with base time | + | |
- | get_primary_scn $1 $2 $3 $4 | + | |
- | l_mal_basescn=$l_gps_val | + | |
- | + | ||
- | # Switch logs to ensure delivery to the standby | + | |
- | switch_logs $1 $2 $3 $4 | + | |
- | + | ||
- | # Loop until the base scn has been applied | + | |
- | l_mal_pstscn=" | + | |
- | l_mal_curscn=" | + | |
- | while (sql_lt $1 $2 $5 " | + | |
- | do | + | |
- | # Get the last processed scn on the standby | + | |
- | if [ " | + | |
- | get_applied_scn $1 $2 $5 $6 | + | |
- | l_mal_curscn=$l_gas_val | + | |
- | else | + | |
- | get_recovery_scn $1 $2 $5 $6 $7 | + | |
- | l_mal_curscn=$l_grs_val | + | |
- | fi | + | |
- | + | ||
- | # Grab the time associated with processed scn | + | |
- | l_mal_curtime=`perl -e 'print int(time)' | + | |
- | + | ||
- | # The base scn has been processed | + | |
- | if (sql_lt $1 $2 $5 " | + | |
- | + | ||
- | # Calculate the apply lag | + | |
- | l_mal_lag=`expr $l_mal_curtime - $l_mal_basetime` | + | |
- | display "apply lag measured at ${l_mal_lag} seconds" | + | |
- | + | ||
- | # Success if it was applied within the delay | + | |
- | if [ " | + | |
- | l_mal_status=0 | + | |
- | else | + | |
- | # Reset the timeout and try again since we're making progress | + | |
- | l_mal_reset=1 | + | |
- | fi | + | |
- | + | ||
- | # Break to the main loop to proceed or retry | + | |
- | break | + | |
- | fi | + | |
- | + | ||
- | # The processed scn has advanced from the last check | + | |
- | if [ " | + | |
- | l_mal_pstscn=$l_mal_curscn | + | |
- | l_mal_engtime=`expr $l_mal_curtime + 60` | + | |
- | else | + | |
- | # Check the engine status if the processed scn was stagnant for 60 seconds | + | |
- | if [ " | + | |
- | if [ " | + | |
- | is_lsp_running $1 $2 $5 $6 | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | else | + | |
- | is_mrp_running $1 $2 $5 $6 | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | # Reset the engine check time | + | |
- | l_mal_engtime=`expr $l_mal_curtime + 60` | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | # Sleep and try again | + | |
- | sleep $STB_VIEW_INIT_INTERVAL | + | |
- | done | + | |
- | done | + | |
- | + | ||
- | chkerr $l_mal_status "timed out after $9 minutes of inactivity" | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: prompt | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: message to display to user | + | |
- | # $2: valid answers list eg: y/n | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | prompt() | + | |
- | { | + | |
- | # Create a space delimited list of valid answers | + | |
- | l_p_anslst=`echo $2 | tr '/' | + | |
- | + | ||
- | # Create the full message text | + | |
- | l_p_msg=" | + | |
- | + | ||
- | while [ " | + | |
- | do | + | |
- | # Write to logfile only since prompting writes to the terminal | + | |
- | suppresst=1 | + | |
- | display_raw " | + | |
- | suppresst=0 | + | |
- | + | ||
- | l_p_val="" | + | |
- | read -p " | + | |
- | for validans in $l_p_anslst | + | |
- | do | + | |
- | if [ " | + | |
- | l_p_val=" | + | |
- | display_raw "" | + | |
- | return 0 | + | |
- | fi | + | |
- | done | + | |
- | + | ||
- | display "not a valid option - ' | + | |
- | done | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: set_rolling_upg_params | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Setup logical standby parameters suitable for physical rolling upgrade on | + | |
- | # the specified database. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | set_rolling_upgrade_params() | + | |
- | { | + | |
- | display " | + | |
- | l_rup_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | execute sys.dbms_logstdby.apply_set(' | + | |
- | execute sys.dbms_logstdby.apply_set(' | + | |
- | execute sys.dbms_logstdby.apply_set(' | + | |
- | execute sys.dbms_logstdby.apply_set(' | + | |
- | execute sys.dbms_logstdby.apply_set(' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: shutdown_database | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | shutdown_database() | + | |
- | { | + | |
- | display " | + | |
- | l_sd_sql=`sqlplus -s $1/$2@$3 as sysdba << EOF > /dev/null | + | |
- | set pagesize 0 feedback off verify off heading off echo off tab off | + | |
- | shutdown immediate; | + | |
- | exit; | + | |
- | EOF` | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: sql_exec | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # code from sqlplus is returned from this routine. | + | |
- | # | + | |
- | # | + | |
- | # the sql_out global variable, and should not be modified in any way. This | + | |
- | # | + | |
- | # a failure occur during execution. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: sql string to execute | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | sql_exec() | + | |
- | { | + | |
- | # write sql string to temporary file | + | |
- | echo " | + | |
- | + | ||
- | # execute sql | + | |
- | sql_out=`sqlplus -L -s $1/$2@$3 as sysdba @${LOG_SQL_EXETMP}` | + | |
- | + | ||
- | # save sqlplus return value | + | |
- | l_se_ret=$? | + | |
- | + | ||
- | # display offending sql code | + | |
- | if [ " | + | |
- | display_raw "\n### The following error was encountered:" | + | |
- | display_raw " | + | |
- | display_raw "\n### The offending sql code in its entirety:" | + | |
- | display_raw " | + | |
- | fi | + | |
- | + | ||
- | return $l_se_ret | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: start_logical_apply | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Start logical standby apply on the specified database. | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | start_logical_apply() | + | |
- | { | + | |
- | # check if logical needs to be started | + | |
- | is_lsp_running $1 $2 $3 $4 | + | |
- | if [ " | + | |
- | + | ||
- | # Start logical standby | + | |
- | display " | + | |
- | l_sla_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database start logical standby apply immediate; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | + | ||
- | # Confirm startup | + | |
- | l_sla_status=1 | + | |
- | l_sla_curtime=`perl -e 'print int(time)' | + | |
- | l_sla_exptime=`expr $LSP_START_TIMEOUT " | + | |
- | l_sla_maxtime=`expr $l_sla_curtime + $l_sla_exptime` | + | |
- | while [ " | + | |
- | do | + | |
- | is_lsp_running $1 $2 $3 $4 | + | |
- | if [ " | + | |
- | l_sla_status=0 | + | |
- | break | + | |
- | fi | + | |
- | + | ||
- | sleep $LSP_START_INTERVAL | + | |
- | l_sla_curtime=`perl -e 'print int(time)' | + | |
- | done | + | |
- | chkerr $l_sla_status "timed out after $LSP_START_TIMEOUT minutes of inactivity" | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: start_logical_build | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | start_logical_build() | + | |
- | { | + | |
- | display " | + | |
- | l_slb_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | execute dbms_logstdby.build; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: start_media_recovery | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # This routine starts media recovery on the specified database. | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: recovery options (optional) | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | start_media_recovery() | + | |
- | { | + | |
- | # check if media recovery needs to be started | + | |
- | is_mrp_running $1 $2 $3 $4 | + | |
- | l_smr_inst=$? | + | |
- | if [ " | + | |
- | if [ " | + | |
- | l_smr_opt=" | + | |
- | else | + | |
- | l_smr_opt=" | + | |
- | fi | + | |
- | + | ||
- | # start media recovery | + | |
- | display " | + | |
- | l_smr_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database recover managed standby database ${l_smr_opt}; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | + | ||
- | # confirm the MRP has started | + | |
- | wait_mrp_active $1 $2 $3 $4 | + | |
- | else | + | |
- | # ensure the MRP is running on the instance associated with the tns service name | + | |
- | get_instance_id $1 $2 $3 $4 | + | |
- | if [ " | + | |
- | display "media recovery on database $4 is unexpectedly running on instance id $l_smr_inst" | + | |
- | fail " | + | |
- | fi | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: stop_logical_apply | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Stops logical standby apply on the specified database. | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | stop_logical_apply() | + | |
- | { | + | |
- | # check if logical needs to be stopped | + | |
- | is_lsp_running $1 $2 $3 $4 | + | |
- | if [ " | + | |
- | + | ||
- | # stop logical standby | + | |
- | display " | + | |
- | l_sla_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database stop logical standby apply; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: stop_media_recovery | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Stop media recovery on the specified database. | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | stop_media_recovery() | + | |
- | { | + | |
- | # check if media recovery needs to be stopped | + | |
- | is_mrp_running $1 $2 $3 $4 | + | |
- | l_smr_inst=$? | + | |
- | if [ " | + | |
- | # ensure the MRP is running on the instance associated with the tns service name | + | |
- | get_instance_id $1 $2 $3 $4 | + | |
- | if [ " | + | |
- | display "media recovery on database $4 is unexpectedly running on instance id $l_smr_inst" | + | |
- | fail " | + | |
- | fi | + | |
- | + | ||
- | # stop media recovery | + | |
- | display " | + | |
- | l_smr2_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database recover managed standby database cancel; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: switch_logs | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | switch_logs() | + | |
- | { | + | |
- | l_sl_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter system switch logfile; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: switch_logical_to_primary | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # the database is already a primary, this routine concludes success. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | switch_logical_to_primary() | + | |
- | { | + | |
- | # Assume success if db is already a primary | + | |
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | display "$4 is already a primary" | + | |
- | return 1 | + | |
- | fi | + | |
- | + | ||
- | # Ensure we're switching from a logical | + | |
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | fail "$4 is neither a primary nor logical standby database" | + | |
- | fi | + | |
- | + | ||
- | # Switchover | + | |
- | display " | + | |
- | l_slp_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database commit to switchover to primary; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | display "$4 is now the new primary" | + | |
- | return 0 | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: switch_physical_to_primary | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # the database is already a primary, this routine concludes success. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | switch_physical_to_primary() | + | |
- | { | + | |
- | # Assume success if db is already a primary | + | |
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | display "$4 is already a primary" | + | |
- | return 1 | + | |
- | fi | + | |
- | + | ||
- | # Ensure we're switching from a physical | + | |
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | fail "$4 is neither a primary nor physical standby database" | + | |
- | fi | + | |
- | + | ||
- | # Switchover | + | |
- | display " | + | |
- | l_spp_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database commit to switchover to primary; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | display "$4 is now the new primary" | + | |
- | return 0 | + | |
- | } | + | |
- | + | ||
- | + | ||
- | ############################################################################### | + | |
- | # NAME: switch_primary_to_logical | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | switch_primary_to_logical() | + | |
- | { | + | |
- | # Assume success if db is already a logical | + | |
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | display "$4 is already a logical standby" | + | |
- | return 1 | + | |
- | fi | + | |
- | + | ||
- | # Ensure we're switching from a primary | + | |
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | fail "$4 is neither a primary nor logical standby database" | + | |
- | fi | + | |
- | + | ||
- | # Switchover | + | |
- | display " | + | |
- | l_spl_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database commit to switchover to logical standby; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | display "$4 is now a logical standby" | + | |
- | return 0 | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: switch_primary_to_physical | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # | + | |
- | # the database is already a physical standby, this routine concludes success. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | switch_primary_to_physical() | + | |
- | { | + | |
- | # Assume success if db is already a physical | + | |
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | display "$4 is already a physical standby" | + | |
- | return 1 | + | |
- | fi | + | |
- | + | ||
- | # Ensure we're switching from a primary | + | |
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | fail "$4 is neither a primary nor physical standby database" | + | |
- | fi | + | |
- | + | ||
- | # Switchover | + | |
- | display " | + | |
- | l_spp_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | alter database commit to switchover to physical standby with session shutdown; | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | display "$4 is now a physical standby" | + | |
- | return 0 | + | |
- | # | + | |
- | # NOTE: no further queries permitted since the database will no longer mounted | + | |
- | # | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: wait_mrp_active | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Wait for $MRP_START_TIMEOUT minutes to confirm that the MRP is active. | + | |
- | # we can't detect an active MRP, abort the script with an error. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | wait_mrp_active() | + | |
- | { | + | |
- | display " | + | |
- | l_wma_status=1 | + | |
- | l_wma_curtime=`perl -e 'print int(time)' | + | |
- | l_wma_exptime=`expr $MRP_START_TIMEOUT " | + | |
- | l_wma_maxtime=`expr $l_wma_curtime + $l_wma_exptime` | + | |
- | while [ " | + | |
- | do | + | |
- | is_mrp_running $1 $2 $3 $4 | + | |
- | if [ " | + | |
- | l_wma_status=0 | + | |
- | break | + | |
- | fi | + | |
- | + | ||
- | sleep $MRP_START_INTERVAL | + | |
- | l_wma_curtime=`perl -e 'print int(time)' | + | |
- | done | + | |
- | chkerr $l_wma_status "could not detect an active MRP after $MRP_START_TIMEOUT minutes" | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: wait_standby_eor | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Wait for specified standby database to process the end-of-redo and shutdown | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # $5: database version of standby | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | wait_standby_eor() | + | |
- | { | + | |
- | display " | + | |
- | + | ||
- | # Identify the standby type | + | |
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | l_wse_islogical=1 | + | |
- | else | + | |
- | is_database_role $1 $2 $3 $4 " | + | |
- | if [ " | + | |
- | l_wse_islogical=0 | + | |
- | else | + | |
- | fail " | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | # Wait for 'TO PRIMARY' | + | |
- | #display " | + | |
- | l_wse_expdelta=`expr $STB_EOR_TIMEOUT " | + | |
- | l_wse_resdelta=`expr $STB_EOR_RESTART_AFTER " | + | |
- | l_wse_pstscn=0 | + | |
- | l_wse_curscn=1 | + | |
- | l_wse_restarted=0 | + | |
- | l_wse_status=1 | + | |
- | l_wse_curtime=0 | + | |
- | l_wse_maxtime=1 | + | |
- | l_wse_reset=1 | + | |
- | while [ " | + | |
- | do | + | |
- | # Grab the current time | + | |
- | l_wse_curtime=`perl -e 'print int(time)' | + | |
- | + | ||
- | # Reset the timeouts | + | |
- | if [ " | + | |
- | l_wse_maxtime=`expr $l_wse_curtime + $l_wse_expdelta` | + | |
- | l_wse_restime=`expr $l_wse_curtime + $l_wse_resdelta` | + | |
- | l_wse_reset=0 | + | |
- | fi | + | |
- | + | ||
- | # Check for end-of-redo completion | + | |
- | l_wse_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(1) from v\$database where SWITCHOVER_STATUS=' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_wse_val=`echo $sql_out` | + | |
- | + | ||
- | # Success | + | |
- | if [ " | + | |
- | l_wse_status=0 | + | |
- | break | + | |
- | fi | + | |
- | + | ||
- | # Get the last processed scn on the standby | + | |
- | if [ " | + | |
- | get_applied_scn $1 $2 $3 $4 | + | |
- | l_wse_curscn=$l_gas_val | + | |
- | else | + | |
- | get_recovery_scn $1 $2 $3 $4 $5 | + | |
- | l_wse_curscn=$l_grs_val | + | |
- | fi | + | |
- | + | ||
- | # Reset all timeouts if last applied scn has changed | + | |
- | if [ " | + | |
- | l_wse_pstscn=$l_wse_curscn | + | |
- | l_wse_reset=1 | + | |
- | else | + | |
- | # Consider a one-time restart if last applied scn has stagnated for l_wse_resdelta seconds | + | |
- | if [ " | + | |
- | + | ||
- | # Check if apply/ | + | |
- | if [ " | + | |
- | is_lsp_running $1 $2 $3 $4 | + | |
- | else | + | |
- | is_mrp_running $1 $2 $3 $4 | + | |
- | fi | + | |
- | l_wse_running=$? | + | |
- | + | ||
- | # Perform a one-time restart if apply/ | + | |
- | if [ " | + | |
- | if [ " | + | |
- | display " | + | |
- | if [ " | + | |
- | start_logical_apply $1 $2 $3 $4 | + | |
- | else | + | |
- | start_media_recovery $1 $2 $3 $4 | + | |
- | fi | + | |
- | l_wse_restarted=1 | + | |
- | l_wse_reset=1 | + | |
- | fi | + | |
- | else | + | |
- | if [ " | + | |
- | fail " | + | |
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | fi | + | |
- | sleep $STB_EOR_INTERVAL | + | |
- | done | + | |
- | chkerr $l_wse_status "timed out after $l_wse_expdelta seconds of inactivity" | + | |
- | } | + | |
- | + | ||
- | ############################################################################### | + | |
- | # NAME: wait_logical_dictload | + | |
- | # | + | |
- | # DESCRIPTION: | + | |
- | # Wait for the logminer dictionary to load. This routine will wait for up to | + | |
- | # | + | |
- | # | + | |
- | # the entire timeout period. | + | |
- | # | + | |
- | # INPUT(S): | + | |
- | # | + | |
- | # $1: database user | + | |
- | # $2: user password | + | |
- | # $3: tns service name | + | |
- | # $4: database unique name | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | # RETURN: | + | |
- | # | + | |
- | # | + | |
- | ############################################################################### | + | |
- | wait_logical_dictload() | + | |
- | { | + | |
- | display " | + | |
- | + | ||
- | # Wait for dictionary to load | + | |
- | l_wld_lstpct=0 | + | |
- | l_wld_retried=0 | + | |
- | l_wld_status=1 | + | |
- | l_wld_wasloading=0 | + | |
- | l_wld_curtime=`perl -e 'print int(time)' | + | |
- | l_wld_exptime=`expr $LSP_DICT_LOAD_TIMEOUT " | + | |
- | l_wld_maxtime=`expr $l_wld_curtime + $l_wld_exptime` | + | |
- | while [ " | + | |
- | do | + | |
- | # Lookup current dictionary load completion | + | |
- | l_wld_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select nvl(translate((select substr(l.status, | + | |
- | v\$logstdby l, v\$logstdby_state s where l.status like ' | + | |
- | and s.state = ' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_wld_curpct=`echo $sql_out | awk ' | + | |
- | + | ||
- | # has dictionary loading stopped ? | + | |
- | if [ " | + | |
- | + | ||
- | # Upon successful load, we should be in either of these states | + | |
- | l_wld_sql=" | + | |
- | whenever sqlerror exit sql.sqlcode | + | |
- | select count(1) from v\$logstdby_state where | + | |
- | state = ' | + | |
- | exit;" | + | |
- | sql_exec $1 $2 $3 " | + | |
- | chkerr $? " | + | |
- | l_wld_loaded=`echo $sql_out` | + | |
- | + | ||
- | # Success | + | |
- | if [ " | + | |
- | l_wld_status=0 | + | |
- | break | + | |
- | fi | + | |
- | + | ||
- | # Give apply one chance to reload the dictionary | + | |
- | if [ " | + | |
- | start_logical_apply $1 $2 $3 $4 | + | |
- | l_wld_retried=1 | + | |
- | fi | + | |
- | else | + | |
- | # Set flag indicating we've seen the dictionary loading | + | |
- | l_wld_wasloading=1 | + | |
- | + | ||
- | # NOTE: this view hangs at 100%...show 99% instead | + | |
- | if [ " | + | |
- | l_wld_curpct=99 | + | |
- | fi | + | |
- | + | ||
- | # Report if progress was made since last check | + | |
- | if [ " | + | |
- | l_wld_strpct=`printf %02d $l_wld_curpct` | + | |
- | display " | + | |
- | + | ||
- | # Reset timeout | + | |
- | l_wld_maxtime=`expr $l_wld_curtime + $l_wld_exptime` | + | |
- | + | ||
- | # Retain last retain last percentage | + | |
- | l_wld_lstpct=$l_wld_curpct | + | |
- | fi | + | |
- | fi | + | |
- | + | ||
- | sleep $LSP_DICT_LOAD_INTERVAL | + | |
- | l_wld_curtime=`perl -e 'print int(time)' | + | |
- | done | + | |
- | + | ||
- | if [ " | + | |
- | if [ " | + | |
- | display " | + | |
- | else | + | |
- | display " | + | |
- | fi | + | |
- | else | + | |
- | fail "timed out after $LSP_DICT_LOAD_TIMEOUT minutes of inactivity" | + | |
- | fi | + | |
- | } | + | |
- | + | ||
- | autopru $1 $2 $3 $4 $5 $6 | + | |
- | </code> | + |