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_change
session_track_schema
session_track_system_variables
更改通知发生在 MySQL 客户端/服务器协议中,它在 OK 数据包中包含跟踪器信息,以便可以检测到会话状态更改。为了使客户端应用程序能够从 OK 数据包中提取状态更改信息,MySQL C API 提供了一对函数:
mysql_session_track_get_first()
获取从服务器接收到的状态更改信息的第一部分。mysql_session_track_get_next()
获取从服务器接收到的任何剩余状态更改信息。成功调用 后mysql_session_track_get_first()
,重复调用此函数,直到它返回成功。
参数使用
mysql_session_track_get_first()
如下。这些描述也适用于
mysql_session_track_get_next()
采用相同参数的 。
mysql
: 连接处理程序。-
type
:跟踪器类型,指示要检索的信息类型。enum_session_state_type
允许的跟踪器值是以下定义的枚举的成员mysql_com.h
: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_BEGIN
和SESSION_TRACK_END
符号被定义为等于enum_session_state_type
枚举的第一个和最后一个成员。本节稍后显示的示例代码演示了此技术。(当然,如果枚举成员发生变化,您必须重新编译您的应用程序以使其能够考虑新的跟踪器。) data
:const char *
变量的地址。成功调用后,此变量指向返回的数据,该数据应被视为只读。length
:size_t
变量的地址。成功调用后,此变量包含参数指向的数据的长度data
。
下面的讨论描述了如何
根据值来解释data
和值。它还指示哪个系统变量为每个跟踪器类型启用通知。
length
type
-
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_isolation
和transaction_read_only
系统变量的会话值给出。)如果显式启动事务,则该字符串包含重新启动具有相同特征的事务所需的语句。作为一般规则,这是一个 声明(可能包含、和
START TRANSACTION
中的一个或多个)。如果任何适用的特性无法传递给 ,例如,则会在前面加上合适的语句(例如)。READ ONLY
READ WRITE
WITH CONSISTENT SNAPSHOT
START TRANSACTION
ISOLATION LEVEL
SET TRANSACTION
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; START TRANSACTION READ WRITE;
-
如果未显式启动事务,但设置了仅适用于下一个事务的一次性特征,
SET TRANSACTION
则会生成适合复制该设置的语句(例如,SET TRANSACTION READ ONLY;
)。SET TRANSACTION
可以不使用任何GLOBAL
或SESSION
关键字 来设置下一个交易特征 ,或者通过 使用仅适用于下一个交易的语法 设置transaction_isolation
和 系统变量:transaction_read_only
SET @@transaction_isolation = value; SET @@transaction_read_only = value;
有关事务特征范围级别及其设置方式的更多信息,请参阅 事务特征范围。
要为此跟踪器类型启用通知,请将
session_track_transaction_info
系统变量设置为CHARACTERISTICS
(这也会启用SESSION_TRACK_TRANSACTION_STATE
跟踪器类型)。事务特征跟踪使客户端能够确定如何在另一个会话中重新启动事务,以便它具有与原始会话中相同的特征。
因为可以
SET TRANSACTION
在事务开始之前设置 using 特性,如果没有事务处于活动状态,则客户端假设没有事务特性是不安全的。因此,不跟踪事务特征并在没有事务处于活动状态时切换连接是不安全的(无论这是由事务状态跟踪器还是传统SERVER_STATUS_IN_TRANS
标志检测到)。如果客户端 可能希望在某个时候将其会话切换到另一个连接并且可以使用事务,则 客户端必须订阅事务特征跟踪器。特性跟踪器跟踪对仅适用于下一个事务的一次性特性的更改。它不跟踪对会话变量的更改。因此,客户端还必须跟踪
transaction_isolation
和transaction_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()
orUUID()
对于基于语句的复制是不安全的。s
: 执行了一个或多个不安全语句。_
: 到目前为止没有执行不安全的语句。
-
位置 7:当前事务期间是否向客户端发送了结果集。
S
: 已发送结果集。_
: 目前还没有发送结果集。
-
位置 8:
LOCK TABLES
声明是否有效。L
:表被显式锁定LOCK TABLES
。_
: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. ________
-
以下示例说明如何在
成功执行 SQL 语句字符串(由 表示)后调用mysql_session_track_get_first()
、
检索和显示所有可用的会话状态更改信息。假定应用程序已设置
系统变量以启用它希望接收的通知。
mysql_session_track_get_next()
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);
}
}
}