暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

OB 4.2.5+ 的连接ID 的语义变化分析

279

OB 4.2.5 到目前已经发布了 3 个 BP 版本,每个 BP 版本都有很多功能变化。其中有个新的变化叫 “全局唯一 Client Session ID”,说的是客户端会话 ID
 的取值逻辑变化。这个变化的原因在 Release Note (查看原文地址)里是提到了是为了杀会话方便。

这个变化也是一个兼容性原理的变化,有好有坏,本文主要分析这个变化的原理和影响。


MySQL 的连接会话 ID

故事先从 MySQL 的连接会话 ID 说起。


mysql> status;
--------------
mysql  Ver 14.14 Distrib 5.7.24, for Linux (x86_64) using  EditLine wrapper

Connection id:          8
Current database:
Current user:           mq@10.212.1.7
SSL:                    Cipher in useis ECDHE-RSA-AES128-GCM-SHA256
Current pager:          stdout
Usingoutfile:          ''
Using delimiter:        ;
Server version:         5.7.44-log MySQL Community Server (GPL)
Protocol version:       10
Connection:             10.0.0.61 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8
Conn.  characterset:    utf8
TCP port:               3307
Uptime:                 8 min 41 sec

Threads: 2  Questions: 149  Slow queries: 103  Opens: 122  Flushtables1Opentables116  Queries per secondavg0.285
--------------

mysql> select connection_id();
+-----------------+
connection_id() |
+-----------------+
|               8 |
+-----------------+
1 row in set (0.02 sec)

mysql> showprocesslist;
+----+------+------------------+------+---------+------+----------+------------------+
Id | User | Host             | db   | Command | Time | State    | Info             |
+----+------+------------------+------+---------+------+----------+------------------+
|  7 | root | 127.0.0.1:20740  | NULL | Sleep   |   29 |          | NULL             |
 8 | mq   | 10.212.1.7:21756 | NULL | Query   |    0 | starting | showprocesslist |
+----+------+------------------+------+---------+------+----------+------------------+
2rowsinset (0.02 sec)

mysql> showfullprocesslist;
+----+------+------------------+------+---------+------+----------+-----------------------+
Id | User | Host             | db   | Command | Time | State    | Info                  |
+----+------+------------------+------+---------+------+----------+-----------------------+
|  7 | root | 127.0.0.1:20740  | NULL | Sleep   |   32 |          | NULL                  |
|  | mq   | 10.212.1.7:21756 | NULL | Query   |    0 | starting | showfullprocesslist |
+----+------+------------------+------+---------+------+----------+-----------------------+
2rowsinset (0.01 sec)

上面是 MySQL 跟查看连接有关的所有命令。逐一解释一下。

  • 命令 status
     查看的是客户端当前连接的信息,其中 Connection Id
     就是当前连接 ID
     
  • 函数 connection_id()
     查看的是客户端当前连接的 ID ,我怀疑上面 status
     结果里取出的连接 ID
     方法就是调用 connection_id
     。总之,在 MySQL 里这个二者是一致的。
  • 命令 show processlist
     查看的是所有有权限查看的会话连接,其中列 Id
     取值跟 connection_id()
     是一致的。列info
     会显示 SQL 的前 100 个字符。
  • 命令 show full processlist
     跟 show processlist
     一样,不同之处在于列 info
     会显示完整的 SQL。

MySQL 8.0 后 show processlist
 会废弃根据 information_schema.processlist
 视图实现, 改用 performance_schema.processlist
 视图,其中列 ID
 值会取自于 connection_id()
 结果。

这个连接 ID
 可用在杀会话命令 kill [query|session] xxxx
 中。这个是 MySQL 的基础,就不展示了。

OBServer 直连时的连接会话 ID

OB 是分布式数据库,现在用法上区分“分布式版本”和“单机版本”,也方便了讲解 OB 的连接原理。

先说一个单机版的 OB 的连接。只有一个节点,这个时候就不用 ODP 了,业务可以直连 OB 。通常大家都是这么认为的,然而这是个错误的想法。在以后的最佳实践里,还是推荐要走 ODP ,因为主备切换要用到 OB 的新功能“服务名”,依赖 ODP。是不是觉得有点“矛盾”。这不是本文的重点,以后再说。

