Oracle RAC 修改系统时区避坑指南(深挖篇)

news2024/9/21 19:01:28

大家好,这里是 Lucifer三思而后行,专注于提升数据库运维效率。

目录

  • 前言
  • 环境安装
  • 问题重现
    • 时区检查
    • 修改时区
    • 问题分析
    • 问题解决
  • 深究根源
    • 问题一
    • 问题二
    • 问题三
  • 写在最后
  • 往期精彩文章推荐

前言

昨天遇到一个问题,Oracle RAC 安装完之后,客户反馈数据库查询的时间不对,经分析原来是系统时区与客户所属时区不一致(看来是安装操作系统时选错了时区),需要修改系统时区。

本以为是一个很简单的操作,没想到踩坑了,修改系统时区之后,查询发现以下问题(已解决):

## 使用 TNS 连接数据库查询时间时区为:上海 +0800
$ sqlplus system/oracle@lucifer

SQL> select SYSTIMESTAMP from dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
21-AUG-24 01.19.41.557307 PM +08:00

## 使用本地连接数据库查询时间:越南 +0700
$ sqlplus / as sysdba

SQL> select SYSTIMESTAMP from dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
21-AUG-24 12.20.25.136498 PM +07:00

于是把问题重现了一下进行分享,希望大家能够在遇到这种情况时可以及时避坑。

环境安装

首先用 Oracle一键安装脚本 快速部署一套测试环境:

./OracleShellInstall -n rocky9 `# RAC 主机名前缀`\
-hn rocky9-01,rocky9-02 `# RAC 主机名`\
-cn rocky9-cls `# RAC 集群名称`\
-sn rocky9-scan `# RAC SCAN 名称`\
-rp oracle `# 主机 root 用户密码`\
-lf ens33 `# 主机网卡名称`\
-pf ens34 `# 主机心跳网卡名称`\
-ri 192.168.6.160,192.168.6.161 `# RAC 公网 IP`\
-vi 192.168.6.162,192.168.6.163 `# RAC 虚拟 IP`\
-si 192.168.6.165 `# RAC SCAN IP`\
-od /dev/sdb `# OCR 磁盘盘符名称`\
-dd /dev/sdc `# DATA 磁盘盘符名称`\
-o lucifer `# 数据库名称`\
-dp 'Passw0rd#PST' `# sys/system 用户密码`\
-ds AL32UTF8 `# 数据库字符集`\
-ns AL16UTF16 `# 国家字符集`\
-redo 100 `# 在线重做日志大小(M)`\
-opd Y `# 是否优化数据库`

耗时 45 分钟左右,下面重现下问题。

问题重现

时区检查

当前环境我的系统时区是 Asia/Shanghai (CST, +0800)

## 节点一
[root@rocky9-01:/root]# ll /etc/localtime 
lrwxrwxrwx. 1 root root 35 Aug 15 10:17 /etc/localtime -> ../usr/share/zoneinfo/Asia/Shanghai
[root@rocky9-01:/root]# timedatectl 
               Local time: Wed 2024-08-21 11:56:42 CST
           Universal time: Wed 2024-08-21 03:56:42 UTC
                 RTC time: Wed 2024-08-21 03:56:45
                Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: no
              NTP service: active
          RTC in local TZ: no

## 节点二
[root@rocky9-02:/root]# ll /etc/localtime 
lrwxrwxrwx. 1 root root 35 Aug 15 10:17 /etc/localtime -> ../usr/share/zoneinfo/Asia/Shanghai
[root@rocky9-02:/root]# timedatectl 
               Local time: Wed 2024-08-21 11:57:40 CST
           Universal time: Wed 2024-08-21 03:57:40 UTC
                 RTC time: Wed 2024-08-21 03:57:43
                Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: no
              NTP service: active
          RTC in local TZ: no

查看数据库时间:

-- 使用 TNS 连接数据库查询时间时区为:上海 +0800
SQL> select SYSTIMESTAMP from dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
21-AUG-24 11.59.33.946355 AM +08:00

-- 使用本地连接数据库查询时间:上海 +0800
SQL> select SYSTIMESTAMP from dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
21-AUG-24 11.59.33.946355 AM +08:00

修改之前可以发现两个方式查询的时间和时区是一致的。

修改时区

首先停止数据库以及集群服务:

## 关闭数据库
[oracle@rocky9-01:/home/oracle]$ srvctl stop db -d lucifer
## 关闭集群以及自启(两个节点)
[root@rocky9-01:/root]# crsctl stop crs
[root@rocky9-01:/root]# crsctl disable crs
[root@rocky9-02:/root]# crsctl stop crs
[root@rocky9-02:/root]# crsctl disable crs

手动修改操作系统时区:

## 修改时区为越南(两个节点)
## 节点一
[root@rocky9-01:/root]# timedatectl set-timezone "Asia/Ho_Chi_Minh"
[root@rocky9-01:/root]# timedatectl 
               Local time: Wed 2024-08-21 11:09:43 +07
           Universal time: Wed 2024-08-21 04:09:43 UTC
                 RTC time: Wed 2024-08-21 04:09:46
                Time zone: Asia/Ho_Chi_Minh (+07, +0700)
System clock synchronized: no
              NTP service: active
          RTC in local TZ: no
[root@rocky9-01:/root]# ll /etc/localtime 
lrwxrwxrwx 1 root root 38 Aug 21 11:09 /etc/localtime -> ../usr/share/zoneinfo/Asia/Ho_Chi_Minh

