Saturday, February 27, 2021

Exadata - Oracle Hardware -- SFP Transceiver types & models

Yesterday, one of my collegues made me revisit the following article that I wrote after completing a field operation in an Exadata environment.

Exadata -- How to Connect Oracle Exadata to 10G Networks Using SFP Modules

The subject was about activating SFP modules and the related network on Exadata.. The question was the type/model of the transceivers that I have used while accomplishing the task that I shared in the article..

Actually, it's been a while since I did that job. I did not include that detail in my blog post either, but I could hardly remember that I have used the transceivers customer already had.. The client bought the transceivers from Oracle long time ago, longer than the time I start working there as the lead consultant :)
This was a good question indeed.. So I though about it and made a little research..

I guess the transceiver model was something similar to X2124A-N. So, one can position transceivers that meet similar standards. The general idea is to be compatible with the switch side. But as we have oracle hardware (Exadata) in the picture -- at least on one side, we need to be compatible with the oracle hardware as well - in the first place actually.. So using oracle supplied transceivers is the best idea, but similar transceivers should also work.

Anyways, we ended up with the following document -> 

Oracle's 10 Gigabit Ethernet Transceivers and Cables Frequently Asked Questions

Still the idea given in the paragraph above applies.. As we may not have Oracle switches in the custom environment, I mean as we may have to work with customer supplied 3rd party switches, being compatible with the switch side should be on our focus as well..

That is it.. I wish you a good weekend :)

Monday, February 15, 2021

RDBMS / RAC -- Inteconnect: RDS , IPC , RAC relink/make, skgxpinfo & ORA-27300 - bind_fail

Recently my team reported this issue to me.. An Oracle 11.2.0.4 database couldn't start on an Exadata with a freshly installed RAC Home. Startup was encountering ORA-27300 errors and it was clear that we couldn't bind to a ip:port during initial phase of the instance startup...

ORA-00603: ORACLE server session terminated by fatal error
ORA-27504: IPC error creating OSD context
ORA-27300: OS system dependent operation:bind failed with status: 11
ORA-27301: OS failure message: Resource temporarily unavailable
ORA-27302: failure occurred at: sskgxpsoc

or

ORA-00603: ORACLE server session terminated by fatal error
ORA-27504: IPC error creating OSD context
ORA-27300: OS system dependent operation:bind_fail failed with status: 0
ORA-27301: OS failure message: Error 0
ORA-27302: failure occurred at: skgxpvifconf
ORA-27303: additional information: requested interface X.X.X.X failed bind. Check output from ifconfig command

These errors in the bottom stack can be sskgxpsoc and/or skgxpvifconf and according to the following MOS note, we have some patches already available for these types of issues.

Getting ORA-00603, ORA-27504, ORA-27300, ORA-27301, ORA-27302; with "bind failed" with EAGAIN and "bind_fail failed", on "sskgxpsock" and "skgxpvifconf" (Doc ID 1524444.1)

We have also workaround and it is based on setting cluster_interconnects parameter to the infiniband ip addresses.

In this blog post, I want to go a little bit further on this topic and give you some extra information about RDS, IPC and the related libraries linked or made available for Oracle to use for interconnect and the relation between these types errors and the RDS/IPC interconnect configuıration.

It is all about oracle binaries, the libraries used by them and the options used while relinking/make'ing oracle...

If you relink ioracle with RDS (ipc_rds), then you need to have interfaces that support RDS in your environment and in this kind of an environment, you set the cluster_interconnects and tell oracle -> use them!

Of course we are talking about this environment where there is no functionality like finding available interfaces automatically. I mean, if you don't have an infiniband-like interface, then you need to turn off rds. Oracle just doesn't start even when we set the cluster_interconnect to the IP adresses of a classical tcp/udp ethernet interface. It just can't bind... This is what is seen even on single node environments.

If you are going to use a single node non-rac, you can link the  ioracle with rac_off.. I mean, you can disable the rac option, and this move solves our problem as well.... 
Eventually, relinking with rac_off removes the rds mode. Note that, relinking with rac_on uses the configuration as is...(unless we have an ipc_none -- dummy configuration .. I will touch on this topic later) 

I mean, if your oracle binary is linked with rds, it will be relinked with rds even after you relink your oracle with rac_on.. So rac_off disables the rds mode and enables the ipc_g mode, but rac_on leaves it as is.. (at least in 11.2.0.4 :))

