본문 바로가기

강남 아이티윌 오라클DBA과정 94기/RAC

[오라클 DBA 과정] 87일차 RAC(4) (2026-07-23)

# client tnsnames.ora

이거 tnsnames.ora 메모장 파일 racdb_taf_sess 밑에 추가해서 저장

racdb_taf_sel =
  (DESCRIPTION =
    (LOAD_BALANCE=YES)(FAILOVER=YES)
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.56.177)(PORT = 1521))
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.56.178)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = racdb)
      (FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC))
    )
  )


[oracle@rac1 ~]$ crsctl stat res -t
--------------------------------------------------------------------------------
Name           Target  State        Server                   State details
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.LISTENER.lsnr
               ONLINE  ONLINE       rac1                     STABLE
               ONLINE  ONLINE       rac2                     STABLE
ora.chad
               ONLINE  ONLINE       rac1                     STABLE
               ONLINE  ONLINE       rac2                     STABLE
ora.net1.network
               ONLINE  ONLINE       rac1                     STABLE
               ONLINE  ONLINE       rac2                     STABLE
ora.ons
               ONLINE  ONLINE       rac1                     STABLE
               ONLINE  ONLINE       rac2                     STABLE
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.ASMNET1LSNR_ASM.lsnr(ora.asmgroup)
      1        ONLINE  ONLINE       rac1                     STABLE
      2        ONLINE  ONLINE       rac2                     STABLE
      3        ONLINE  OFFLINE                               STABLE
ora.DATA.dg(ora.asmgroup)
      1        ONLINE  ONLINE       rac1                     STABLE
      2        ONLINE  ONLINE       rac2                     STABLE
      3        OFFLINE OFFLINE                               STABLE
ora.FRA.dg(ora.asmgroup)
      1        ONLINE  ONLINE       rac1                     STABLE
      2        ONLINE  ONLINE       rac2                     STABLE
      3        OFFLINE OFFLINE                               STABLE
ora.LISTENER_SCAN1.lsnr
      1        ONLINE  ONLINE       rac2                     STABLE
ora.asm(ora.asmgroup)
      1        ONLINE  ONLINE       rac1                     Started,STABLE
      2        ONLINE  ONLINE       rac2                     Started,STABLE
      3        OFFLINE OFFLINE                               STABLE
ora.asmnet1.asmnetwork(ora.asmgroup)
      1        ONLINE  ONLINE       rac1                     STABLE
      2        ONLINE  ONLINE       rac2                     STABLE
      3        OFFLINE OFFLINE                               STABLE
ora.cvu
      1        ONLINE  ONLINE       rac2                     STABLE
ora.qosmserver
      1        ONLINE  ONLINE       rac2                     STABLE
ora.rac1.vip
      1        ONLINE  ONLINE       rac1                     STABLE
ora.rac2.vip
      1        ONLINE  ONLINE       rac2                     STABLE
ora.racdb.db
      1        ONLINE  ONLINE       rac1                     Open,HOME=/u01/app/o
                                                             racle/product/19.0.0
                                                             /dbhome_1,STABLE
      2        ONLINE  ONLINE       rac2                     Open,HOME=/u01/app/o
                                                             racle/product/19.0.0
                                                             /dbhome_1,STABLE
ora.scan1.vip
      1        ONLINE  ONLINE       rac2                     STABLE
--------------------------------------------------------------------------------


[oracle@rac1 ~]$ srvctl status nodeapps
VIP 192.168.56.177 is enabled
VIP 192.168.56.177 is running on node: rac1
VIP 192.168.56.178 is enabled
VIP 192.168.56.178 is running on node: rac2
Network is enabled
Network is running on node: rac1
Network is running on node: rac2
ONS is enabled
ONS daemon is running on node: rac1
ONS daemon is running on node: rac2


C:\Users\ITWILL>sqlplus sys/oracle@racdb_taf_sess as sysdba

SYS@racdb_taf_sess> select instance_name, status from v$instance;

INSTANCE_NAME                    STATUS
-------------------------------- ------------------------
racdb1                           OPEN


