2024 年 PHP 日本研討會

OCI8 透明應用程式故障移轉 (TAF) 支援

TAF 是一項 Oracle 資料庫功能,可提供高可用性。它讓 PHP OCI8 應用程式在資料庫連線因執行個體或網路故障而失敗時,自動重新連線到預先設定的資料庫。

在已設定的 Oracle 資料庫系統中,當 PHP 應用程式偵測到資料庫執行個體已關閉或無法連線時,就會發生 TAF。它會建立與 Oracle » RAC 設定中的另一個節點、熱備援資料庫或相同資料庫執行個體本身的連線。詳情請參閱 » Oracle 呼叫介面程式設計師指南 以取得關於 OCI TAF 的更多資訊。

應用程式回呼函式可以使用 oci_register_taf_callback() 註冊。在故障轉移期間,正常的應用程式處理會停止,並呼叫已註冊的回呼函式。該回呼函式會將故障轉移事件通知應用程式。如果故障轉移成功,則會繼續正常處理。如果故障轉移中止,則應用程式中後續的任何資料庫操作都將失敗,因為沒有可用的連線。

當連線故障轉移到另一個資料庫時,回呼函式可以重設任何必要的連線狀態,例如,如果資料庫服務未啟用 -failover_restore,則重新執行任何必要的 ALTER SESSION 命令。

可以透過呼叫 oci_unregister_taf_callback() 來移除應用程式回呼函式。

設定透明應用程式故障轉移 (Transparent Application Failover, TAF)

TAF 可以在 PHP OCI8 端或資料庫設定中設定。如果兩者都已設定,則以資料庫端設定優先。

在 PHP OCI8(用戶端)中設定 TAF,方法是在連線描述元的 CONNECT_DATA 部分中加入 FAILOVER_MODE 參數。有關 TAF 用戶端設定的更多資訊,請參閱《Oracle Database Net Services 管理員指南》中的設定透明應用程式故障轉移 ( »  Oracle Database Net Services 管理員指南 )。