## 节点二
[root@rocky9-02:/root]# timedatectl set-timezone "Asia/Ho_Chi_Minh"
[root@rocky9-02:/root]# timedatectl 
               Local time: Wed 2024-08-21 11:09:28 +07
           Universal time: Wed 2024-08-21 04:09:28 UTC
                 RTC time: Wed 2024-08-21 04:09:31
                Time zone: Asia/Ho_Chi_Minh (+07, +0700)
System clock synchronized: no
              NTP service: active
          RTC in local TZ: no
[root@rocky9-02:/root]# ll /etc/localtime 
lrwxrwxrwx 1 root root 38 Aug 21 11:09 /etc/localtime -> ../usr/share/zoneinfo/Asia/Ho_Chi_Minh

可以发现时区已经修改成功,但是为了确保起见,重启一下两台服务器主机:

[root@rocky9-01:/root]# reboot
[root@rocky9-02:/root]# reboot

重启完成后,再次检查操作系统时区:

## 节点一
[root@rocky9-01:/root]# timedatectl 
               Local time: Wed 2024-08-21 12:10:03 +07
           Universal time: Wed 2024-08-21 05:10:03 UTC
                 RTC time: Wed 2024-08-21 05:10:03
                Time zone: Asia/Ho_Chi_Minh (+07, +0700)
System clock synchronized: no
              NTP service: active
          RTC in local TZ: no

## 节点二
[root@rocky9-02:/root]# timedatectl 
               Local time: Wed 2024-08-21 12:10:07 +07
           Universal time: Wed 2024-08-21 05:10:07 UTC
                 RTC time: Wed 2024-08-21 05:10:07
                Time zone: Asia/Ho_Chi_Minh (+07, +0700)
System clock synchronized: no
              NTP service: active
          RTC in local TZ: no

确保没有问题后启动集群和数据库:

## 启动集群(两个节点)
[root@rocky9-01:/root]# crsctl start crs
[root@rocky9-02:/root]# crsctl start crs
## 打开数据库
[oracle@rocky9-01:/home/oracle]$ srvctl start db -d lucifer

正常启动:

[root@rocky9-01:/root]# crsctl stat res -t
--------------------------------------------------------------------------------
NAME           TARGET  STATE        SERVER                   STATE_DETAILS       
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.DATA.dg
               ONLINE  ONLINE       rocky9-01                                    
               ONLINE  ONLINE       rocky9-02                                    
ora.LISTENER.lsnr
               ONLINE  ONLINE       rocky9-01                                    
               ONLINE  ONLINE       rocky9-02                                    
ora.OCR.dg
               ONLINE  ONLINE       rocky9-01                                    
               ONLINE  ONLINE       rocky9-02                                    
ora.asm
               ONLINE  ONLINE       rocky9-01                Started             
               ONLINE  ONLINE       rocky9-02                Started             
ora.gsd
               OFFLINE OFFLINE      rocky9-01                                    
               OFFLINE OFFLINE      rocky9-02                                    
ora.net1.network
               ONLINE  ONLINE       rocky9-01                                    
               ONLINE  ONLINE       rocky9-02                                    
ora.ons
               ONLINE  ONLINE       rocky9-01                                    
               ONLINE  ONLINE       rocky9-02                                    
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
      1        ONLINE  ONLINE       rocky9-02                                    
ora.cvu
      1        ONLINE  ONLINE       rocky9-01                                    
ora.lucifer.db
      1        ONLINE  ONLINE       rocky9-01                Open                
      2        ONLINE  ONLINE       rocky9-02                Open                
ora.oc4j
      1        ONLINE  ONLINE       rocky9-01                                    
ora.rocky9-01.vip
      1        ONLINE  ONLINE       rocky9-01                                    
ora.rocky9-02.vip
      1        ONLINE  ONLINE       rocky9-02                                    
ora.scan1.vip
      1        ONLINE  ONLINE       rocky9-02 

验证一下修改后的数据库时间:

-- 使用 TNS 连接数据库查询时间时区为:上海 +0800
SQL> select SYSTIMESTAMP from dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
21-AUG-24 01.26.09.483623 PM +08:00

-- 使用本地连接数据库查询时间:越南 +0700
SQL> select SYSTIMESTAMP from dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
21-AUG-24 12.26.21.182588 PM +07:00

问题成功复现了。

问题分析

通过以上情况可以发现,本地的时区是正确的,但是使用 TNS 连接的时区是不对的,因为通过 TNS 连接数据库查询 SYSTIMESTAMP 是取的监听时间,也就是说监听可能存在问题。

这里可以参考 MOS 文档中的 point 9 & 11:Dates & Calendars - Frequently Asked Questions (Doc ID 227334.1)

9) Why is my SYSDATE / SYSTIMESTAMP time not the same as my system clock on Unix?
To debug situations in which you have a unexplained difference between the oracle SYSDATE / SYSTIMESTAMP and the system time you see on Unix, use the following method:

telnet/ssh to the Unix box
connect using sqlplus in the telnet session:

1) once through the listener using a tnsnames alias
$sqlplus user/password @ [tnsnames alias]
SQL>select to_char(sysdate,'DD-MON-YY HH24:MI:SS') from dual;

2) once through a "local" ORACLE_SID connection
$env | egrep 'ORACLE_SID'
$sqlplus user/password
SQL>select to_char(sysdate,'DD-MON-YY HH24:MI:SS') from dual;