先看不用 ODP 时候的 OB 连接方式。 OB 的连接协议是参考 MySQL 连接协议实现的,MySQL 租户里更是兼容 MySQL 的命令。所以我就拿 MySQL 租户举例。

[admin@server061 ~]$ obclient -h10.0.0.61 -uroot@sys -P2881 -paaAA11__ -c -A oceanbase
Welcome to the OceanBase.  Commands end with ; or \g.
Your OceanBase connection id is 3221494731
Server version: OceanBase 4.2.1.10 (r110040012024122218-76b8444f981549d277143b833c2bed1b64471eef) (Built Dec 22 2024 18:56:57)

Copyright (c) 2000, 2018, OceanBase and/or its affiliates. All rights reserved.

Type 'help;' or '\h'forhelp. Type '\c' to clear the current input statement.

obclient [oceanbase]> status;
--------------
obclient  Ver 2.2.5 Distrib 10.4.18-MariaDB, for Linux (x86_64) using readline 5.1

Connection id:          3221494731
Current database:       oceanbase
Current user:           root@10.0.0.61
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         OceanBase 4.2.1.10 (r110040012024122218-76b8444f981549d277143b833c2bed1b64471eef) (Built Dec 22 2024 18:56:57)
Protocol version:       10
Connection:             10.0.0.61 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
TCP port:               2881
Protocol:               Compressed
Active                  --------------

obclient [oceanbase]> select connection_id();
+-----------------+
connection_id() |
+-----------------+
|      3221494731 |
+-----------------+
1 row inset (0.000 sec)

  • 命令 status
     跟 MySQL 一致,输出的是客户端连接信息。
  • 函数 connection_id()
     返回当前连接 ID
     。跟原生 MySQL 一样,status
     里的 ID
     取值也是跟 connection_id()
     一致的。这个值很大(起步值很大,我没有找到文档说明,只能看源代码了)。

这里是直连到 OBServer 进程的,可以理解为 OBServer 上的连接 ID 都是这样的,非常大。

obclient [oceanbase]> show processlist;
+------------+-------------+-----------------+-----------+---------+------+--------+------------------+
Id         | User        | Host            | db        | Command | Time | State  | Info             |
+------------+-------------+-----------------+-----------+---------+------+--------+------------------+
| 3221487948 | ocp_monitor | 127.0.0.1:64586 | oceanbase | Sleep   |   22 | SLEEP  | NULL             |
| 3221488166 | YUNQU       | 10.0.0.61:36850 | TEST      | Sleep   |   32 | SLEEP  | NULL             |
| 3221488080 | yunqu       | 10.0.0.61:36172 | oceanbase | Sleep   | 8113 | SLEEP  | NULL             |
<...此处省略 N 行...>
| 3221487936 | ocp_monitor | 127.0.0.1:64556 | oceanbase | Sleep   |  145 | SLEEP  | NULL             |
+------------+-------------+-----------------+-----------+---------+------+--------+------------------+
128 rows in set (0.004 sec)

obclient [oceanbase]> show full processlist;
+------------+-------------+----------+-----------------+-----------+---------+------+--------+-----------------------+-----------+------+--------------------+
Id         | User        | Tenant   | Host            | db        | Command | Time | State  | Info                  | Ip        | Port | Proxy_sessid       |
+------------+-------------+----------+-----------------+-----------+---------+------+--------+-----------------------+-----------+------+--------------------+
| 3221487948 | ocp_monitor | sys      | 127.0.0.1:64586 | oceanbase | Sleep   |   26 | SLEEP  | NULL                  | 10.0.0.61 | 2881 |               NULL |
| 3221488166 | YUNQU       | oboracle | 10.0.0.61:36850 | TEST      | Sleep   |    2 | SLEEP  | NULL                  | 10.0.0.61 | 2881 | 720576202561224817 |
| 3221488080 | yunqu       | obmysql  | 10.0.0.61:36172 | oceanbase | Sleep   | 8117 | SLEEP  | NULL                  | 10.0.0.61 | 2881 | 720576202561224781 |
<...此处省略 N 行...>
| 3221487936 | ocp_monitor | sys      | 127.0.0.1:64556 | oceanbase | Sleep   |  149 | SLEEP  | NULL                  | 10.0.0.61 | 2881 |               NULL |
+------------+-------------+----------+-----------------+-----------+---------+------+--------+-----------------------+-----------+------+--------------------+
128 rows in set (0.005 sec)