tnsnames.ora 設定 TAF 重新連線到同一個資料庫實例的範例

    ORCL =
      (DESCRIPTION =
        (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
        (CONNECT_DATA =
          (SERVICE_NAME = orclpdb1)
          (FAILOVER_MODE =
            (TYPE = SELECT)
            (METHOD = BASIC)
            (RETRIES = 20)
            (DELAY = 15))))
 

或者,也可以在資料庫端設定 TAF,方法是使用 » srvctl(適用於 RAC)或 »  DBMS_SERVICE.MODIFY_SERVICE 封裝程序(適用於單一實例資料庫)修改目標服務。

在 OCI8 中使用 TAF 回呼函式

TAF 回呼函式是一個應用程式函式,可以註冊在故障轉移期間被呼叫。在重新建立應用程式連線時,它會被呼叫多次。

當偵測到連線中斷時,會先發生回呼。這允許應用程式針對即將發生的故障轉移延遲採取相應的行動。如果故障轉移成功,則在連線重新建立且可用後會呼叫回呼函式。此時,應用程式可以重新同步會話設定,並採取一些動作,例如通知使用者已發生故障轉移。如果故障轉移失敗,則會發生回呼,通知應用程式故障轉移未發生且連線無法使用。

TAF 使用者定義回呼函式的介面如下:

userCallbackFn(resource $connection, int $event, int $type): int

connection

透過 oci_register_taf_callback() 註冊 TAF 回呼函式的 Oracle 連線。在故障轉移成功完成之前,連線無效。

event

故障轉移事件指示故障轉移的目前狀態。

  • OCI_FO_BEGIN 表示故障轉移已偵測到連線中斷,並且故障轉移正在啟動。

  • OCI_FO_END 表示故障轉移已成功完成。

  • OCI_FO_ABORT 表示故障轉移失敗,並且沒有重試選項。

  • OCI_FO_ERROR 也表示故障轉移失敗,但它讓應用程式有機會處理錯誤並返回 OCI_FO_RETRY 以重試故障轉移。

  • OCI_FO_REAUTH 表示 Oracle 使用者已重新驗證。

類型

故障轉移類型。這讓回呼函式知道應用程式請求的故障轉移類型。通常的值如下:

  • OCI_FO_SESSION 表示使用者僅請求工作階段故障轉移。例如,如果使用者的連線斷開,則會在備份伺服器上自動為使用者建立新的工作階段。這種故障轉移類型不會嘗試恢復 SELECT 陳述式。

  • OCI_FO_SELECT 表示使用者也請求了 SELECT 故障轉移。它允許具有開啟游標的使用者在故障後繼續從中擷取資料。

傳回值

  • 0 表示故障轉移步驟應正常繼續。

  • OCI_FO_RETRY 表示 Oracle 應再次嘗試故障轉移。如果在故障轉移到新連線時發生錯誤,TAF 可以重試故障轉移。通常,應用程式程式碼應在返回 OCI_FO_RETRY 之前休眠一段時間。

範例 #1 註冊 TAF 回呼函式

<?php

// Define userspace callback
class MyClass {
public static
$retry_count;
public static function
TAFCallback($conn, $event, $type)
{
switch (
$event) {
case
OCI_FO_BEGIN:
printf(" Failing Over ... Please stand by\n");
printf(" Failover type was found to be %s \n",
((
$type==OCI_FO_SESSION) ? "SESSION"
:(($type==OCI_FO_SELECT) ? "SELECT" : "UNKNOWN!")));
self::$retry_count = 0;
break;
case
OCI_FO_ABORT:
// The application cannot continue using the database
printf(" Failover aborted. Failover will not take place.\n");
break;
case
OCI_FO_END:
// Failover completes successfully. Inform users a failover occurs.
printf(" Failover ended ... resuming services\n");
break;
case
OCI_FO_REAUTH:
printf(" Failed over user ... resuming services\n");
// Replay any ALTER SESSION commands associated with this connection
// eg. oci_parse($conn, ‘ALTER SESSION …’) ;
break;
case
OCI_FO_ERROR:
// Stop retrying if we have already attempted for 20 times.
if (self::$retry_count >= 20)
return
0;
printf(" Failover error received. Sleeping...\n");
sleep(10);
self::$retry_count++;
return
OCI_FO_RETRY; // retry failover
break;
default:
printf("Bad Failover Event: %d.\n", $event);
break;
}
return
0;
}
}

$fn_name = 'MyClass::TAFCallback';

$conn = oci_connect('hr', 'welcome', 'orcl');
$sysconn = oci_connect('system', 'oracle', 'orcl');

// Use a privileged connection to construct a SQL statement that will initiate failover
$sql = <<< 'END'
select unique 'alter system disconnect session '''||sid||','||serial#||''''
from v$session_connect_info
where sid = sys_context('USERENV', 'SID')
END;

$s = oci_parse($conn, $sql);
oci_execute($s);
$r = oci_fetch_array($s);
$disconnectssql = $r[0];

oci_register_taf_callback($conn, $fn_name); // Register TAFCallback to Oracle TAF

print "Parsing user query\n";
$sql = "select systimestamp from dual";
$stmt = oci_parse($conn, $sql);

// For example, if a connection loss occurs at this point, oci_execute() will
// detect the loss and failover begins. During failover, oci_execute() will
// invoke the TAF callback function several times. If the failover is successful,
// a new connection is transparently created and oci_execute() will continue as
// usual. The connection session settings can be reset in the TAF callback
// function. If the failover is aborted, oci_execute() will return an error
// because a valid connection is not available.

// Disconnect the user, which initiates failover
print "Disconnecting the user\n";
$discsql = oci_parse($sysconn, $disconnectssql);
oci_execute($discsql);

print
"Executing user query\n";
$e = oci_execute($stmt);
if (!
$e) {
$m = oci_error($stmt);
trigger_error("Could not execute statement: ". $m['message'], E_USER_ERROR);
}
$row = oci_fetch_array($stmt);
print
$row[0] . "\n";

// do other SQL statements with the new connection, if it is valid
// $stmt = oci_parse($conn, . . .);

?>
新增註記

使用者貢獻的註記

此頁面沒有使用者貢獻的註記。
To Top