Check that the time in the banner of sqlplus ( SQL*Plus: Release 10.1.0.4.0 - Production on Wo Jan 11 15:05:46 2006 ) is reflecting the time based on the current TZ set in the Unix (!) session.

If the results are different this means that the listener is started with a different TZ setting than you current user environment. To resolve this simply stop and start listener with the TZ setting you want to use.
Make sure you double check what listener you are using when having multiple listeners. For more information about the TZ variable please see your OS documentation.

11)How do I see & set the TZ environment variable in a RAC environment
note 1390015.1 Incorrect SYSDATE shown when connected via Listener in RAC

Note: If you stop and start a RAC database and/or listener "manual" on Unix (= with sqlplus or lsnrctl) then the above setting is NOT used but the TZ setting of the OS user that starts the database/listener, see point 9)

How to use multiple timezones for current_timestamp ( NOT for sysdate !) please see Note 1531653.1 How to use multiple timezones with one Oracle RAC database .

检查监听的时间是否正确:

[grid@rocky9-01:/home/grid]$ lsnrctl stat

LSNRCTL for Linux: Version 11.2.0.4.0 - Production on 21-AUG-2024 12:28:52

Copyright (c) 1991, 2013, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 11.2.0.4.0 - Production
Start Date                21-AUG-2024 13:13:32
Uptime                    0 days 0 hr. 15 min. 20 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u01/app/11.2.0/grid/network/admin/listener.ora
Listener Log File         /u01/app/grid/diag/tnslsnr/rocky9-01/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.6.160)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.6.162)(PORT=1521)))
Services Summary...
Service "+ASM" has 1 instance(s).
  Instance "+ASM1", status READY, has 1 handler(s) for this service...
Service "lucifer" has 1 instance(s).
  Instance "lucifer1", status READY, has 1 handler(s) for this service...
Service "luciferXDB" has 1 instance(s).
  Instance "lucifer1", status READY, has 1 handler(s) for this service...
The command completed successfully

通过上面的输出可以发现一个很诡异的现象:

## 查看监听的时间是 12:30,也就是越南时间
LSNRCTL for Linux: Version 11.2.0.4.0 - Production on 21-AUG-2024 12:30:35

## 然而监听启动时间是 13:13,也就是北京时间,明显是错误的
Start Date                21-AUG-2024 13:13:32

为什么监听启动时间会是错误的呢?为了尽快解决问题,通过搜索 MOS 发现了一个文档有相关解决方案:How To Change Timezone for Grid Infrastructure (Doc ID 1209444.1)

其中有一段描述与我们遇到的情况极其相似:

可以看到从 11.2.0.2 版本开始,TZ 时区环境变量需要读取 $GRID_HOME/crs/install/s_crsconfig_<nodename>_env.txt 文件中的 TZ 变量值,这也会影响监听的启动时间。

检查文件中对应的 TZ 变量值:

## 节点一
[grid@rocky9-01:/home/grid]$ cd $ORACLE_HOME/crs/install
[grid@rocky9-01:/u01/app/11.2.0/grid/crs/install]$ grep TZ s_crsconfig_rocky9-01_env.txt 
TZ=Asia/Shanghai

## 节点二
[grid@rocky9-02:/u01/app/11.2.0/grid/crs/install]$ grep TZ s_crsconfig_rocky9-02_env.txt 
TZ=Asia/Shanghai

当前配置文件的 TZ 值明显为修改之前的时区,看来是符合的。

问题解决

既然知道了解决方案,那解决就很简单了,修改 $GRID_HOME/crs/install/s_crsconfig_<nodename>_env.txt 文件中的 TZ 变量为正确的值即可:

## 节点一
## 备份配置文件
[grid@rocky9-01:/u01/app/11.2.0/grid/crs/install]$ cp s_crsconfig_rocky9-01_env.txt s_crsconfig_rocky9-01_env.txt20240821
## 修改 TZ 值
[grid@rocky9-01:/u01/app/11.2.0/grid/crs/install]$ sed -i 's/^TZ=.*/TZ=Asia\/Ho_Chi_Minh/' s_crsconfig_rocky9-01_env.txt
[grid@rocky9-01:/u01/app/11.2.0/grid/crs/install]$ grep TZ s_crsconfig_rocky9-01_env.txt
TZ=Asia/Ho_Chi_Minh

## 节点二
## 备份配置文件
[grid@rocky9-02:/u01/app/11.2.0/grid/crs/install]$ cp s_crsconfig_rocky9-02_env.txt s_crsconfig_rocky9-02_env.txt20240821
## 修改 TZ 值
[grid@rocky9-02:/u01/app/11.2.0/grid/crs/install]$ sed -i 's/^TZ=.*/TZ=Asia\/Ho_Chi_Minh/' s_crsconfig_rocky9-02_env.txt
[grid@rocky9-02:/u01/app/11.2.0/grid/crs/install]$ grep TZ s_crsconfig_rocky9-02_env.txt 
TZ=Asia/Ho_Chi_Minh

修改后需要重启数据库和集群才能生效,最好重启主机:

## 关闭数据库
[oracle@rocky9-01:/home/oracle]$ srvctl stop db -d lucifer
## 关闭集群以及恢复自启(两个节点)
[root@rocky9-01:/root]# crsctl stop crs
[root@rocky9-01:/root]# crsctl enable crs
[root@rocky9-02:/root]# crsctl stop crs
[root@rocky9-02:/root]# crsctl enable crs
[root@rocky9-01:/root]# reboot
[root@rocky9-02:/root]# reboot