You can understand this by reviewing the related make file or outputs of the relink command;

$ORACLE_HOME/rdbms/lib/ins_rdbms.mk rac_off ioracle
rm -f /u01/dbebs/PROD/db/tech_st/11.2.0/lib/libskgxp11.so
cp /u01/dbebs/PROD/db/tech_st/11.2.0/lib//libskgxpg.so .
/u01/dbebs/PROD/db/tech_st/11.2.0/lib/libskgxp11.so

Note that --> libskgxpg is the non RDS one.. IPC related one.. So rac_off make oracle to use that..

Rds enabled or not; after those make operations; the library name used by Oracle is libskgxp11 .. However; its contents are different.. It is actually based on the relink options used. 

If we use rds on ( ipc_rds), the library named libskgxpr is used (I mean it is renamed and copied as libskgxp11.. If we use no rds (ipc_g), the library named libskgxpg is used (it is renamed and copied to libskgxp11)

If you want to see what oracle is currently linked to (or more precisely; to see which library oracle is currently configured to use for interconnect related things), you can use the command below ->

[oracle@ebstestdb lib]$ $ORACLE_HOME/bin/skgxpinfo -v
Oracle UDP/IP (generic)

the name skgxp is related to -> system kernel generic interface inter-process communications

skgxpinfo is just a little binary available in Oracle Home for getting that info...

But! How do I check that manually? :)

If rds is off (ipc_g) ->

[oracle@ebstestdb lib]$ strings /u01/dbebs/PROD/db/tech_st/11.2.0/lib/libskgxp11.so |grep -i sskgxphack| awk '{print $16}'

output: skgxpg_rds_off.c -> This means oracle uses ipc_g :)

Actually, we have the following string in libskgxp11.so;

-> comment:Intel(R) C++ Compiler for applications running on Intel(R) 64, Version 10.1 Build 20100527 %s : skgxpg_rds_off.c

If rds is on (ipc_rds)

We can check with the same command that we used above and expect to see sskgxphack.c as the output(rather than kgxpg_rds_off.c)

[oracle@ebstestdb lib]$  strings /u01/dbebs/PROD/db/tech_st/11.2.0/lib/libskgxp11.so |grep -i sskgxphack| awk '{print $16}'

This way we get that info we need manually: ) Note that, we see sskgxphack.c when the rds is on.

Actually, we have the following string in libskgxp11.so; ->comment:Intel(R) C++ Compiler for applications running on Intel(R) 64, Version 10.1 Build 20100527 %s : sskgxphack.c

One last note, we have also an entry named ipc_none in the ins_rdbms.mk (makefile) and this seems to be a dummy driver for IPC. As far as I can see, this ipc_none is used while deinstalling Oracle software using the installer (OUI). Other than that, I don't see a point of using that.. When we relink an oracle binary with rac_on, which is currently have ipc_none configuration, it is automatically configured as ipc_g .. Well, that's the last thing I want to mention on this topic :)

Wednesday, February 10, 2021

RDBMS -- Failed add column operation may cause ORA-14097 & ORA-14278 during Partition Exchange

Recently an interesting issue escalated to me..

Customer was complaining about failed queries on a partitioned table..

The problem was obvious.. This database environment was created using rman duplicate with "SKIP TABLESPACE".. Well, SKIP TABLESPACE options was used for the duplicate, and the problem was caused by the missing datafiles mapped to some partitions of that partitioned table..

Note that, database version was 18C and customer didn't need the data in those problematic partitions.

Before, escalating the issue, customer also tried to add some columns to this table and got ORA-00376, ORA-01111 and ORA-01110.. Actually, this was no suprise.. The datafiles of some partitions were missing, as a result of duplicating this database with SKIP tablespace option.

In this kind of a case, we create a new empty dummy table with the same structure as our original partitioned one, and then we exchange partitions between this new empty table and our partitioned table to get rid of those empty/unneeded partitions which are mapped to missing data files..

However; customer tried to add a column to this table without this partition exchange thing and got those errors mentioned above.

Also, this failed add column action left unused column in the partition table... So because of those unused columns in the table, exchange partition action was encountering "ORA-14278: column type or size mismatch in EXCHANGE SUBPARTITION".

