文件首頁
MySQL 8.4 C API 開發人員指南
下載本手冊
PDF (美式信紙) - 1.4Mb
PDF (A4) - 1.4Mb


MySQL 8.4 C API 開發人員指南  /  ...  /  mysql_session_track_get_first()

5.4.74 mysql_session_track_get_first()

int
mysql_session_track_get_first(MYSQL *mysql,
                              enum enum_session_state_type type,
                              const char **data,
                              size_t *length)

說明

MySQL 實作了一種會話追蹤機制,伺服器會將會話狀態變更的相關資訊傳回給客戶端。為了控制伺服器針對狀態變更提供的通知,客戶端應用程式會設定名稱格式為 session_track_xxx 的系統變數,例如 session_track_state_changesession_track_schemasession_track_system_variables。請參閱伺服器追蹤用戶端會話狀態

變更通知發生在 MySQL 客戶端/伺服器協定中,該協定在 OK 封包中包含追蹤器資訊,以便可以偵測到會話狀態變更。為了讓客戶端應用程式能夠從 OK 封包中擷取狀態變更資訊,MySQL C API 提供了一對函數

mysql_session_track_get_first() 的參數使用方式如下。這些說明也適用於 mysql_session_track_get_next(),它採用相同的參數。

  • mysql:連線處理常式。

  • type:追蹤器類型,指出要擷取哪種資訊。允許的追蹤器值是在 mysql_com.h 中定義的 enum_session_state_type 列舉的成員。

    enum enum_session_state_type
    {
      SESSION_TRACK_SYSTEM_VARIABLES,            /* Session system variables */
      SESSION_TRACK_SCHEMA,                      /* Current schema */
      SESSION_TRACK_STATE_CHANGE,                /* Session state changes */
      SESSION_TRACK_GTIDS,                       /* GTIDs */
      SESSION_TRACK_TRANSACTION_CHARACTERISTICS, /* Transaction characteristics */
      SESSION_TRACK_TRANSACTION_STATE            /* Transaction state */
    };

    隨著 MySQL 實作額外的會話資訊追蹤器,該列舉的成員可能會隨著時間而變更。為了方便應用程式循環遍歷所有可能的追蹤器類型,而不考慮成員的數量,SESSION_TRACK_BEGINSESSION_TRACK_END 符號定義為等於 enum_session_state_type 列舉的第一個和最後一個成員。本節稍後顯示的範例程式碼將示範此技術。(當然,如果列舉成員變更,您必須重新編譯您的應用程式,使其能夠考慮新的追蹤器。)

  • dataconst char * 變數的位址。成功呼叫後,此變數會指向傳回的資料,該資料應視為唯讀。

  • lengthsize_t 變數的位址。成功呼叫後,此變數會包含由 data 參數指向的資料長度。