重启后检查监听:

## 系统时间
[grid@rocky9-01:/home/grid]$ date
Wed Aug 21 01:07:01 PM +07 2024
## 监听时间
[grid@rocky9-01:/home/grid]$ lsnrctl stat

LSNRCTL for Linux: Version 11.2.0.4.0 - Production on 21-AUG-2024 13:07:02

Copyright (c) 1991, 2013, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 11.2.0.4.0 - Production
Start Date                21-AUG-2024 13:05:03
Uptime                    0 days 0 hr. 1 min. 59 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /u01/app/11.2.0/grid/network/admin/listener.ora
Listener Log File         /u01/app/grid/diag/tnslsnr/rocky9-01/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.6.160)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.6.162)(PORT=1521)))
Services Summary...
Service "+ASM" has 1 instance(s).
  Instance "+ASM1", status READY, has 1 handler(s) for this service...
Service "lucifer" has 1 instance(s).
  Instance "lucifer1", status READY, has 1 handler(s) for this service...
Service "luciferXDB" has 1 instance(s).
  Instance "lucifer1", status READY, has 1 handler(s) for this service...
The command completed successfully

可以看到监听时间和系统时间已经保持一致,再次验证数据库时间:

-- 使用 TNS 连接数据库查询时间时区为:越南 +0700
SQL> select SYSTIMESTAMP from dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
21-AUG-24 01.08.20.889733 PM +07:00

-- 使用本地连接数据库查询时间:越南 +0700
SQL> select SYSTIMESTAMP from dual;

SYSTIMESTAMP
---------------------------------------------------------------------------
21-AUG-24 01.08.24.437260 PM +07:00

时区一致,与客户确认后,已恢复正常。

深究根源

问题解决,就结束了吗?不,还想深究下 3 个问题:

  1. 这个 txt 配置文件是如何生成的?
  2. txt 配置文件中的 TZ 值是如何获取的?
  3. 监听为什么会受这个文件影响?

问题一

这个配置文件是什么时候生成的?通过分析 Grid 安装日志,大致算是搞清楚了,下面记录一下分析过程,通过倒退的方式。

首先在 $GRID_HOME/crs/install/s_crsconfig_lib.pm 文件中有一个函数:

sub s_createConfigEnvFile
#---------------------------------------------------------------------
# Function: Create s_crsconfig_$HOST_env.txt file for Time Zone
# Args    : none
# Notes   : Valid <env_file> format
#           (Please keep this in sync with has/utl/crswrapexec.pl)
#             * Empty lines: lines with all white space
#             * Comments: line starts with #.
#             * <key>=<value>
#             * <key> is all non-whitespace characters on the left of the
#               first "=" character.
#             * <value> is everything on the right of the first "=" character
#               (including whitespaces).
#             * Surrounding double-quote (") won't be stripped.
#             * Key with blank <value> ('') will be undefined.
#               (e.g: Hello=, Hello will be undefined)
#---------------------------------------------------------------------
{
   my $env_file = catfile($ORA_CRS_HOME, 'crs', 'install',
                          's_crsconfig_' . $HOST . '_env.txt');

   open (ENVFILE, ">$env_file") or die "Can't create $env_file: $!";

   print ENVFILE "### This file can be used to modify the NLS_LANG environment"
               . " variable, which determines the charset to be used for messages.\n"
               . "### For example, a new charset can be configured by setting"
               . " NLS_LANG=JAPANESE_JAPAN.UTF8 \n"
               . "### Do not modify this file except to change NLS_LANG,"
               . " or under the direction of Oracle Support Services\n\n";

   # get TZ
   if ($CFG->defined_param('TZ')) {
      my $tz = $CFG->params('TZ');
      $tz    =~ s/'//g; # remove single quotes
      print ENVFILE "TZ=" . $tz . "\n";
   }
    ...
    ...
    ...
}

我这里截取了其中重要的一部分,也就是创建 s_crsconfig_$HOST_env.txt 文件的代码,这段代码的主要目的是生成一个环境变量配置文件 s_crsconfig_<HOST>_env.txt,其中包含头注释信息,并且会写入 TZ(时区)变量的值。

当然,上面只是定义了一个函数,并没有在这个文件中被调用,调用函数的文件是 $GRID_HOME/crs/install/crsconfig_lib.pm,对应的代码段为:

# 导入名为 s_crsconfig_lib 的模块,也就是上面的 s_crsconfig_lib.pm 文件
use s_crsconfig_lib;

# 调用 s_createConfigEnvFile 函数创建 s_crsconfig_$HOST_env.txt 文件
sub run_env_setup_modules
{
    ...
    ...
    ...

    # create s_crsconfig_$HOST_env.txt file
    s_createConfigEnvFile ();
}

顺藤摸瓜,找到调用 run_env_setup_modules 函数的文件是 $GRID_HOME/crs/install/rootcrs.pl,对应的代码块是:

# 导入名为 crsconfig_lib 的模块,也就是上面的 crsconfig_lib.pm 文件
use crsconfig_lib;

# 调用 run_env_setup_modules 函数
# run directory creation, script instantiation, files creation/permissions
# modules
run_env_setup_modules ();

那么 rootcrs.pl 文件是在哪里以及什么时候调用的呢?对 root.sh 执行过程比较熟悉的朋友应该已经知道了,不熟悉的朋友也没关系,继续顺藤摸瓜就行。

调用 rootcrs.pl 的文件是 $GRID_HOME/crs/config/rootconfig.sh,对应的代码块是:

HA_CONFIG=false

# 这里 ROOTCRSPL 指向的就是 crs/install/rootcrs.pl 文件
ROOTCRSPL="$ORACLE_HOME/perl/bin/perl -I$ORACLE_HOME/perl/lib -I$ORACLE_HOME/crs/install $ORACLE_HOME/crs/install/rootcrs.pl"

# 当 HA_CONFIG 为 false 时调用了 `rootcrs.pl` 文件
if [ "$HA_CONFIG" = "true" ]; then
  ROOTSCRIPT=$ROOTHASPL
else
  ROOTSCRIPT=$ROOTCRSPL
fi

接着就是 rootconfig.sh$GRID_HOME/root.sh 文件调用,对应的代码块是:

/u01/app/11.2.0/grid/crs/config/rootconfig.sh

到这里,生成 s_crsconfig_$HOST_env.txt 文件的整个流程就很清晰了,大概如下:

  1. 安装 Grid 时执行 $GRID_HOME/root.sh
  2. root.sh 脚本调用 $GRID_HOME/crs/config/rootconfig.sh 脚本
  3. rootconfig.sh 脚本调用 $GRID_HOME/crs/install/rootcrs.pl 脚本
  4. rootcrs.pl 脚本调用 $GRID_HOME/crs/install/crsconfig_lib.pm 文件
  5. crsconfig_lib.pm 文件调用 $GRID_HOME/crs/install/s_crsconfig_lib.pm 文件
  6. s_crsconfig_lib.pm 文件中定义了函数创建 s_crsconfig_$HOST_env.txt 文件。

第一个问题算是彻底研究明白了。

问题二

因为前面知道 s_crsconfig_$HOST_env.txt 文件的创建函数了,所以只要看下创建时 TZ 值是如何获取就知道了。

查看创建函数获取 TZ 变量值的代码段:

# get TZ
   if ($CFG->defined_param('TZ')) {
      my $tz = $CFG->params('TZ');
      $tz    =~ s/'//g; # remove single quotes
      print ENVFILE "TZ=" . $tz . "\n";
   }

这段代码的主要作用是检查配置对象 $CFG 中是否定义了 TZ 参数,并在存在时获取其值,去除其中的单引号,然后将其以 TZ=<value> 的格式写入到文件中。

也就是说需要知道 $CFG 对象是如何定义的,这个对象是在 $GRID_HOME/crs/install/rootcrs.pl 脚本中定义的,对应的代码段是:

# pull all parameters defined in crsconfig_params and s_crsconfig_defs (if
# it exists) as variables in Perl
my $paramfile_default = catfile (dirname ($0), "crsconfig_params");

our $PARAM_FILE_PATH = $paramfile_default;

# Read the config files and set up the configuration data for
# subsequent processing
my $cfg =
  crsconfig_lib->new(IS_SIHA             => FALSE,
                     paramfile           => $PARAM_FILE_PATH,
                     osdfile             => $defsfile,
                     addfile             => $addparams,
                     crscfg_trace        => TRUE,
                     CRSDelete           => $g_delete,
                     DEBUG               => $DEBUG,
                     HAS_USER            => $SUPERUSER,
                     HOST                => $HOST,
                     UPGRADE             => $UPGRADE,
                     UNLOCK		 => $g_unlock,
                     unlock_crshome      => $unlock_crshome,
                     CRSPatch            => $g_patch,
                     DOWNGRADE           => $DOWNGRADE,
                     oldcrshome          => $oldcrshome,
                     oldcrsver           => $oldcrsver,
                     force               => $g_force,
                     deinstall           => $g_deinstall,
                     keepdg              => $g_keepdg,
                     lastnode            => $g_lastnode,
                     REMOTENODE          => $REMOTENODE,
                     destcrshome         => $destcrshome
                     );

可以看到获取参数值的对应文件为当前目录下的 crsconfig_params 文件,查看文件中是否存在 TZ 相关的参数:

## 以节点一为例
[grid@rocky9-01:/u01/app/11.2.0/grid/crs/install]$ grep TZ crsconfig_params
#    dpham      03/17/10 - Add TZ variable (9462081
TZ=Asia/Shanghai

📢 注意:这里的 TZ 值还是 Asia/Shanghai,为什么没有影响到数据库的运行?因为这里仅用于安装时生成 s_crsconfig_$HOST_env.txt 文件所用,所以不修改也无关大雅。

这个文件是由 crsconfig_params.sbs 生成,其中 TZ 参数:

[grid@rocky9-01:/u01/app/11.2.0/grid/crs/install]$ grep TZ crsconfig_params.sbs 
#    dpham      03/17/10 - Add TZ variable (9462081
TZ=%oracle_install_crs_Timezone%

可以看到 TZ 变量值是通过 %oracle_install_crs_Timezone% 获取。

在 Grid 安装过程中会生成一个静默文件 $GRID_HOME/inventory/response/oracle.crs_Complete.rsp,其中记录了 Grid 安装时获取到的 %oracle_install_crs_Timezone% 值:

#-------------------------------------------------------------------------------
#Name       : oracle_install_crs_Timezone
#Datatype   : String
#Description: 
#-------------------------------------------------------------------------------
oracle_install_crs_Timezone="Asia/Shanghai"

这个文件的值是来源于 $GRID_HOME/inventory/globalvariables/oracle.crs/globalvariables.xml,对应的安装日志中也有相关记录:

