RMAN-03009 and ORA-27052 Due to Opportunistic Locking
12/31/2012 12:20:00 PM
Gönderen Mete Karar
While backing up backup sets to a secondary location which was a Windows share, RMAN job failed with the following error:
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03009: failure of backup command on ORA_DISK_1 channel at sometime
ORA-27052: unable to flush file data
Linux-x86_64 Error: 5: Input/output error
When I digged up a little bit, I found the following lines in server's system log:
<host> kernel: CIFS VFS: No response to cmd 47 mid 2921
<host> kernel: CIFS VFS: Write2 ret -11, wrote 0
<host> kernel: CIFS VFS: Write2 ret -112, wrote 0
<host> kernel: CIFS VFS: Write2 ret -11, wrote 0
<host> kernel: CIFS VFS: Write2 ret -11, wrote 0
The problem was caused by optimistic locking property of CIFS module. If the file you are copying is large enough (in my case it was about 80 GB) through a CIFS channel, you may hit this problem. By default optimistic locking is set to 1 when the module is loaded. Disabling optimistic locking solves the problem with no performance drawback, at least I haven't observed.
To disable optimistic locking:
$ echo 0 > /proc/fs/cifs/OplockEnabled
ETL with Bulk Insert Using ODP.Net
12/12/2012 01:48:00 AM
Gönderen Mete Karar
First one is row-by-row basis. Pseudo code representing the case is as below:
For each row in the file
Read row;
Do transformations of the row;
Insert row;
loop;
To execute insert statements, I will use the method below. It takes advantage of bind variable to avoid hard parsing.
private void ExecuteNonQuery(string commandText, Dictionary<string, object> parameters)
{
using (OracleCommand comm = new OracleCommand(commandText))
{
if (orclConn.State != System.Data.ConnectionState.Open)
orclConn.Open();
comm.Connection = this.orclConn;
foreach (KeyValuePair<string, object> kvp in parameters)
comm.Parameters.Add(kvp.Key, kvp.Value);
comm.ExecuteNonQuery();
}
}
Begin a transaction: OracleCommand comm = GetTransaction();
For each row in the file
Read row;
Do transformations of the row;
Insert row: ExecuteNonQuery(comm, "<insert statement>", parameters);
loop
Commit transaction: comm.Transaction.Commit();
Methods referenced above are:
private OracleCommand GetTransaction()
{
OracleTransaction dbTran = this.BeginTransaction;
OracleCommand comm = new OracleCommand();
comm.Connection = this.orclConn;
comm.Transaction = dbTran;
return comm;
}
private void ExecuteNonQuery(OracleCommand comm, string commandText, Dictionary<string, object> parameters)
{
comm.CommandText = commandText;
foreach (KeyValuePair<string, object> kvp in parameters)
comm.Parameters.Add(kvp.Key, kvp.Value);
comm.ExecuteNonQuery();
}
- Every three seconds,
- When someone commits,
- When switching log file,
- When redo buffer gets full 1/3 of it or has 1 MB of cached redo log data
To insert rows using array binding, required code:
These are the good, the bad and the ugly (if we skip using bind variable, it could be uglier) methods of bulk insert.