在 OB 里 show processlist
 和 show full processlist
 命令结果跟原生的 MySQL 是一样的,只是后者增加了更多的字段 IP
Port
 和 Proxy_sessid
 。

  • Proxy_sessid
     : 表示通过 ODP 连接时 ODP 为服务端连接(也叫后端连接)分配的唯一 ID
    。在直连 OBServer 这个场景下没有 ODP,所以这个值为 NULL
     。所以这个也是区分这个连接是不是经过 ODP 连接的一个办法。
  • IP
     :表示服务端连接的服务端(指 OBServer)的 IP
  • Host
     : 表示服务端连接上的客户端 IP
    。如果是直连 OBServer 节点,这个值就是用户客户端 IP
    ;如果是经过 ODP 连接 OBServer ,这个值就是 ODP 的 IP。这涉及到 ODP 的连接原理,后面介绍。

OB 也兼容了 MySQL 的 information_schema.processlist
 视图,也实现了自己的专用视图 oceanbase.gv$ob_processlist
 ,后者内容更丰富。这里就看 OB 的会话视图。

obclient [oceanbase]> select id, svr_ip, host, proxy_sessid, user_client_ip from gv$ob_processlist limit 10;
+------------+-----------+-----------------+--------------------+----------------+
id         | svr_ip    | host            | proxy_sessid       | user_client_ip |
+------------+-----------+-----------------+--------------------+----------------+
| 3221487948 | 10.0.0.61 | 127.0.0.1:64586 |               NULL | 127.0.0.1      |
| 3221488166 | 10.0.0.61 | 10.0.0.61:36850 | 720576202561224817 | 177.5.0.2      |
| 3221488080 | 10.0.0.61 | 10.0.0.61:36172 | 720576202561224781 | 177.5.0.2      |
| 3221497635 | 10.0.0.61 | 10.0.0.61:54960 | 720576202561225451 | 177.5.0.2      |
| 3221488118 | 10.0.0.61 | 10.0.0.61:36474 | 720576202561224798 | 177.5.0.2      |
| 3221496723 | 10.0.0.61 | 10.0.0.61:47214 | 720576202561225399 | 177.5.0.2      |
| 3221488374 | 10.0.0.61 | 10.0.0.61:39440 | 720576202561224846 | 177.5.0.2      |
| 3221497626 | 10.0.0.61 | 127.0.0.1:28718 |               NULL | 127.0.0.1      |
| 3221489062 | 10.0.0.61 | 10.212.1.7:6387 |               NULL | 10.212.1.7     |
| 3221497164 | 10.0.0.61 | 10.0.0.64:48250 | 720576215695518897 | 127.0.0.1      |
+------------+-----------+-----------------+--------------------+----------------+
10 rows in set (0.005 sec)

说明:

  • id
     :表示连接 ID
     。
  • svr_ip
     :表示连接所在的 OBServer 的IP
     。
  • host
     :表示连接的客户端 IP。跟前面一样,这个“客户端”可能是用户客户端,也可能是 ODP。
  • proxy_sessid
     :表示 ODP 连接为 OBServer 分配的连接 ID 。为 NULL
     表示没有经过 ODP 连接。

截止到此,OBServer 上的连接 ID
 相关逻辑跟原生 MySQL 的理解还是一致的。

通过 ODP 连接 OB 时的连接会话 ID

虽然 OBServer 支持直接连接,也有 SQL 路由能力,但是 OB 分布式版本里有多个 OB 节点的时候,还是建议业务通过 ODP 连接 OB 。ODP 的设计本意就是 OB 集群数据库连接的反向代理。

ODP 的连接原理如下图


说明:

  • 左边的连接是“客户端连接”,也叫“前端连接”。这个 Client 就是用户客户端。对于 Client而言,ODP 就是它的“服务端”。这个概念在连接启用 SSL
     里也很重要。
  • 右边的连接有多个Conn
    ,叫“服务端连接”,也叫“后端连接”。在这个连接里,客户端是 ODP ,服务端是 OBServer 节点,可能有多个,这是分布式数据库特有的。
  • 一个前端连接可能对应 1~N
     个后端连接,N 是 OB 租户的节点数。
  • 如果杀掉前端连接,后端连接也会自动断开;如果杀掉后端连接,前端连接也会自动断开;如果后端连接因为别的原因断开(如 OBServer 节点故障),前端连接不会断开,ODP 会重新发起新的后端连接。