## $GRID_HOME/inventory/globalvariables/oracle.crs/globalvariables.xml
<VAR NAME="oracle_install_crs_Timezone" TYPE="STRING" VALUE="Asia/Shanghai" ADVISE="T" COMPUTE_AT_CLONE="F" CALC_REQD="F" CLASS="oracle.sysman.oii.oiis.OiisVariable" EXTENDS_FROM="" ALLOW_ASSIGNMENT="T" HANDLE_ERRORS="F" VAL_REQD="F" SECURE="F" SUPPRESS_ON_SILENT="F" DESC_ID=""/>

## $GRID_HOME/cfgtoollogs/oui/installActions2024-08-15_04-05-22PM.log
INFO: The default response file generated with recorded values is /u01/app/11.2.0/grid/inventory/response/oracle.crs_Complete.rsp
INFO: -destinationFile option was not provided. Saving the default response file as /u01/app/11.2.0/grid/inventory/response/oracle.crs_Complete.rsp
INFO: Recording the installation in file /u01/app/11.2.0/grid/inventory/response/oracle.crs_Complete.rsp.

INFO: INFO: globalpropLocation= /soft/grid/install/../stage/globalvariables/globalvar.xml
INFO: INFO: oracle.install.tb.globalvarpath= /soft/grid/install/../stage/globalvariables/globalvar.xml

INFO: Reading global variables from file /soft/grid/install/../stage/globalvariables/globalvar.xml

INFO: ----------------------------------------------------------------------------------------------------
INFO:  PROPERTY                                               VALUE                                      
INFO: ----------------------------------------------------------------------------------------------------
INFO:  oracle_install_crs_Timezone                            Asia/Shanghai           
INFO: adding the variable oracle_install_crs_Timezone to command line args table
INFO: Setting variable 'oracle_install_crs_Timezone' to 'Asia/Shanghai'. Received the value from the command line.

## $GRID_HOME/install/root_rocky9-01_2024-08-15_16-14-17.log
Using configuration parameter file: /u01/app/11.2.0/grid/crs/install/crsconfig_params

## $GRID_HOME/cfgtoollogs/crsconfig/rootcrs_rocky9-01.log
2024-08-15 16:14:17: The configuration parameter file /u01/app/11.2.0/grid/crs/install/crsconfig_params is valid
2024-08-15 16:14:17: ### Printing the configuration values from files:
2024-08-15 16:14:17:    /u01/app/11.2.0/grid/crs/install/crsconfig_params
2024-08-15 16:14:17: paramfile=/u01/app/11.2.0/grid/crs/install/crsconfig_params

TZ 的值是通过 /soft/grid/install/../stage/globalvariables/globalvar.xml 文件读取的,所以只需要搞清楚 globalvar.xml 的值是如何注入的就知道了。

这个可以在安装软件解压后的文件中找到相关定义:

## stage/globalvariables/variable.properties
variables_xmls=globalvar.xml

## stage/globalvariables/globalvar.xml
<!-- GLOBAL VARIABLES FOR VENDOR CLUSTERWARE INSTALL -->
      <VAR NAME="oracle_install_crs_Timezone" TYPE="STRING" VALUE="" ALLOW_ASSIGNMENT="T"/>

在软件包刚解压时,oracle_install_crs_Timezone 对应的 VALUE 值为空,在安装过程中被写入,至于如何写入的,这个在安装日志中没有找到,怀疑可能是核心 jar 包中获取写入的。

问题三

至于最后一个问题,监听为什么会受这个文件影响?这个就需要追溯到监听是在哪一步启动了,在前几天写过一篇:Oracle RAC 集群启动顺序 就有这个答案:

监听是由 oraagent 服务启动,所以需要查看 bin/oraagent 脚本文件,对应的代码段为:

case $0 in
*.bin) 
    ORASYM=/u01/app/11.2.0/grid/bin/`basename $0 .bin`
    ;;
*)     
    ORASYM=$0.bin
    ;;
esac

exec $ORASYM "$@"

这个文件是为了找 oraagent.bin 执行,看起来并没有相关 TZ 配置文件的调用,但是在脚本中我发现了:

*ohasd*)
    CRSWRAPEXECE="/u01/app/11.2.0/grid/bin/crswrapexece.pl"
    ENV_FILE="${ORA_CRS_HOME}/crs/install/s_crsconfig_${MY_HOST}_env.txt"
    export ENV_FILE

由此看来,这个文件是在调用 ohasd 时调用生效,而 ohasd 是最初启动的进程:

查看 $GRID_HOME/log/rocky9-01/client/crswrapexece.log 日志也可以看到:

20-Aug-24 12:46 Executed cmd: /u01/app/11.2.0/grid/bin/crswrapexece.pl /u01/app/11.2.0/grid/crs/install/s_crsconfig_rocky9-01_env.txt /u01/app/11.2.0/grid/bin/ohasd.bin reboot
20-Aug-24 12:46 executing "/u01/app/11.2.0/grid/bin/ohasd.bin reboot"

这样的话,一切就说的通了,在 ohasd 服务启动时,会去获取 s_crsconfig_${MY_HOST}_env.txt 文件作为环境变量文件 ENV_FILE,然后生效该环境变量文件,自然也就生效了 TZ 时区变量,后续启动监听时也会读取 TZ 变量值。

写在最后

虽然还是有一些疑问❓没有得到解答,比如 TZ 到底是如何从操作系统层面获取并赋值的?但是通过这一次深挖,确实对 Grid 的安装启动流程了解更加清晰了,希望能对大家也有所帮助!