PS C:\Users\ITWILL> sqlplus sys/oracle@racdb_taf_sel as sysdba

SYS@racdb_taf_sel> select instance_name, status from v$instance;

INSTANCE_NAME                    STATUS
-------------------------------- ------------------------
racdb1                           OPEN

 

cmd창 두 개 똑같이 맞춰놓은 상태에서 진행


putty rac1

[oracle@rac1 ~]$ srvctl status database -d racdb
Instance racdb1 is running on node rac1
Instance racdb2 is running on node rac2

위에서부터 차례대로 하나씩 enter 눌러서 실행
SYS@racdb_taf_sess> select * from all_objects;
SYS@racdb_taf_sel> select * from all_objects;
[oracle@rac1 ~]$ srvctl stop instance -d racdb -i racdb1

그러면 sess는 에러나고 sel은 잠깐 멈췄다가 계속 실행돼서 잘 마무리 됨.



rac1 인스턴스(putty창에서 srvctl stop하는 거 말고도 아예 서버(Virtual Box rac1)를 전원 꺼짐으로 종료해도 똑같이 돌아감.
sess랑 sel 둘 다 멈췄다가 sess는 오류 나고 sel도 멈췄다가 쭉 실행돼서 잘 마무리 됨.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


데이터딕셔너리정보들은 데이터딕셔너리테이블에 있는데 이 딕셔너리테이블은 시스템테이블스페이스에 있다.
매번 데이터딕셔너리테이블을 봐야 될 때가 많아서 디스크에 있는 거를 계속 읽는 게 비용이 부담이라 메모리에 쌓아놓자. => 데이터딕셔너리캐시

기존 실행계획을 쉐어링하면 비용이 줄어드니까 소프트파싱을 함. 동일한 SQL문장이 있는지 라이브러리캐시에서 조회하는 것.

select문 처리 단계 큰 그림만 물어봄. 그래도 execute단계와 fetch단계 때 latch 잡고 buffer lock을 무슨 모드로 잡고 이런 거 설명해야 함.
execute 때 데이터 버퍼 캐시에 찾는 블록이 없으면 물리적 I/O가 발생한다. 먼저 프리 버퍼를 확보하기 위해서
lru list의 보조리스트를 보고 프리버퍼가 있으면 거기에 exclusive모드로 buffer pin 찍고 디스크에서 올려서 데이터 적재하고
shared mode로 변경 후 hash테이블에 등록한다. 이런 것도 설명해줘야 함.
latch, mutex 이런 게 뭔지 세세한 건 안 물어봄.

값의 분포도에 따라 실행계획을 분리하는 작업도 생각해야 한다. 무조건 변수 처리하는 게 좋지 않다.

일반적인 select문 처리 단계에서 execute 단계는 library cache lock과 library cache pin을 shared mode로 잡고 블록 I/O(root블록 주소만 알면 다음 블록들 찾을 수 있음(b-tree구조)) 발생
=> active set결과 생성

RAC는 select문 처리 단계 execute 단계가 좀 다름. 
RAC에서는 물리적 I/O를 따로 발생하지 않는다. 10g부터는 데이터가 없으면 네트워크(?)로 노드들끼리 전송해준다. 이게 바로 캐쉬퓨전(cache fusion)
프리버퍼를 확보하는 거까진 똑같다. 
대상 블록이 어느 노드에 올라와 있는지 확인한다. 이거를 마스터 노드에서 체크함.
마스터노드가 어느 노드에 전송해달라고 요청함.
서로 다른 데이터버퍼캐시를 하나로 묶어서 사용하는 방식 => 글로벌 캐시

 


■ Global Cache(Data buffer cache)

RAC 시스템은 개별 인스턴스의 버퍼캐시를 통합해서 마치 하나의 글로벌 캐시처럼 사용하는 개념
사용자는 현재 특정 블록이 어떤 인스턴스의 버퍼캐시에 있는지 알 필요가 없으며 캐시 통합은 오라클 캐시 퓨전 메커니즘에 의해
자동으로 이루어진다.

 


■ Cache Fusion

- instance간에 데이터를 융합(fusion)해서 사용하는 것을 말하며 오라클이 RAC의 글로벌 버퍼 동기화 과정을 개념적으로 
설명하기 위해서 만든 용어
- instance간에 interconnect를 통한 효율적인 글로벌 버퍼 동기화를 수행한다.
- 디스크가 아닌 인터커넥트를 통한 블록 전송과 메모리 동기화가 캐시퓨전의 핵심이다.

 


■ GRD(Global Resource Directory)

- RAC를 구성하는 각 인스턴스들은 개별 자원들에 대한 메타정보를 GRD에서 관리한다.
- 분산 데이터베이스 일종이다. 분산 데이터베이스란 데이터베이스가 여러 노드에 걸쳐있다는 의미이다.
- 모든 블록의 정보는 블록이 속한 master node의 GRD에서 관리한다.
- 어느 노드에 최신의 데이터가 있는지에 대한 위치 정보와 락 정보를 Shared pool에서 관리한다.
- DBA(Data Block Address), hold node, mode(null, share, exclusive), role(local, global), SCN, PI(Past Image)
 => 이 정보들을 master node에서 관리한다.

 


■ GRD 관리하는 서비스

1. GCS(Global Cache Service)
- 노드 간의 데이터(블록)을 전송하는 서비스
- 데이터(블록) 전송 데몬(프로세스) : LMS
- 오라클 권장값은 cpu 개수가 4개마다 1개의 LMS 프로세스를 사용한다.

SYS@racdb1> show parameter gcs_server_processes

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
gcs_server_processes                 integer     1


SYS@racdb2> show parameter gcs_server_processes

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
gcs_server_processes                 integer     1

각각 하나씩 프로세스가 있다.

SYS@racdb1> ! ps -ef | grep lms -- OS에서 lms라는 문자열이 포함된 프로세스가 실제로 실행 중인지 확인하는 명령
oracle    4550     1  0 11:29 ?        00:00:09 asm_lms0_+ASM1
oracle    4978     1  0 11:29 ?        00:00:10 ora_lms0_racdb1
oracle   24015 23470  0 12:16 pts/0    00:00:00 /bin/bash -c  ps -ef | grep lms
oracle   24017 24015  0 12:16 pts/0    00:00:00 grep lms


SYS@racdb2> ! ps -ef | grep lms
oracle    3454     1  0 09:19 ?        00:00:51 ora_lms0_racdb2
oracle   10304     1  0 00:33 ?        00:02:26 asm_lms0_+ASM2
oracle   26799 26511  0 12:16 pts/0    00:00:00 /bin/bash -c  ps -ef | grep lms
oracle   26801 26799  0 12:16 pts/0    00:00:00 grep lms




2. GES(Global Enqueue Service)
- 노드 간의 발생하는 lock을 관리하는 서비스
- 글로벌 enqueue 담당하는 데몬: LMD, LCK

SYS@racdb1> ! ps -ef | grep lmd
SYS@racdb1> ! ps -ef | grep lck

SYS@racdb2> ! ps -ef | grep lmd
SYS@racdb2> ! ps -ef | grep lck




3. CGS(Cluster Group Service)
- 클러스터 멤버십을 관리
- 클러스터를 모니터링하면서 노드의 가입이나 탈퇴에 따른 클러스터의 상태 관리
- 데몬 : LMON

SYS@racdb1> ! ps -ef | grep lmon

SYS@racdb1> ! ps -ef | grep lmon
oracle    4548     1  0 11:29 ?        00:00:11 asm_lmon_+ASM1
oracle    4957     1  0 11:29 ?        00:00:10 ora_lmon_racdb1
oracle   27551 23470  0 13:43 pts/0    00:00:00 /bin/bash -c  ps -ef | grep lmon
oracle   27553 27551  0 13:43 pts/0    00:00:00 grep lmon


select inst_id, pool, name, bytes
from gv$sgastat
where name like 'gcs%'; -- 이거는 그냥 이런 기능들이 있구나 정도로만 알면 됨. 뭐하는 건지는 몰라도 됨. shared pool에서 관리함.

SYS@racdb1> select account_status from dba_users where username = 'HR';

ACCOUNT_STATUS
--------------------------------
EXPIRED & LOCKED

해결방법은 비밀번호 설정, 계정 풀기.
alter user hr identified by hr account unlock;
alter user 유저명 identified by 비밀번호 account unlock;


select
        dbms_rowid.rowid_relative_fno(rowid) as file_no,
        dbms_rowid.rowid_block_number(rowid) as block_no
from hr.employees
where employee_id = 100;

rowid의 파일번호, 블록번호 추출 (= Database address 추출)

SYS@racdb1> select
        dbms_rowid.rowid_relative_fno(rowid) as file_no,
        dbms_rowid.rowid_block_number(rowid) as block_no
from hr.employees
where employee_id = 100; 

   FILE_NO   BLOCK_NO
---------- ----------
         3      31276


# master node
블록의 최신정보를 GRD에 저장관리하는 노드
# holder node
최신 블록을 가지고 있는 노드
# request node
master node에게 블록 전송을 요청하는 노드

 


■ 처음으로 블록을 select

클러스터 내에서 블록을 최초로 읽어(select)들이는 노드는 디스크 I/O를 통해 자신의 버퍼 캐시로 블록을 읽게 된다.
select * from hr.employees where employee_id = 100;

# [3, 31276]
# master node : rac2 node
# request node : rac1 node

물리적 I/O 발생 시 프리버퍼를 찾는 거까지는 동일

1) rac1 노드에 접속한 사용자가 [3, 31276] 블록을 읽기 요청한다.
   해당 블록을 null모드로 획득한다.
