Hi All,
I am trying to test TAF capabilities upon SELECT fail-over to my FSFO enabled DG (New primary) to handle
1) Retension of SESSION properties(EG:db_file_multiblock_read_count) after fail-over
2) TAF for SELECT having PARALLELLISM.
For 2nd i am getting below msg after SELECT fail-over
ERROR at line 1:
ORA-25408: can not safely replay call
ERROR:
ORA-25401: can not continue fetches
4350 rows selected.
SQL> select *From v$pq_tqstat;
DFO_NUMBER TQ_ID SERVER_TYP NUM_ROWS BYTES OPEN_TIME AVG_LATENCY WAITS TIMEOUTS PROCES INSTANCE
---------- ---------- ---------- ---------- ---------- ---------- ----------- ---------- ---------- ------ ----------
1 0 Producer 19800 65296 0 0 3 0 P002 1
1 0 Producer 19800 65296 0 0 4 1 P001 1
1 0 Producer 19800 65294 0 0 3 0 P000 1
1 0 Producer 19800 65296 0 0 3 0 P003 1
1 0 Consumer 4351 65296 0 0 8 0 QC 1
However, V$PQ_TQSTAT at new primary shows that 4 PX slaves have been registered.
In reply to my SR, Metalink directed me to below link that describes how callback functions can be used to control this properties for TAF usage.
But i m not sure how and where to register this callbacks. It seems they are C/C++ Functions. How should i compile or place them so that my OCI Clients (SQLPLUS) get the desire TAF fail-over capabilities?
http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10646/oci09adv.htm#i449791
Failover Callback Example
The following code shows an example of a simple user-defined callback function definition, registration, and unregistration.
Part 1: Failover Callback Definition
sb4 callback_fn(svchp, envhp, fo_ctx, fo_type, fo_event)
void * svchp;
void * envhp;
void *fo_ctx;
ub4 fo_type;
ub4 fo_event;
{
switch (fo_event)
{
case OCI_FO_BEGIN:
{
printf(" Failing Over ... Please stand by \n");
printf(" Failover type was found to be %s \n",
((fo_type==OCI_FO_SESSION) ? "SESSION"
:(fo_type==OCI_FO_SELECT) ? "SELECT"
: "UNKNOWN!"));
printf(" Failover Context is :%s\n",
(fo_ctx?(char *)fo_ctx:"NULL POINTER!"));
break;
}
case OCI_FO_ABORT:
{
printf(" Failover stopped. Failover will not take place.\n");
break;
}
case OCI_FO_END:
{
printf(" Failover ended ...resuming services\n");
break;
}
case OCI_FO_REAUTH:
{
printf(" Failed over user. Resuming services\n");
break;
}
default:
{
printf("Bad Failover Event: %d.\n", fo_event);
break;
}
}
return 0;
}
Part 2: Failover Callback Registration
int register_callback(srvh, errh)
void *srvh; /* the server handle */
OCIError *errh; /* the error handle */
{
OCIFocbkStruct failover; /* failover callback structure */
/* allocate memory for context */
if (!(failover.fo_ctx = (void *)malloc(strlen("my context.")+1)))
return(1);
/* initialize the context. */
strcpy((char *)failover.fo_ctx, "my context.");
failover.callback_function = &callback_fn;
/* do the registration */
if (OCIAttrSet(srvh, (ub4) OCI_HTYPE_SERVER,
(void *) &failover, (ub4) 0,
(ub4) OCI_ATTR_FOCBK, errh) != OCI_SUCCESS)
return(2);
/* successful conclusion */
return (0);
}
Part 3: Failover Callback Unregistration
OCIFocbkStruct failover; /* failover callback structure */
sword status;
/* set the failover context to null */
failover.fo_ctx = NULL;
/* set the failover callback to null */
failover.callback_function = NULL;
/* un-register the callback */
status = OCIAttrSet(srvhp, (ub4) OCI_HTYPE_SERVER,
(void *) &failover, (ub4) 0,
(ub4) OCI_ATTR_FOCBK, errhp);
I highly appriciate updation on this thread.
Regards,
Bhavik Desai