往期精彩文章推荐

一篇文章让你彻底掌握 Python 🔥
一篇文章让你彻底掌握 Shell 🔥
Oracle 监控 EMCC 13.5 安装部署超详细教程 🔥
Oracle 一键巡检自动生成 Word 报告 🔥
Oracle一键安装脚本的 21 个疑问与解答 🔥
Oracle一键巡检脚本的 21 个疑问与解答 🔥
全网首发:Oracle 23ai 一键安装脚本 🔥
Oracle 19C 最新 RU 补丁 19.24 ,一键安装! 🔥
Oracle Linux 6 一键安装 Oracle 11GR2 RAC
Oracle Linux 7.9 一键安装 Oracle 19C
Oracle Linux 8.9 一键安装 Oracle 19C RAC
Oracle Linux 9.4(aarch64) 一键安装 Oracle 19C 🔥
openEuler 20.03 LTS SP4 一键安装 Oracle 19C 🔥
openEuler 22.03 LTS SP4 一键安装 Oracle 19C RAC
RHEL 7.9 一键安装 Oracle 19C 19.23 RAC
Redhat 8.4 一键安装 Oracle 11GR2
RedHat 9.4(aarch64) 一键安装 Oracle 19C
龙蜥 Anolis 7.9 一键安装 Oracle 19C 19.23
龙蜥 Anolis OS 8.8 一键安装 Oracle 19C
SUSE 15 SP5 一键安装 Oracle 19C
统信 UOS V20 1070(a) 一键安装 Oracle 11GR2
Ubuntu 22.04 一键安装 Oracle 19C
Ubuntu 14.04 一键安装 Oracle 19C
银河麒麟 Kylin V10 SP3 一键安装 Oracle 19C 🔥
银河麒麟 Kylin V10 SP3 一键安装 Oracle 11GR2 RAC
Oracle DataGuard GAP 修复手册 🔥
优化 Oracle:最佳实践与开发规范
DBA 必备:Linux 软件源配置全攻略 🔥
Linux 一键配置时钟同步全攻略 🔥
Starwind 配置 ISCSI 共享存储
SUSE 15 SP3 安装 Oracle 19C RAC 数据库
达梦 8 数据库安装手册 🔥
Oracle 12CR2 RAC 安装避坑宝典
Linux7 安装 Oracle 19C RAC 详细图文教程 🔥
Oracle ADG 搭建 RAC to Single 详细教程
Oracle DataGuard GAP 修复手册 🔥
Oracle 分区表之在线重定义
AutoUpgrade 快速升级 Oracle 数据库
Oracle 数据库巡检命令手册 🔥
Oracle 数据坏块的 N 种修复方式 🔥
数据库 SQL 开发入门教程
超全 Linux 基础命令总结 🔥
VMware 虚拟机安装 Linux 系统
Linux 安装 MySQL 详细教程
教你玩转 SQLPLUS,工作效率提升 200%


感谢您的阅读,这里是 Lucifer三思而后行,欢迎 点赞+关注,我会持续分享数据库知识、运维技巧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2082122.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

bitsandbytes使用错误:CUDA Setup failed despite GPU being available

参考:https://huggingface.co/docs/bitsandbytes/main/en/installation 报错信息 ======================

【JavaEE精炼宝库】网络原理基础——网络层 | IP协议

文章目录 一、IP 协议的格式二、IP 地址的数量限制三、私有 IP 地址和公网 IP 地址3.1 私有 IP 地址和公网 IP 地址的基本知识&#xff1a;3.2 内网 IP 设备访问外网 IP 设备的过程&#xff08;NAT 机制&#xff09;&#xff1a; 四、地址管理4.1 网段划分&#xff1a;4.1.1 网…

npm、cnpm、pnpm、yarn包管理工具别傻傻分不清楚了

干啥的&#xff1a; nodejs的包管理工具。 用于自动化处理包的安装、更新、配置和管理。它们之间的主要区别在于它们各自的实现方式、性能优化、以及一些特有的功能。 怎么用&#xff1a; 1、npm 1.1、描述 Node Package Manager默认包管理器从 npm 公共仓库中安装、共享…

.net framework 4.8 开发windows系统服务

ps:旧技术了&#xff0c;有一点局限性&#xff0c;但好像网上记录并不多&#xff0c;或是很零散&#xff0c;比较坑人。故自己记录一下。 项目环境&#xff1a; win 10、.Net framework 4.8&#xff0c;Visual Studio 2019&#xff0c;oracle 12G&#xff0c;ORM是SqlSugar5.…

uniapp video标签无法播放视频

当video标签路径含有中文以及特殊字符视频就会无法播放 解决方法使用encodeURIComponent对路径进行加密处理 videoSrc data.coursewareFile? ${appConfig.apiUrl encodeURIComponent(data.coursewareFile)}: "";最后效果

GHA高质量seo文章怎么写?

撰写高质量SEO文章不仅仅是文字的堆砌&#xff0c;更是对内容的精心打磨&#xff0c;而GHA文章更是如此&#xff0c;想写出一篇GHA文章&#xff0c;首先就要保证以下几点&#xff0c;一定要原创&#xff0c;谷歌对于原创内容是极其看重的&#xff0c;哪怕是伪原创&#xff0c;在…

一种导出PPT到MP4的方法