由于 OB 连接多一个反向代理组件,这个时候在兼容 MySQL 的时候选择就有点难了。

下面是通过 ODP (版本 4.2.1)连接 OB(版本 4.2.1)的示例。

(base) mq@OBPILOT:~$ mysql -h10.0.0.61 -uroot@sys#obdemo61 -P2883 -paaAA11__ -c -A oceanbase
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1649989
Server version: 5.6.25 OceanBase 4.2.1.10 (r110040012024122218-76b8444f981549d277143b833c2bed1b64471eef) (Built Dec 22 2024 18:56:57)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h'forhelp. Type '\c' to clear the current input statement.

mysql> status;
--------------
mysql  Ver 14.14 Distrib 5.7.24, for Linux (x86_64) using  EditLine wrapper

Connection id:          1649989
Current database:       oceanbase
Current user:           root@10.212.1.7
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.6.25 OceanBase 4.2.1.10 (r110040012024122218-76b8444f981549d277143b833c2bed1b64471eef) (Built Dec 22 2024 18:56:57)
Protocol version:       10
Connection:             10.0.0.61 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
TCP port:               2883
Active                  --------------

从原生 MySQL 命令的 status
 设计目的来说,这个就指客户端连接信息。在 OB 数据库里,这个就是指用户客户端连接信息,也就是前面说的“前端连接”的信息。ODP 作为 OBServer 的连接代理,必须实现最基本的连接协议,包括这个最基础的命令 status
 。 所以上面看到 status
 连接信息里的 Connection id
 的值是 1649989
 ,非常的小,跟前面 OBServer 上的连接 ID
 不一样。实际上 ODP 的连接 ID
 应该是从很小的数(可能是 1)开始叠加使用的,这个 ID
 会累加。所以后面如果我们看到连接 ID
 如果很小的话,那可以大概率判断为这个 ID
 是取自 ODP 上的连接 ID
 。

紧接着我们再看。

mysql> select connection_id();
+-----------------+
connection_id() |
+-----------------+
|      3221498326 |
+-----------------+
1 row in set (0.01 sec)

从原生 MySQL 的函数 connection_id()
 设计目的来说,是返回客户端连接 ID
 。但是 ODP 早期版本并没有实现这个函数,而是把这个 SQL 路由到 OBServer 节点上去执行了。所以这个函数根据设计目的而言返回的是 OBServer 上的连接 ID
 值,也就是这个前端链接对应后端连接的 ID
 。

虽然 connection_id()
 跟 status
 中的连接 ID
 值不一样,让很多从 MySQL 转型过来的 DBA 很不适应(不适应的原因还在后面),但是上面这个解释还是符合逻辑的,可以自圆其说。也就是说 OB SQL 语义里把 connection_id()
 设计为后端连接的 ID
 。

但是随之而来的困扰就是 MySQL 的杀会话命令 kill [session|query] xxid
 。 紧接着上面这个会话,杀掉这个会话 ID
 。用哪个 ID
 呢?实际上二者都可以。

mysql> kill 3221498326;
ERROR 1317 (70100): Query execution was interrupted

会话断开重连后,继续杀。

mysql> status;
--------------
mysql  Ver 14.14 Distrib 5.7.24, for Linux (x86_64) using  EditLine wrapper

Connection id:          1633071
Current database:       oceanbase
Current user:           root@10.212.1.7
SSL:                    Not in use
Current pager:          stdout
Usingoutfile:          ''
Using delimiter:        ;
Server version:         5.6.25 OceanBase 4.2.1.10 (r110040012024122218-76b8444f981549d277143b833c2bed1b64471eef) (Built Dec 22 2024 18:56:57)
Protocol version:       10
Connection:             10.0.0.61 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
TCP port:               2883
Active                  --------------

mysql> kill 1633071;
ERROR 1317 (70100): Query execution was interrupted