2) rac1 노드는 [3, 31276] 블록의 마스터 노드인 rac2 노드에게 블록 전송을 요청한다.
    요청 후 응답이 올 때까지는 gc cr request 이벤트로 대기한다.(global cache consistent read request => gc cr request)
3) 마스터 노드인 rac2 노드는 GRD를 [3, 31276] 블록을 체크하는데 어떤 인스턴스도 [3, 31276] 블록을 버퍼 캐시에 가지고 있지 않다는 것을 
    확인하면 rac2 마스터 노드는 rac1 노드에게 [3, 31276] 블록을 공유 모드로 블록을 버퍼 캐시에 적재할 수 있는 권한을 부여한다.
    요청한 노드는 gc cr grant 2-way 이벤트로 대기한다.
4) 권한을 받은 rac1 노드는 [3, 31276] 블록을 디스크에서 읽어 들인다.
    이때 db file sequential read 대기 이벤트가 발생한다.(블록 하나 올릴 때의 대기 이벤트)
    메모리에 올린 블록은 null모드를 shared mode로 변경한다.
5) 마스터 노드인 rac2노드에 GRD에 [3, 31276] 블록의 최신 정보로 갱신한다.

* buffer lock(블록 헤더에 찍는 것)이랑 RAC에서의 블록(블록 자체의 상태) 모드는 서로 다른 것이다. 혼동하지 말 것!

 