Here is the action plan to workaround this situation;

  • alter session set events '14529 trace name context forever, level 512'
  • CTAS  to create the new empty partitioned table
  • EXCHANGE PARTITION for those problematic partitions between the newly created partitioned table and the original one..

Important  Note: "Level 512" is a must. I see similar blog posts and Oracle Support notes, but level 512 is missing. "In this case", using Level 512 in that event is a must.

Note that; -> event 14529 has been enhanced with level 512 to handle the cases like the following  for exchange partition operations;

unusable columns, invisible columns

fast add of nullable columns with default value

fast add of not nullable columns with default value, long varchar columns, virtual expression columns and so on..

Tuesday, February 9, 2021

OVM - Changing Cluster Heartbeat nw, Questions related to High availability & DR, Comments on bond device problems - LACP activity unknown , LACP suspend-individual

Recently I was asked 4 interesting questions. Questions about OVM... In this blog post, I will share my answers and comment for these questions.. This might help for OVM users.

The first question was about OVM clusters, about cluster heartbeat nework.. Specifically about changing the heartbeat network and having more than one cluster heartbeat network.

This operation is a little costly. Requires VM shutdown etc. If there is an available port in the environment, it can be added to the corresponding heartbeat bond. What is important here is that, both port and switch redundancy in the relevant network path...

We shared the Oracle Support notes below.. These notes may be followed to change the Cluster Heartbeat network;

  • OVM - How to Migrate Cluster HeartBeat Network Channel To A Different Bonded Interface Of An Existing Deployment (Doc ID 2408148.1)
  • How to Move the Heartbeat from One Network to Another in Oracle VM (Doc ID 1995619.1)
  • How to Move the Heartbeat from One Network to Another in OVM3 (Doc ID 1504140.1) – This method may not work on OVM 3.4.. The other documents above seems more promising.

About having a heartbeat channel with more than one network;

We shared that; there was a change on OVVM 3.3.x that prevented having multiple networks with the cluster heartbeat role on a single server. So adding additional networking to the Cluster Heartbeat will probably not work. Add job will get an error like the following;->

“Cannot add Ethernet device: eth1 on oraclevm, to network: hearbeat, because server: oraclevm, already has cluster network”. 

Even if VM Manager shows added, we think it will not be added in the background .. Of course you can test. 

Second question was related with the general steps for having a DR for OVM environments.

As for implementing DR, we shared the following ateam document.. Method explained in that document is applicable for this task (ocfourse if you have the necessary infrastructure to support the methods that is used in that document)

https://www.ateam-oracle.com/oracle-vm-storage-repository-replication-for-on-premise-fusion-applications-disaster-recovery