这里 KILL
 之所以两个 ID
 都能杀,是因为这两个 ID
 描述的是同一个连接(区别只是一个是后端链接,一个是前端链接)。但这还没有完。

我们继续查看命令 show processlist
 。

mysql> show processlist;
+---------+----------+----------+------------------+-----------+-------------+-------------------+-------------------+------+------+
Id      | Tenant   | User     | Host             | db        | trans_count | svr_session_count | state             | tid  | pid  |
+---------+----------+----------+------------------+-----------+-------------+-------------------+-------------------+------+------+
| 1633148 | sys      | root     | 10.212.1.7:21814 | oceanbase |           0 |                 1 | MCS_ACTIVE_READER | 1849 | 1805 |
| 1633134 | obmysql  | yunqu    | 10.0.0.107:50790 | oceanbase |           0 |                 1 | MCS_ACTIVE_READER | 1849 | 1805 |
| 1633110 | oboracle | yunqu    | 10.0.0.118:38816 | SYS       |           0 |                 1 | MCS_ACTIVE_READER | 1849 | 1805 |
<...省略 N 行...>
| 1622018 | obmysql  | test     | 10.0.0.175:57878 | test      |           0 |                 1 | MCS_ACTIVE_READER | 1848 | 1805 |
+---------+----------+----------+------------------+-----------+-------------+-------------------+-------------------+------+------+
89 rows in set (0.03 sec)

mysql>

从原生 MySQL 命令 show processlist
 设计目的看,这个命令显示的是客户端连接(前端连接),所以看到的连接 Id
 都是很小的数。我们尝试取一个 Id
 来杀一下。

mysql> kill 1622031;
Query OK, 0 rows affected (0.01 sec)

mysql> kill 1605657;
Query OK, 0 rows affected (0.01 sec)


随便抽查了几个连接 Id
 都可以杀(如果报错,应该是那个会话已经自己断开了)。

再继续查看命令 show full processlist
 。

mysql> show full processlist;
+------------+-------------+----------+-----------------+-----------+---------+-------+--------+-----------------------+-----------+------+--------------------+
Id         | User        | Tenant   | Host            | db        | Command | Time  | State  | Info                  | Ip        | Port | Proxy_sessid       |
+------------+-------------+----------+-----------------+-----------+---------+-------+--------+-----------------------+-----------+------+--------------------+
| 3221487948 | ocp_monitor | sys      | 127.0.0.1:64586 | oceanbase | Sleep   |    11 | SLEEP  | NULL                  | 10.0.0.61 | 2881 |               NULL |
| 3221488166 | YUNQU       | oboracle | 10.0.0.61:36850 | TEST      | Sleep   |    19 | SLEEP  | NULL                  | 10.0.0.61 | 2881 | 720576202561224817 |
| 3221499544 | YUNQU       | oboracle | 10.0.0.61:11532 | TEST      | Sleep   |    58 | SLEEP  | NULL                  | 10.0.0.61 | 2881 | 720576202561225571 |
<... 省略 N 行...>
| 3221487936 | ocp_monitor | sys      | 127.0.0.1:64556 | oceanbase | Sleep   |    74 | SLEEP  | NULL                  | 10.0.0.61 | 2881 |               NULL |
+------------+-------------+----------+-----------------+-----------+---------+-------+--------+-----------------------+-----------+------+--------------------+
133 rows in set (0.04 sec)

从这里可以看出 show full processlist
 跟 show processlist
 的区别很大,远大于 OB 直连时的结果(其实内在逻辑是一致的)。

  • 列 Id
     表示的是后端连接 ID
    ,也就是 OBServer 上的产生的连接 ID
     。
  • 列 Host
     列表示的就是后端连接的客户端 IP
     ,通常是 ODP 的 IP
     。如果是直连 OBServer 的会话,这个 Host
     就是用户客户端 IP
     。
  • 列 IP
     表示服务端(OBServer)的 IP

我们再次随机挑选几个连接 Id
 尝试杀会话看看。

mysql> kill 3221499594;
ERROR 1094 (HY000): Unknown thread id: 3221499594
mysql> kill 3221499019;
ERROR 1094 (HY000): Unknown thread id: 3221499019
mysql> kill 3221488887;
Query OK, 0 rows affected (0.02 sec)