SYS@racdb1> select
        dbms_rowid.rowid_relative_fno(rowid) as file_no,
        dbms_rowid.rowid_block_number(rowid) as block_no
from hr.employees
where employee_id = 100;  
   FILE_NO   BLOCK_NO
---------- ----------
         3      31276


SYS@racdb1> alter system flush buffer_cache;

System altered.

SYS@racdb2> alter system flush buffer_cache;

System altered.

SYS@racdb1> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;

no rows selected

SYS@racdb2> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;

no rows selected


<<RAC1 NODE hr session>>
HR@racdb1> select * from hr.employees where employee_id = 100;

EMPLOYEE_ID FIRST_NAME           LAST_NAME                 EMAIL                     PHONE_NUMBER        HIRE_DATE JOB_ID          SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID
----------- -------------------- ------------------------- ------------------------- -------------------- --------- ---------- ---------- -------------- ---------- -------------
        100 Steven               King                      SKING                     515.123.4567        17-JUN-03 AD_PRES          24000                                      90


<<RAC1 NODE SYS SESSION>>
SYS@racdb1> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;

LOCK_ELEMENT_ADD STATUS      MODE_HELD      LOCAL
---------------- ---------- ---------- ----------
0000000080FB37B0 scur                1          1  
scur => shared mode

 