需求 导出PPT到MP4&#xff0c;并记录每页&#xff0c;每个动作的时间线。通过 MP4时间线 就可以在页面上很方便的放映PPT的内容&#xff0c;并支持翻页点击。 代码 保存每一页的图像信息&#xff0c;用做播放器的缩略图 public void SaveThumbnail(string ppt_filepath, st…

【STL】红黑树的全面探索与红黑树的实现

ps&#xff1a;文章最后有完整的代码 1.红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路…

如何使用IDEA搭建Mybatis框架环境

文章目录 ☕前言为什么学习框架技术Mybatis框架简介 &#x1f379;一、如何配置Mybatis框架环境1.1下载需要MyBatis的jar文件1.2部署jar文件1.3创建MyBatis核心配置文件configuration.xml1.4.创建持久类(POJO)和SQL映射文件1.5.创建测试类 &#x1f9cb;二、 MyBatis框架的优缺…

前端性能优化:使用Vue3+TS+Canvas对图片进行压缩后再上传,优化带宽,减小服务器存储成本,减少流量损耗

在上传图片之前&#xff0c;对图片进行压缩。看到这里是不是有点懵&#xff0c;前端怎么压缩图片呢&#xff0c;这不应该是后端做的吗&#xff1f; 但是我在开发的时候接到了这样一个需求&#xff0c;要求对用户上传的图片进行一定的压缩&#xff0c;而且并且尽量还原图片的清…

大模型如何改变世界?李彦宏:未来至少一半人要学会“提问题“

2023年爆火的大模型&#xff0c;对我们来说意味着什么&#xff1f; 百度创始人、董事长兼CEO李彦宏认为&#xff0c;“大模型即将改变世界。” 5月26日&#xff0c;李彦宏参加了在北京举办的2023中关村论坛&#xff0c;发表了题为《大模型改变世界》的演讲。李彦宏认为&#…

2024年新算法-基于SBOA-BP混合神经网络的数据预测(Python代码实现)

在今天的数字化时代&#xff0c;机器学习和人工智能领域的不断发展为数据处理和预测提供了强大的工具。其中&#xff0c;BP神经网络&#xff08;反向传播神经网络&#xff09;作为一种经典的网络模型&#xff0c;因其能够处理复杂的非线性问题而备受关注。然而&#xff0c;传统…

吴恩达机器学习课后作业-07kmeans and pca

k-均值与PCA k-均值图片颜色聚类 PCA&#xff08;主成分分析&#xff09;对x去均值化图像降维 k-均值 K-均值是最普及的聚类算法&#xff0c;算法接受一个未标记的数据集&#xff0c;然后将数据聚类成不同的组。 K-均值是一个迭代算法&#xff0c;假设我们想要将数据聚类成n个…

python-变量声明、数据类型、标识符

一.变量 1.什么是变量 为什么需要变量呢&#xff1f; 一个程序就是一个世界&#xff0c;不论使用哪种高级程序语言编写代码&#xff0c;变量都是其程序的基本组成单位。如下图所示的sum和sub都是变量。 变量的定义&#xff1a; 变量相当于内存中一个数据存储空间的表示&#…

Spring MVC常用注解及用法

目录 1.建立连接--RequestMapping 2.请求 2.1 传递单个参数 2.2 传递多个参数 2.3 传递对象 2.4 参数重命名--RequestParam 2.5 传递数组 2.6 传递集合 2.7 传递json数据--RequestBody 2.8 获取URL中参数--PathVariable 2.9 上传文件--RequestPart 2.10 获取Cookie--…

bomb 实验

GDB常用命令&#xff1a; GDB调试常用命令-CSDN博客 原理&#xff1a; 编译与反汇编过程-CSDN博客 Bomb实验实现 阶段一&#xff1a; 分析 分配空间&#xff1a;sub $0x8,%rsp 为局部变量分配栈空间。设置参数&#xff1a;mov $0x402400,%esi 将字符串地址加载到 %esi。…

MMsegmentation与MMdeploy简单使用

最近涉及到了图像分割的任务&#xff0c;于是拿来写下博客加深下使用。 MMsegmentation与MMdeploy的环境配置暂不做讲解&#xff0c;在官网和其他博客中有很多说明。 MMdeploy主要是把pt转为 onnx_int8的情况。 MMsegmentation环境配置可以参考 : 安装与配置MMSegmentation 目录…

【管理型文档】软件需求管理过程(原件)

软件需求管理规程应明确需求收集、分析、确认、变更控制及验证等流程&#xff0c;确保需求准确反映用户期望&#xff0c;支撑软件开发。该规程要求系统记录需求来源&#xff0c;通过评审确保需求完整、清晰、无歧义&#xff0c;实施变更控制以维护需求基线稳定&#xff0c;并持…

后端面试真题整理

面试问题整理 本人主要记录2024年秋招、春招过程中的疑难八股真题&#xff0c;参考来源&#xff1a;牛客网、知乎等。 八股 深拷贝与浅拷贝 浅拷贝&#xff1a; 浅拷贝会在堆上创建一个新的对象&#xff08;区别于引用拷贝的一点&#xff09;&#xff0c;不过&#xff0c;如果…

井盖丢失隐患大?智慧井盖监管系统帮你解决

在现代都市中&#xff0c;我们每天行走在钢筋水泥之间&#xff0c;却很少有人注意到脚下的小小井盖。这些不起眼的圆形铁盘不仅是城市地下管网的入口&#xff0c;更是维系城市生命线的重要组成部分。然而&#xff0c;当暴雨来袭&#xff0c;或是深夜无人之时&#xff0c;井盖的…