mysql> kill 3221488079;
Query OK, 0 rows affected (0.01 sec)


可以看到有些连接可以杀,有些连接杀不掉。即使我用的是 root@sys#obdemo61
 账户,也存在有些连接杀不掉。其原因是我只能杀掉跟我当前所用 ODP 相同的连接会话,有很多会话是从其他 ODP 连接过来的,我是杀不掉的。这些会话是 OCP 监控会话,走的是 OCP 机器上的 ODP (版本 4.2.1)。

如果要杀掉其他 ODP 的连接,有两个方法。一是通过那个 ODP 连接,然后杀会话。第二就是到后端连接对应的 OBServer(也就是列IP
) 上去杀这个会话。

再看看视图 gv$ob_processlist
 的结果。

mysql> select id, svr_ip, host, proxy_sessid, user_client_ip from gv$ob_processlist limit 10;
+------------+-----------+-----------------+--------------------+----------------+
id         | svr_ip    | host            | proxy_sessid       | user_client_ip |
+------------+-----------+-----------------+--------------------+----------------+
| 3221499828 | 10.0.0.61 | 10.0.0.61:14324 | 720576202561225590 | 177.5.0.2      |
| 3221487948 | 10.0.0.61 | 127.0.0.1:64586 |               NULL | 127.0.0.1      |
| 3221488166 | 10.0.0.61 | 10.0.0.61:36850 | 720576202561224817 | 177.5.0.2      |
| 3221488080 | 10.0.0.61 | 10.0.0.61:36172 | 720576202561224781 | 177.5.0.2      |
| 3221488118 | 10.0.0.61 | 10.0.0.61:36474 | 720576202561224798 | 177.5.0.2      |
| 3221496723 | 10.0.0.61 | 10.0.0.61:47214 | 720576202561225399 | 177.5.0.2      |
| 3221488374 | 10.0.0.61 | 10.0.0.61:39440 | 720576202561224846 | 177.5.0.2      |
| 3221499994 | 10.0.0.61 | 10.0.0.64:26632 | 720576215695518912 | 127.0.0.1      |
| 3221489062 | 10.0.0.61 | 10.212.1.7:6387 |               NULL | 10.212.1.7     |
| 3221488046 | 10.0.0.61 | 10.0.0.61:35990 | 720576202561224775 | 177.5.0.2      |
+------------+-----------+-----------------+--------------------+----------------+
10 rows in set (0.03 sec)

这个结果比 show full processlist
 多一项内容就是真实的客户端 IP
信息,即列 user_client_ip
 。 这里的 Id
 取值跟 show full processlist
 是一样的。

总结一下,OB 此前版本的 connection_id()
 是取自 OBServer 上的连接 ID
 ,ODP 并没有实现 connection_id()
 函数语义(或者说它实现了,直接丢给 OBServer 了)。尽管如此,逻辑上还能自洽,带来的负面影响只是杀会话这个操作。

OB 4.2.5 版本后连接 ID 的变化

先直接发官网的 ReleaseNote 说明:


全局唯一 Client Session ID

这个变化要满足两个条件:OB版本大于等于 4.2.5 以及 ODP 版本大于等于 4.2.3.1 。不满足这个条件的我就不专门展示了。实际上在客户环境一定会存在不满足 ODP 版本的连接(来自于 OCP)。

首先直连一个 OB 4.2.5 版本看看连接 ID 的变化。


status
connection_id

由上图可见,命令 status
 跟connection_id()
 取值不一样,这个跟此前版本是一样的,逻辑可以自洽。


show processlist
 命令

由上图可见,命令 show processlist
 里的 Id
 已经出现两种类型的取值了。但原因从这个图还看不出来。


show full processlist
 命令

由上图可见,不同 Id
 取值的原因就能看得出来。分三类:

  • 一部分是 OB 节点本机发起的直连 OBServer 2881 端口的连接,这个情形就等同于前面直连 OBServer 节点特性。这类连接是 ocp_agent
     监控客户端发起的。
  • 一部分是来自其他低版本 ODP 过来的连接。这类连接是没有升级的 ODP 版本或者 OCP 应用(及其ODP)。这两类在生产环境都不轻易升级。
  • 一部分是来自满足要求的 ODP 过来的连接。

紧接着再随机杀会话看看。


kill