# STATUS :  scur(shared current) : 공유모드의 현재 블록, RAC에서의 의미
 클러스터 내의 같은 블록에 대해 여러 인스턴스가 scur모드의 블록을 가질 수 있다.
# MODE_HELD : 0(null), 1(shared, select), 2(exclusive, dml)
# LOCAL : 1(local, 글로벌 변경이 이루어지지 않았다.), 0(global, 글로벌 변경이 이루어지고 있다.)

SYS@racdb2> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;

no rows selected


SYS@racdb1> select inst_id, sid, event, total_waits, time_waited 
 from gv$session_event 
 where (inst_id,sid) in (select inst_id, sid from gv$session where username = 'HR');


 INST_ID        SID EVENT                                                        TOTAL_WAITS TIME_WAITED
---------- ---------- ------------------------------------------------------------ ----------- -----------
         1        282 Disk file operations I/O                                               4           0
         1        282 IPC group service call                                                 2           0
         1        282 db file sequential read                                               67           3
         1        282 gc cr grant 2-way                                                     27           1
         1        282 library cache pin                                                      5           0
         1        282 library cache lock                                                     7           0
         1        282 SQL*Net message to client                                              9           0
         1        282 SQL*Net message from client                                            8        1742
         1        282 events in waitclass Other                                             23           0

 



■ 동일한 블록에 대해서 select(shared) - select(shared)

# [3, 31276]
# master node : rac2 node
# request node : rac2 node
# hold node : rac1 node

rac2 노드에 접속한 세션이 SELECT문을 실행했고, 필요한 [3, 31276] 블록이 rac2의 버퍼 캐시에 없어서 rac1으로부터 전달받는 상황

1) rac2 노드에 접속한 사용자는 [3, 31276] 블록을 읽기 요청한다.([3, 31276] 블록 null모드)
   rac2 노드의 [3, 31276] 블록의 마스터 노드에게 요청한다. 요청 후 응답이 올 때까지 gc cr request 대기 이벤트가 발생한다.
2) 요청 받은 master node는 GRD를 통해 해당 블록이 rac1 노드에 있다는 것을 확인한다.
3) master node는 rac1 노드에게 [3, 31276] 블록을 rac2 노드로 보낼 것을 요청한다.
4) 요청 받은 rac1 노드는 [3, 31276] 블록을 interconnect를 통해서 rac2 노드에게 전송한다. 이때가 cache fusion이 발생할 때이다. rac2 노드는 [3, 31276] 블록을 받을 때까지 gc cr block 2-way 이벤트로 대기한다.
5) 전송 받은 rac2 노드의 [3, 31276] 블록은 null모드에서 shared 모드로 갱신한 후 마스터 노드에게 최신 정보를 갱신하도록 요청한다.

 

<<RAC1 SYS SESSION>>
SYS@racdb1> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276; -- rac1에는 블록을 보유함.  

LOCK_ELEMENT_ADD STATUS      MODE_HELD      LOCAL
---------------- ---------- ---------- ----------
0000000080FB37B0 scur                1          1


<<RAC2 SYS SESSION>>
SYS@racdb2> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;  

no rows selected


<<RAC2 HR SESSION>>
HR@racdb2> select * from hr.employees where employee_id = 101;

EMPLOYEE_ID FIRST_NAME           LAST_NAME
----------- -------------------- -------------------------
EMAIL                     PHONE_NUMBER         HIRE_DATE JOB_ID         SALARY
------------------------- -------------------- --------- ---------- ----------
COMMISSION_PCT MANAGER_ID DEPARTMENT_ID
-------------- ---------- -------------
        101 Neena                Kochhar