Third question was about the reason why auto switchover not work.. I mean when one of the VM nodes in an OVM cluster crashes or fails, the relevant VM guests do not switch to the other standing node (they don't start from the other node, although we see that the server pool is clustered)

Analysis showed that this situation was an expected behavior. Although there was an OVM cluster, the Enable High Availability checkbox was not selected for the relevant VMs.

As for the solution; we recommended that the relevant checkbox be marked for the relevant VMs.

Following diagram shows that decision mechanism clearly..

Ref:  https://docs.oracle.com/cd/E27300_01/E27309/html/vmusg-svrpool-ha.html

To automatically configure the server pool cluster and enable HA in a server pool, select the Clustered Server Pool check box when you create or edit a server pool. See Section 6.7, “Creating a Server Pool” and Section 6.8.3, “Editing a Server Pool” for more information on creating and editing a server pool.

To enable HA on a virtual machine, select the Enable High Availability check box when you create or edit a virtual machine. See Section 7.7, “Creating a Virtual Machine” and Section 7.9.2, “Editing a Virtual Machine” for more information on creating and editing a virtual machine.


The last question was about bonding-LACP configuration.. The problem was a suspended port.. The port to which one of the slaves of a bond with a Bonding-LACP configuration was suspended..

Error messages in the logs on the switch side -> "LACP activity unknown", "LACP suspend-individual".

Bonding configuration and syslogd messages of OVM have been checked. There was no misconfiguration.. There wasn't any log record that could directly cause this problem.

The problem was solved by restarting the eth devices of the related bonds that were suspended. (example commands: ifdown eth7, ifup eth7)

After these moves, we observed that the ports of those interfaces were not suspended again.

We recommended the following;

In case problem reoccurs, a detailed analysis on the switch side should be done. Disabling the "LACP suspend-individual" setting should also be considered.

This setting is already shown disabled in some MOS notes related to Exadata ;

* Configure Exadata X8M Backup 40gbe ZS5-2 and ZS5-4 (Doc ID 2698913.1)
* Set Up and Configure Exadata X8M Backup with ZFS Storage ZS7-2 (Doc ID 2635423.1)

This environment was not an Exadata, but OVM is similar to Oracle Linux, which is what we have in Exadata.

Also, Redhat have some documents on the same subject, recommending the same solution ->

* LACP Linux Bonds not working properly on Cisco Nexus 9000-series switches

https://access.redhat.com/solutions/3702541

* Resolution: Disable LACP suspend-individual on the Cisco access port

As far as we can see, some switches also have these suspend-individual bugs.

At the end of the day,  those suspend individual messages didn't appear again.. We suggested  the setting -> "no lacp suspend-individual" on the switch side.. ( if the problem reappears in the future)

Sunday, February 7, 2021

RDBMS -- Analyze AWR reports (part by part /section by section) using Python

I like dealing with Python nowadays. By using Python (I used to use perl for these types of things), I am trying to address some issues, especially in environments with Oracle products.  
In this blog post, I will share a python code (it is not finished yet.. it is not final) that can be used to read AWR reports (AWR reports in text format).. 
This code is written just for making a POC, for showing how we can read AWR reports section by section, and load the data that we read into the arrays and use that AWR data for making recommendations. 

The comments in the code are already clear, so you can understand what we are doing here..
Basically, we read a 11.2.0.4 AWR report, certain parts of it.. Then we populate our arrays.. Once our arrays are populated with AWR data, we check some performance indicators and make our comments and give our recommendations accordingly.

Here is the output of a demo run.. The system we analyze here had a hard parse problem.


#!/usr/bin/python
"""
AWR ANALYZER -- work in progress by Erman Arslan
Creation date : 07.02.2021
"""
#import modules

import re

#declarations

ins_load_array_2d=[]
all_lines=[]
load_profile_array=[]
cpu_core_count_array=[]
instance_efficiency_array=[]
dbtime_elapsed_array=[]
timed_model_array=[]

pattern1= re.compile("Load Profile", re.IGNORECASE)
pattern2= re.compile("Instance Efficiency Percentages", re.IGNORECASE)
pattern3= re.compile("~~~~~~~~~~~~~~", re.IGNORECASE)


pattern4= re.compile("Host Name", re.IGNORECASE)
pattern5= re.compile("Snap Id", re.IGNORECASE)
pattern6= re.compile("---------------- ", re.IGNORECASE)


pattern7= re.compile("Instance Efficiency Percentages", re.IGNORECASE)
pattern8= re.compile("Top 10 Foreground Events by Total Wait Time", re.IGNORECASE)
pattern9= re.compile("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~", re.IGNORECASE)

pattern10= re.compile("End Snap:", re.IGNORECASE)
pattern11= re.compile("Instance Efficiency Percentages", re.IGNORECASE)
pattern12= re.compile("~~~~~~~~~~~~~~", re.IGNORECASE)
pattern13= re.compile("Time Model Statistics", re.IGNORECASE)
pattern14= re.compile("Operating System Statistics", re.IGNORECASE)
pattern15= re.compile("------------------------------------------------------", re.IGNORECASE)

#functions

def read_awr(startword,endword,ignoreword):
   concantrated_lines=[]
   ins_load_string=""
   i=0
   global ins_load_array_2d
   ins_load_array_2d=[]
   for single_line in all_lines:
       i=i+1
       if startword.search(single_line) != None:
         concantrated_lines.append(single_line.rstrip('\n'))
         for i in range(i,len(all_lines)):
          if endword.search(all_lines[i]) != None:
            break
          if endword.search(all_lines[i]) == None and ignoreword.search(all_lines[i]) == None:
            ins_load_string += all_lines[i]
   ins_load_array=re.split('\n',ins_load_string.strip())
   for k in ins_load_array:
     temp_array=re.split(r'\s{2,}',k.strip())
     ins_load_array_2d.append(temp_array)


#MAIN.. OUR PROGRAM START HERE
awr_file='/home/oracle/awr_analyzer/awr_report.txt'
my_awr_file=open(awr_file, 'r')
for line in my_awr_file:
  all_lines.append(line)

print "\nThis is just a DEMO! It is like POC for our ability to analyze AWR reports programatically!\n"
print "\nAnalyzing awr report file->", awr_file,"\n"

#reading the load profile section
read_awr(pattern1,pattern2,pattern3)
load_profile_array= ins_load_array_2d

#reading the cpu core counts section
read_awr(pattern4,pattern5,pattern6)
cpu_core_count_array=ins_load_array_2d

#reading the Instance Efficiency Section

read_awr(pattern7,pattern8,pattern9)
instance_efficiency_array=ins_load_array_2d

#Reading DB Time and Elapsed Section

read_awr(pattern10,pattern11,pattern12)
dbtime_elapsed_array=ins_load_array_2d

#Reading Time Model Section
read_awr(pattern13,pattern14,pattern15)
timed_model_array=ins_load_array_2d

#####################################################################
#We populated our array.. 
#Now let's check some the performance indicator values stored on those arrays 
#and make some recommendations
######################################################################

#Getting values from time model section

total_db_cpu_time_temp=[string for string in timed_model_array if "DB CPU" in string]
total_db_parse_time_temp=[string for string in timed_model_array if "parse time elapsed" in string]
total_db_hardparse_time_temp=[string for string in timed_model_array if "hard parse elapsed time" in string]
total_sqlexecute_time_temp=[string for string in timed_model_array if "sql execute elapsed time" in string]
total_db_cpu_time=total_db_cpu_time_temp[0][1]
total_db_parse_time=total_db_parse_time_temp[0][1]
total_db_hardparse_time=total_db_hardparse_time_temp[0][1]
total_sqlexecute_time=total_sqlexecute_time_temp[0][1]

#Getting values from instance efficiency section

execute_to_parse=instance_efficiency_array[3][1]
parse_cpu_to_parse_elapsed=instance_efficiency_array[4][1]

#Getting values from load profile section
hard_parses=load_profile_array[13][1]
total_parses=load_profile_array[12][1]
total_executed_sql=load_profile_array[16][1]

#Getting values from db time elapsed section

elapsed_time=dbtime_elapsed_array[0][1]
db_time=dbtime_elapsed_array[1][1]
elapsed_time=elapsed_time.replace(' (mins)','')
db_time=db_time.replace(' (mins)','')

#Getting values from cpu core count section
core_count=cpu_core_count_array[0][2]


#Making some comments/recommendations
print "\nCOMMENTS and RECOMMENDATIONS"
print "--------------------------------"
if float(db_time) > float(elapsed_time)*float(core_count)*float(0.75):
  print "-Note : We have",core_count," core/cores in this machine.\n*DB Time is pushing the limits.. Higher than %75 of the total resources..\n -Note : DB Time is the total Oracle CPU consumption plus + sum of non-idle wait time.\n "

if float(hard_parses)>float(total_parses)/10:
  print "*We are doing lots of hard parses.. Hard parse / Total parse ratio is  %", format(float(hard_parses)/float(total_parses)*100,'.2f')
  print "*Total parse / Execute ratio is %", format(float(total_parses)/float(total_executed_sql)*100,'.2f')
  print "*We spent %",parse_cpu_to_parse_elapsed," of our parse time on the CPU..."
  print "*Parsing takes place in %",100-float(execute_to_parse)," of the executions.."
  print "*%",format(float(total_db_hardparse_time)/float(total_sqlexecute_time)*100,'.2f')," of total sql elapsed time is spent on hard parsing..\n->Fixing this hard parse issue will have a positive effect on response time."

Monday, February 1, 2021

Erman Arslan's Oracle Forum -- January 2021 - "Questions and Answers Series"

Question: How much time do you spend/lose?

Answer: Well, how much time I gain? :) 

Remember, you can ask questions and get remote support using my forum.
Just click on the link named "Erman Arslan's Oracle Forum is available now.
Click here to ask a question", which is available on the main page of Erman Arslan's Oracle Blog -- or just use the direct link:



Come on, let's see what we've been up to this month. (Do not forget to read the blog posts too :)