此时发现,不管是哪种 ID
,都可以杀。这里应该是 OBServer 也同步修改了 KILL
 逻辑。不管你给的是前端连接的 ID
 还是后端连接的 ID
 ,只要账户有权限,都可以杀。这个确实很好。

注:我这里测试的是单机版本,没有看分布式版本。推测分布式版本下,即使我直连一个 OBServer 节点,也是可以杀同一个另外一个 OBServer 节点上的连接(原因是 OBServer 由 SQL 路由功能)。这点未经核实,有环境的朋友可以帮验证一下,如果结果不对,欢迎留言指出。

上面是直连 OBServer 的连接下观察到的现象,我们接着看通过 ODP 连接后的变化。


status
connection_id

由上图可以看出这里有个很大的变化,connection_id()
 的取值跟 status
 里的连接 ID
 又保持一致了。也就是 OB 在 ODP 里也实现了函数(connection_id()
)或者说调整了实现语义。当在 ODP 里调用函数 connection_id()
 的时候,取的就是客户端连接(也是前端连接)的连接 ID
 。这个就是我要说的兼容性变化的关键点。

不光这里,视图 show processlist
 和 show full processlist
 命令,以及视图 gv$ob_processlist
 里的 ID
 都变更为客户端连接的 ID
 了(如果经过满足版本要求的 ODP 的连接)。


所以,实际的结果就是你一定会看到两种类型值的 Id
 。此时杀会话的命令也是百试不爽。即使是其他 ODP 过来的连接,也是有权限杀会话。这应该是这个变化带来的最大好处。

连接 ID 逻辑变换后的影响

初步看影响就是查出来的 Id
 值有大有小,不过好在 KILL
 命令好用了,这一点点影响也就不算什么了。我印象中这个特点在更早的版本(V1/V2/V3)好像就存在,那时候也是有一番解释逻辑可以自洽。现在没有环境验证了。

对这个变化我觉得它有点不好的原因之一是连视图 gv$ob_processlist
Id
 列也变了。这个视图是 OB 上的(不是 ODP 的),应该维持 OBServer 上的连接 ID
 语义,客户端 ODP 的连接 ID
 应该另辟字段展示,就像列 proxy_sessid
,有就有,没有就是 NULL
 。 原因之二就是当 OBServer 内部连接 Id
 的语义变化了后,你就发现 gv$ob_sql_audit
 的关联字段 sid
 关联不上了。因为这个字段取的始终是 OBServer 上的连接ID
,那个是 SQL 被执行的 OBServer 节点上的连接ID
,这个可不能用 ODP 的连接 ID
 去替代(前面说了映射关系是 1:N
)。

由上图可知,传入的 sid
 是 ODP 客户端连接 ID
 ,所以无法查到关联的 SQL 记录。

这个时候就需要根据这个 ODP 客户端连接ID
 找到服务端连接 ID
 。 使用命令:show proxysession attribute xxxxid
 。

由上图可以看出当用后端连接 ID
 去查 SQL 审计视图的时候,就能找到相应会话的 SQL 记录。

但是,QUERY_SQL
 显示为 NULL
 。这是 4.2.5.2 版本以后的变化,普通租户 SQL 审计视图不再展示 SQL 文本。 回到 SYS 租户,就可以查到对应的 SQL。

不知道还有没有其他视图还包含了“会话 ID”这个字段,如果有可能也有类似问题。其实我觉得 gv$
ob_processlist
 如果增加一个字段表示客户端连接 ID
 ,可能更合理一些。

总结

洋洋洒洒写了这么多,总结起来其实也就一句话。OB 4.2.5 版本加 ODP 4.2.3.1 版本后,connect_id()
 语义将改为展示 ODP 客户端连接 ID
 ,并且 KILL
 会话语义加强(只要有权限,所有连接 ID
 皆可杀)。改动的目的是为了 KILL 方便,却连带动了视图 gv$ob_processlist.ID 语义(不完美)。所以此后需要注意的是 OB 内其他视图如果要关联会话或连接ID
,需要使用ODP 命令show proxysession
 间接转换一下。

OB 的版本迭代很快,总是能带给人一些意外的发现。后面还会继续分享其他新功能或变化的功能。

更多阅读


文章转载自数据库技术闲谈,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论