NKOCHHAR                  515.123.4568         21-SEP-05 AD_VP           17000
                      100            90


<<RAC1 SYS SESSION>>
SYS@racdb1> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276; -- 블록 갖고 있는 거 그대로 유지

LOCK_ELEMENT_ADD STATUS      MODE_HELD      LOCAL
---------------- ---------- ---------- ----------
0000000082FF8090 scur                1          1


<<RAC2 SYS SESSION>>
SYS@racdb2> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276; -- rac1로부터 블록 전송 받음.

LOCK_ELEMENT_ADD STATUS      MODE_HELD      LOCAL
---------------- ---------- ---------- ----------
0000000082FF8090 scur                1          1



rac2에서 SELECT 실행
→ rac2가 해당 블록의 마스터
→ rac1이 블록을 보유
→ rac1에서 rac2로 CR 블록 전송
→ Cache Fusion 발생
→ gc cr block 2-way 기록

 


■ 동일한 블록에 대해서 shared(select) - exclusive(dml)

# [3, 31276]
# master node : rac2 node
# request node : rac2 node(exclusive)
# hold node : rac1 node(shared)

rac2노드에서 트랜잭션 발생
exclusive 모드로 바꾸고 GRD 갱신
rac1노드는 계속 null모드 -- 그치만 사용할 수 없음.
commit이나 rollback을 했는지, 아니면 dml문 수행하고 commit이나 rollback을 하지 않은 건지에 따라 또 달라지는데
그건 다음에..!

1) rac2 노드 사용자가 [3, 31276] 블록을 쓰기 요청한다.
    [3, 31276] 블록의 마스터 노드에게 쓰기 요청을 한 후 응답이 올 때까지 gc current request 이벤트로 대기한다.
(여기서는 gc cr아님. gc current)
2) 마스터 노드는 GRD를 통해서 rac1 노드가 동일한 블록에 대해서 shared 모드로 가지고 있는 것을 확인한다.
3) 마스터 노드는 rac1 노드에게 [3, 31276] 블록에 대해서 shared 모드를 null모드로 다운그레이드 요청한다.
4) rac2 노드는 [3, 31276] 블록에 대해서 exclusive 모드로 변경한다. 이때까지 gc current block 2-way 이벤트로 대기한다.
5) 마스터 노드 GRD 정보를 [3, 31276] 블록 정보 갱신

 

<<RAC1 NODE SYS SESSION>>
SYS@racdb1> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;

LOCK_ELEMENT_ADD STATUS      MODE_HELD      LOCAL
---------------- ---------- ---------- ----------
0000000080FB37B0 scur                1          1   
scur => shared mode

<<RAC2 NODE SYS SESSION>>
SYS@racdb2> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;

LOCK_ELEMENT_ADD STATUS      MODE_HELD      LOCAL
---------------- ---------- ---------- ----------
0000000080FB37B0 scur                1          1   
scur => shared mode


<<RAC2 NODE HR SESSION>>
update hr.employees set salary = salary * 1.1 where employee_id = 101;


<<RAC1 NODE SYS SESSION>>
SYS@racdb1> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;  

no rows selected   -- null모드


<<RAC2 NODE SYS SESSION>>
SYS@racdb2> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;  

LOCK_ELEMENT_ADD STATUS      MODE_HELD      LOCAL
---------------- ---------- ---------- ----------
0000000082FF8090 xcur              2          1

xcur => exclusive 모드


<<RAC2 NODE HR SESSION>>
HR@racdb2> rollback;

Rollback complete.

SYS@racdb1> select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;  

no rows selected


SYS@racdb2>  select b.lock_element_addr, b.status, e.mode_held, e.local
from v$bh b, v$gc_element e
where b.lock_element_addr = e.gc_element_addr
and b.file# = 3
and b.block# = 31276;  

LOCK_ELEMENT_ADD STATUS      MODE_HELD      LOCAL
---------------- ---------- ---------- ----------
0000000082FF8090 xcur                2          1