以下討論說明如何根據 type 值來解譯 datalength 值。它還會指出哪個系統變數啟用每個追蹤器類型的通知。

  • SESSION_TRACK_SCHEMA:此追蹤器類型表示已設定預設結構描述。data 是一個包含新預設結構描述名稱的字串。length 是字串長度。

    若要啟用此追蹤器類型的通知,請啟用 session_track_schema 系統變數。

  • SESSION_TRACK_SYSTEM_VARIABLES:此追蹤器類型表示已將一個或多個追蹤的會話系統變數指派一個值。當指派會話系統變數時,每個變數會傳回兩個值 (在個別的呼叫中)。對於第一次呼叫,data 是一個包含變數名稱的字串,而 length 是字串長度。對於第二次呼叫,data 是一個包含變數值的字串,而 length 是字串長度。

    預設情況下,會針對這些會話系統變數啟用通知

    若要變更此追蹤器類型的預設通知,請將 session_track_schema 系統變數設定為要追蹤變更的逗號分隔變數清單,或設定為 * 以追蹤所有變數的變更。若要停用會話變數指派的通知,請將 session_track_system_variables 設定為空字串。

  • SESSION_TRACK_STATE_CHANGE:此追蹤器類型表示會話狀態的某些追蹤屬性發生了變更。data 是一個位元組,其中包含一個布林旗標,指出是否發生了會話狀態變更。length 應為 1。旗標表示為 ASCII 值,而不是二進位值 (例如,'1',而不是 0x01)。

    若要啟用此追蹤器類型的通知,請啟用 session_track_state_change 系統變數。

    此追蹤器會報告會話狀態的這些屬性的變更

    • 預設結構描述 (資料庫)。

    • 系統變數的會話特定值。

    • 使用者定義的變數。

    • 暫時資料表。

    • 預處理陳述式。

  • SESSION_TRACK_GTIDS:此追蹤器類型表示 GTID 可用。data 包含 GTID 字串。length 是字串長度。GTID 字串採用用於指定一組 GTID 值的標準格式;請參閱GTID 集合

    若要啟用此追蹤器類型的通知,請設定 session_track_gtids 系統變數。

  • SESSION_TRACK_TRANSACTION_CHARACTERISTICS:此追蹤器類型表示交易特性可用。data 是一個包含特性資料的字串。length 是字串長度。特性追蹤器資料字串可以是空的,也可以包含一個或多個 SQL 陳述式,每個陳述式都以分號結尾

    • 如果沒有任何特性適用,則字串為空。會套用會話預設值。(對於隔離層級和存取模式,這些預設值由 transaction_isolationtransaction_read_only 系統變數的會話值給定。)

    • 如果交易是明確啟動的,則此字串會包含以相同特性重新啟動交易所需的語句。一般來說,這是一個 START TRANSACTION 語句(可能包含一個或多個 READ ONLYREAD WRITEWITH CONSISTENT SNAPSHOT)。如果任何無法傳遞給 START TRANSACTION 的特性適用,例如 ISOLATION LEVEL,則會預先附加一個適當的 SET TRANSACTION 語句(例如,SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; START TRANSACTION READ WRITE;)。

    • 如果交易不是明確啟動的,但設定了僅適用於下一個交易的一次性特性,則會產生一個適用於複製該設定的 SET TRANSACTION 語句(例如,SET TRANSACTION READ ONLY;)。

      可以使用不帶任何 GLOBALSESSION 關鍵字的 SET TRANSACTION,或使用僅適用於下一個交易的語法來設定 transaction_isolationtransaction_read_only 系統變數,來設定下一個交易的特性。

      SET @@transaction_isolation = value;
      SET @@transaction_read_only = value;

      有關交易特性範圍級別及其設定方式的更多資訊,請參閱交易特性範圍

    若要啟用此追蹤器類型的通知,請將 session_track_transaction_info 系統變數設定為 CHARACTERISTICS(這也會啟用 SESSION_TRACK_TRANSACTION_STATE 追蹤器類型)。

    交易特性追蹤使客戶端能夠確定如何在另一個會話中重新啟動交易,使其具有與原始會話相同的特性。

    由於特性可能會在使用 SET TRANSACTION 啟動交易之前設定,因此如果沒有活動交易,客戶端假設沒有交易特性是不安全的。因此,不追蹤交易特性,而僅在沒有活動交易時切換連線(無論是通過交易狀態追蹤器還是傳統的 SERVER_STATUS_IN_TRANS 標誌檢測到),都是不安全的。如果客戶端可能希望在某個時刻將其會話切換到另一個連線,並且可能會使用交易,則 必須 訂閱交易特性追蹤器。

    特性追蹤器追蹤僅適用於下一個交易的一次性特性的變更。它不追蹤會話變數的變更。因此,客戶端還必須追蹤 transaction_isolationtransaction_read_only 系統變數,以正確確定當下一個交易特性值為空時適用的會話預設值。(要追蹤這些變數,請在 session_track_system_variables 系統變數的值中列出它們。)

  • SESSION_TRACK_TRANSACTION_STATE:此追蹤器類型表示交易狀態資訊可用。data 是一個包含 ASCII 字元的字串,每個字元都表示交易狀態的某些方面。length 是字串長度(始終為 8)。

    若要啟用此追蹤器類型的通知,請將 session_track_transaction_info 系統變數設定為 STATE

    交易狀態追蹤使客戶端能夠確定交易是否正在進行中,以及是否可以在不回滾的情況下將其移動到另一個會話。

    追蹤器項目的範圍是交易。所有表示狀態的標誌都會持續存在,直到交易提交或回滾。當語句添加到交易中時,可能會在連續的追蹤器資料值中設定其他標誌。但是,在交易結束之前,不會清除任何標誌。

    交易狀態報告為包含一系列 ASCII 字元的字串。每個活動狀態都有一個唯一的字元分配給它,以及在序列中的固定位置。以下列表描述了序列的第 1 到第 8 個位置允許的值

    • 位置 1:是否正在進行活動交易。

      • T:正在進行明確啟動的交易。

      • I:正在進行隱式啟動的交易(autocommit=0)。

      • _:沒有活動交易。

    • 位置 2:在目前交易的上下文中是否讀取了非交易表。

      • r:已讀取一個或多個非交易表。

      • _:到目前為止,尚未讀取非交易表。

    • 位置 3:在目前交易的上下文中是否讀取了交易表。

      • R:已讀取一個或多個交易表。

      • _:到目前為止,尚未讀取交易表。

    • 位置 4:在目前交易的上下文中是否執行了不安全的寫入(寫入非交易表)。

      • w:已寫入一個或多個非交易表。

      • _:到目前為止,尚未寫入非交易表。

    • 位置 5:在目前交易的上下文中是否寫入了任何交易表。

      • W:已寫入一個或多個交易表。

      • _:到目前為止,尚未寫入交易表。

    • 位置 6:在目前交易的上下文中是否執行了任何不安全的語句。包含不確定性結構(例如 RAND()UUID())的語句對於基於語句的複製是不安全的。

      • s:已執行一個或多個不安全的語句。

      • _:到目前為止,尚未執行不安全的語句。

    • 位置 7:在目前交易期間是否已將結果集傳送到客戶端。

      • S:已傳送結果集。

      • _:到目前為止,尚未傳送結果集。

    • 位置 8:LOCK TABLES 語句是否生效。

    考慮一個包含以下語句的會話,包括啟用交易狀態追蹤器的語句

    1. SET @@SESSION.session_track_transaction_info='STATE';
    2. START TRANSACTION;
    3. SELECT 1;
    4. INSERT INTO t1 () VALUES();
    5. INSERT INTO t1 () VALUES(1, RAND());
    6. COMMIT;

    啟用交易狀態追蹤後,以下 data 值會從這些語句產生

    1. ________
    2. T_______
    3. T_____S_
    4. T___W_S_
    5. T___WsS_
    6. ________

傳回值

成功返回零。如果發生錯誤,則返回非零值。

錯誤

無。

範例

以下範例顯示如何呼叫 mysql_session_track_get_first()mysql_session_track_get_next(),以檢索和顯示成功執行 SQL 語句字串(由 stmt_str 表示)後的所有可用會話狀態變更資訊。假設應用程式已設定啟用其希望接收的通知的 session_track_xxx 系統變數。

printf("Execute: %s\n", stmt_str);

if (mysql_query(mysql, stmt_str) != 0)
{
  fprintf(stderr, "Error %u: %s\n",
           mysql_errno(mysql), mysql_error(mysql));
  return;
}

MYSQL_RES *result = mysql_store_result(mysql);
if (result) /* there is a result set to fetch */
{
  /* ... process rows here ... */
  printf("Number of rows returned: %lu\n",
          (unsigned long) mysql_num_rows(result));
  mysql_free_result(result);
}
else        /* there is no result set */
{
  if (mysql_field_count(mysql) == 0)
  {
    printf("Number of rows affected: %lu\n",
            (unsigned long) mysql_affected_rows(mysql));
  }
  else      /* an error occurred */
  {
    fprintf(stderr, "Error %u: %s\n",
             mysql_errno(mysql), mysql_error(mysql));
  }
}

/* extract any available session state-change information */
enum enum_session_state_type type;
for (type = SESSION_TRACK_BEGIN; type <= SESSION_TRACK_END; type++)
{
  const char *data;
  size_t length;

  if (mysql_session_track_get_first(mysql, type, &data, &length) == 0)
  {
    /* print info type and initial data */
    printf("Type=%d:\n", type);
    printf("mysql_session_track_get_first(): length=%d; data=%*.*s\n",
           (int) length, (int) length, (int) length, data);

    /* check for more data */
    while (mysql_session_track_get_next(mysql, type, &data, &length) == 0)
    {
      printf("mysql_session_track_get_next(): length=%d; data=%*.*s\n",
             (int) length, (int) length, (int) length, data);
    }
  }
}