MySQL-ProxySQL middleware (b) | Admin Schemas Introduction

table of Contents

    MySQL-ProxySQL middleware (a) | ProxySQL basic concepts:  https://www.cnblogs.com/SQLServer2012/p/10972593.html
    MySQL-ProxySQL middleware (b) | Admin Schemas Introduction: https://www.cnblogs.com/SQLServer2012/p/10972761.html

text

    This time we mainly introduce ProxySQL core database table structure and MGR Main monitor configuration script (included eggs: MySQL 8.0 MGR monitoring scripts)
    Plan the rest of the database, as explained in detail Features do, we do not do too much expansion.

  The Admin Schemas

    ProxySQL Management Interface is a user interface MySQL protocol, any command can be sent through this interface the client is very easy to configure it. 

    ProxySQL resolve queries sent through this interface to find information specific to ProxySQL any order, if appropriate, they are sent to the embedded SQLite3 engine to run the query.

    Please note that the use of different SQLite3 and MySQL SQL syntax, so not suitable for all MySQL commands apply to SQLite3. For example, although the management interface to accept the USE command, but it does not change the default schema, because SQLite3 does not provide this functionality.

        When connected to ProxySQL management interface, we can see some of the database is available. ProxySQL converting command SHOW DATABASES SQLite3 equivalent command.

 

 

The role of these databases are as follows:

main: memory configuration database .
Using this database, you can easily query and update in an automated manner ProxySQL configuration.

Use LOAD MYSQL USERS FROM MEMORY command and the like, where the configuration is stored in memory data structures can be propagated to ProxySQL used at runtime.

disk: Disk-based "main" image.
When you restart, "main" is not permanent, and can be loaded from the "disk" database or configuration file, depending on the presence of signs and startup disk database.

stats: contains the runtime metrics collected from the internal functions of the agent.
Examples of metrics include the number of times each query matching rules, query currently running.

monitor: contains monitoring indicators related to the back-end server ProxySQL connection.
Example metrics include a connection to a back-end server or its shortest and longest ping operation.

myhgm: enabled only in debug builds
Furthermore, the use of both types of users to use these default credentials to access the database management:

user: admin / password: admin - have read and write access to all tables

user: stats / password: stats - read-only access to the tables. This index is used to extract from ProxySQL, the database without exposing too much

Access credentials described above, can be configured and admin-admin_credentials by admin-stats_credentials variable.

MAIN database

    The main table contains the following data:

    

Core configuration table

1.    mysql_server

    

 

  Field Definitions    

hostgroup_id

    This host group comprising mysqld instance. Please note that the same instance can be part of multiple host groups

hostname,port

    You can contact mysqld instance TCP endpoint

gtid_port                

    ProxySQL Binlog Reader listening GTID trace back-end server port

status

    ONLINE - back-end server can run

    SHUNNED - 后端服务器暂时停止使用,因为在时间太短或复制延迟超过允许阈值的情况下连接错误太多

    OFFLINE_SOFT - 当服务器进入OFFLINE_SOFT模式时,不再接受新的传入连接,而现有连接将保持不变,直到它们变为非活动状态。 换句话说,连接一直在使用,直到当前事务完成。 这允许优雅地分离后端

    OFFLINE_HARD - 当服务器进入OFFLINE_HARD模式时,现有连接被丢弃,而新的传入连接也不被接受。 这相当于从主机组中删除服务器,或暂时将其从主机组中取出以进行维护工作

weight

    服务器相对于其他权重的权重越大,从主机组中选择服务器的概率就越高

compression

    如果该值大于0,则与该服务器的新连接将使用压缩

max_connections

    ProxySQL将向此后端服务器打开的最大连接数。 即使此服务器具有最高权重,但一旦达到此限制,就不会向其打开新连接。 请确保后端配置了正确的max_connections值,以避免ProxySQL尝试超出该限制

max_replication_lag

    如果更大且为0,ProxySQL将定期监视复制延迟,如果超出此阈值,它将暂时避开主机,直到复制赶上

use_ssl

    如果设置为1,则与后端的连接将使用SSL

max_latency_ms

    定期监视ping时间。 如果主机的ping时间大于max_latency_ms,则它将从连接池中排除(尽管服务器保持ONLINE状态)

comment

    可用于用户定义的任何目的的文本字段。 可以是主机存储内容的描述,添加或禁用主机的提醒,或某些检查器脚本处理的JSON。

2.   mysql_replication_hostgroups

    表mysql_replication_hostgroups定义用于传统主/从异步或者半同步或者增强半同步复制的复制主机组。 
 
    如果使用Group Replication / InnoDB Cluster或Galera / Percona XtraDB Cluster进行复制,则应使用mysql_group_replication_hostgroups或mysql_galera_hostgroups(在2.x版中提供)。
    mysql_replication_hostgroups中的每一行代表一对writer_hostgroup和reader_hostgroup。 
 
    ProxySQL将监视指定主机组中所有服务器的read_only值,并根据read_only的值将服务器分配给writer组或reader组。 
 
    字段的注释可用于存储任意数据。

  字段定义   

writer_hostgroup - 默认情况下将发送所有请求的主机组,MySQL中read_only = 0的节点将分配给该主机组。

reader_hostgroup - 应该发送读取请求的主机组,应该定义查询规则或单独的只读用户将流量路由到此主机组,将read_only = 1的节点分配给该主机组。

check_type - 执行只读检查时检查的MySQL变量,默认情况下为read_only(也可以使用super_read_only)。 对于AWS Aurora,应使用innodb_read_only。

comment - 可用于用户定义的任何目的的文本字段。 可以是集群存储内容的描述,添加或禁用主机组的提醒,或某些检查器脚本处理的JSON。

3.    mysql_group_replication_hostgroups(MGR)

 

    字段定义

writer_hostgroup - 默认情况下将发送所有请求的主机组,MySQL中read_only = 0的节点将分配给该主机组。

backup_writer_hostgroup - 如果集群有多个节点,其read_only = 0和max_writers,则ProxySQL会将其他节点(超过max_writes的节点)放入backup_writer_hostgroup中。

reader_hostgroup - 应该发送读请求的主机组,将read_only = 1的节点分配给该主机组。

offline_hostgroup - 当ProxySQL的监视确定节点为OFFLINE时,它将被放入offline_hostgroup。

active - 启用时,ProxySQL监视主机组并在适当的主机组之间移动节点。

max_writers' - 此值确定writer_hostgroup中应允许的最大节点数,超过此值的节点将放入backup_writer_hostgroup中

writer_is_also_reader - 确定是否应将同一个节点添加到reader_hostgroup和writer_hostgroup中。

max_transactions_behind - 确定在屏蔽节点之前,ProxySQL应允许的写入器后面的最大事务数,以防止读取落后过多(这是通过查询MySQL中sys.gr_member_routing_candidate_status表的transactions_behind字段来确定的)。

comment - 可用于用户定义的任何目的的文本字段。 可以是集群存储内容的描述,添加或禁用主机组的提醒,或某些检查器脚本处理的JSON。

4.    mysql_galera_hostgroups(PXC)

    表mysql_galera_hostgroups(在ProxySQL 2.x及更高版本中可用)定义了用于Galera Cluster / Percona XtraDB Cluster的主机组。
    字段定义

writer_hostgroup - 默认情况下将发送所有流量的主机组,MySQL中read_only = 0的节点将分配给该主机组。

backup_writer_hostgroup - 如果集群有多个节点,其read_only = 0和max_writers,则ProxySQL会将其他节点(超过max_writes)放入backup_writer_hostgroup中。

reader_hostgroup - 应该发送读取流量的主机组,应该定义查询规则或单独的只读用户将流量路由到此主机组,将read_only = 1的节点分配给该主机组。

offline_hostgroup - 当ProxySQL的监控确定主机处于OFFLINE时,它将被放入offline_hostgroup

active - 启用时,ProxySQL监视主机组并在适当的主机组之间移动服务器。

max_writers - 此值确定writer_hostgroup中应允许的最大节点数,超过此值的节点将放入backup_writer_hostgroup中

writer_is_also_reader - 确定是否应将节点添加到reader_hostgroup以及在提升后的writer_hostgroup。

max_transactions_behind - 确定在避开节点之前ProxySQL应允许的集群后面的最大写集数,以防止过时读取(这是通过查询wsrep_local_recv_queue Galera变量确定的)。

comment - 可用于用户定义的任何目的的文本字段。 可以是集群存储内容的描述,添加或禁用主机组的提醒,或某些检查器脚本处理的JSON。

5.    mysql_users

    表mysql_users定义MySQL用户,用于连接后端。

 

    字段定义

username,password - 用于连接mysqld或ProxySQL实例的凭据。

active - 将在数据库中跟踪active = 0的用户,但永远不会在内存数据结构中加载

default_hostgroup - 如果此用户发送的查询没有匹配规则,则生成的流量将发送到指定的主机组

default_schema - 默认情况下连接应更改的架构

schema_locked - 尚不支持(TODO:check)

transaction_persistent - 如果是一个事务内的多条SQL,只会路由到一个主机组中。

fast_forward - 如果设置,它绕过查询处理层(重写,缓存)并直接将查询传递给后端服务器。

frontend - 如果设置为1,则此(用户名,密码)对用于对ProxySQL实例进行身份验证

backend - 如果设置为1,则此(用户名,密码)对用于针对任何主机组对mysqld服务器进行身份验证

max_connections - 定义特定用户的最大允许前端连接数。

comment - 可用于用户定义的任何目的的文本字段。 可以是集群存储内容的描述,添加或禁用主机组的提醒,或某些检查器脚本处理的JSON。

    注意,目前所有用户都需要将“frontend”和“后backend”都设置为1。 

    ProxySQL的未来版本将在前端和后端之间分离证书。 

    通过这种方式,前端永远不会知道直接连接到后端的凭证,强制通过ProxySQL进行所有连接并提高系统的安全性。

    fast_forward 注意事项:

1.    它不需要不同的端口:完整的功能代理逻辑和“快进”逻辑在同一代码/模块中实现

2.    fast_forward是基于每个用户实现的:取决于连接到ProxySQL的用户,启用或禁用fast_forward

3.    验证后启用fast_forward算法:客户端仍然对ProxySQL进行身份验证,当客户端开始发送流量时,ProxySQL将创建连接。 这意味着在连接阶段仍然会处理连接错误。

4.    fast_forward不支持SSL

5.    如果使用压缩,则必须在两端启用它

注意:mysql_users中的用户也不应该与admin-admin_credentials和admin-stats_credentials里的配置相同

6.    mysql_query_rules

    表mysql_query_rules定义了路由策略和属性。

 

    字段定义

rule_id - 规则的唯一ID。 规则以rule_id顺序处理

 

active - 查询处理模块将仅考虑active = 1的规则,并且只将活动规则加载到运行时。

 

username - 匹配用户名的过滤条件。 如果为非NULL,则仅当使用正确的用户名建立连接时,查询才会匹配

 

schemaname - 匹配schemaname的过滤条件。 如果为非NULL,则仅当连接使用schemaname作为默认模式时,查询才会匹配(在mariadb / mysql schemaname中等效于databasename)

flagIN,flagOUT,apply -

这些允许我们创建一个接一个地应用的“规则链”。
输入标志值设置为0,并且在开始时仅考虑flagIN = 0的规则。
当为特定查询找到匹配规则时,将评估flagOUT,如果为NOT NULL,则将使用flagOUT中的指定标志标记查询。
如果flagOUT与flagIN不同,则查询将退出当前链并输入一个新的规则链,其中flagIN作为新的输入标志。
如果flagOUT与flagIN匹配,则将针对具有所述flagIN的第一个规则再次重新评估查询。
这种情况会发生,直到没有更多匹配规则,或者apply设置为1(这意味着这是要应用的最后一条规则)


client_addr - 匹配来自特定源的流量

 

proxy_addr - 匹配特定本地IP上的传入流量

 

proxy_port - 匹配特定本地端口上的传入流量

使用stats_mysql_query_digest.digest返回的特定摘要匹配查询

 

match_digest - 与查询摘要匹配的正则表达式。 另请参见https://github.com/sysown/proxysql/wiki/Global-variables#mysql-query_processor_regex

 

match_pattern - 与查询文本匹配的正则表达式。 另请参见https://github.com/sysown/proxysql/wiki/Global-variables#mysql-query_processor_regex

 

negate_match_pattern - 如果将其设置为1,则只有与查询文本不匹配的查询才会被视为匹配项。 这在与match_pattern或match_digest匹配的正则表达式前面充当NOT运算符

 

re_modifiers -

用逗号分隔的选项列表,用于修改RE引擎的行为。 使用CASELESS,匹配不区分大小写。

使用GLOBAL,替换是全局的(替换所有匹配而不仅仅是第一个匹配)。

为了向后兼容,默认情况下仅启用CASELESS。 有关更多详细信息,另请参见https://github.com/sysown/proxysql/wiki/Global-variables#mysql-query_processor_regex。

 

replace_pattern -

这是用于替换匹配模式的模式。

它是使用RE2 :: Replace完成的,因此值得一看有关的在线文档:https://github.com/google/re2/blob/master/re2/re2.h#L378。

请注意,这是可选的,当缺少此选项时,查询处理器将仅缓存,路由或设置其他参数而不重写。

 

destination_hostgroup -

将匹配的查询路由到此主机组。

除非存在已启动的事务且登录用户将transaction_persistent标志设置为1(请参阅mysql_users表),否则会发生这种情况。

 

cache_ttl - 缓存查询结果的毫秒数。 注意:在ProxySQL 1.1中,cache_ttl只需几秒钟

 

cache_empty_result -

控制是否缓存没有行的结果集

重新连接 - 未使用的功能

 

timeout -

应执行匹配或重写查询的最大超时(以毫秒为单位)。

如果查询运行的时间超过特定阈值,则会自动终止查询。 如果未指定timeout,则应用全局变量mysql-default_query_timeout

 

retries - 在执行查询期间检测到失败时需要重新执行查询的最大次数。 如果未指定重试,则应用全局变量mysql-query_retries_on_failure

delay -

延迟执行查询的毫秒数。

这本质上是一种限制机制和QoS,允许优先考虑某些查询而不是其他查询。

此值将添加到适用于所有查询的mysql-default_query_delay全局变量中。 未来版本的ProxySQL将提供更高级的限制机制。

 

mirror_flagOUT和mirror_hostgroup - 与镜像相关的设置 https://github.com/sysown/proxysql/wiki/Mirroring。

 

error_msg - 将阻止查询,并将指定的error_msg返回给客户端

 

OK_msg - 将为使用已定义规则的查询返回指定的消息

 

sticky_conn - 尚未实现

 

multiplex -

如果为0,则禁用Multiplex。

如果为1,如果没有任何其他条件阻止此操作(如用户变量或事务),则可以重新启用Multiplex。

如果为2,则不会仅针对当前查询禁用多路复用。 请参阅wiki默认为NULL,因此不会修改多路复用策略

gtid_from_hostgroup - 定义哪个主机组应该用作GTID一致性读取的领导者(通常是复制主机组对中定义的WRITER主机组)

 

log- 将记录查询

 

apply - 当设置为1时,在匹配和处理此规则后,将不再评估进一步的查询(注意:之后不会评估mysql_query_rules_fast_routing规则)

 

comment- 自由格式文本字段,可用于查询规则的描述性注释

 

7.    mysql_query_rules_fast_routing

    表mysql_query_rules_fast_routing是mysql_query_rules的扩展,之后会对快速路由策略和属性进行评估(仅在ProxySQL 1.4.7+中可用)。
 
    字段定义

username - 与用户名匹配的过滤条件,只有在使用正确的用户名建立连接时,查询才会匹配

schemaname - 匹配schemaname的过滤条件,只有当连接使用schemaname作为默认模式时,查询才会匹配(在mariadb / mysql schemaname中,这相当于databasename)

flagIN - 与mysql_query_rules中flagin相同,并与mysql_query_rules表中指定的flagout / apply相关联

destination_hostgroup - 将匹配的查询路由到此主机组。 

comment- 自由格式文本字段,可用于查询规则的描述性注释

8.    global_variables\mysql_collations\scheduler 暂不介绍了,后面会逐步投在功能介绍里提及

 

Runtime层对应表

        表以runtime_开头,其余基本与MAIN库中的表名相同,例如:runtime_mysql_servers 是 内存层 mysql_servers表的对应表
    请注意,如果ProxySQL重新启动,如果内容未保存在磁盘数据库中,则内存表(MAIN数据库)的所有内容都将丢失。
 

Disk层对应表

        “disk”数据库与“main”数据库具有完全相同的表,具有相同的语义。 
        唯一的主要区别是这些表存储在磁盘上,而不是存储在内存中。 
        每当重新启动ProxySQL时,将从此数据库开始填充内存中的“main”数据库。
 

监控MGR,需要在MySQL实例中配置一些监控脚本(MySQL 5.7 和 MySQL 8.0略有不同)

    该脚本需要配置到sys库下,因笔记web显示问题,无法显示折行,但是不影响复制,可以自行复制粘贴出来即可。

    先看看执行效果 

select * from sys.gr_member_routing_candidate_status;
+------------------+-----------+---------------------+----------------------+
| viable_candidate | read_only | transactions_behind | transactions_to_cert |
+------------------+-----------+---------------------+----------------------+
| YES              | NO        |                   0 |                    0 |
+------------------+-----------+---------------------+----------------------+
​
viable_candidate:MGR当前节点是否正常
read_only:当前节点是否开启了只读
transactions_behind:MGR应用relay log的队列中,积压事务数
transactions_to_cert:MGR当前节点的验证队列,积压事务数

    MySQL5.7,配置脚本为:

USE sys;
​
DELIMITER $$
​
CREATE FUNCTION IFZERO(a INT, b INT) RETURNS INT DETERMINISTIC RETURN IF(a = 0, b, a)$$
​
CREATE FUNCTION LOCATE2(needle TEXT(10000), haystack TEXT(10000), offset INT) 
RETURNS INT DETERMINISTIC RETURN IFZERO(LOCATE(needle, haystack, offset), LENGTH(haystack) + 1)$$
​
CREATE FUNCTION GTID_NORMALIZE(g TEXT(10000)) 
RETURNS TEXT(10000) DETERMINISTIC RETURN GTID_SUBTRACT(g, '')$$
​
CREATE FUNCTION GTID_COUNT(gtid_set TEXT(10000)) 
RETURNS INT DETERMINISTIC BEGIN DECLARE result BIGINT DEFAULT 0; DECLARE colon_pos INT; 
DECLARE next_dash_pos INT; DECLARE next_colon_pos INT; DECLARE next_comma_pos INT; 
SET gtid_set = GTID_NORMALIZE(gtid_set); SET colon_pos = LOCATE2(':', gtid_set, 1); 
WHILE colon_pos != LENGTH(gtid_set) + 1 DO SET next_dash_pos = LOCATE2('-', gtid_set, colon_pos + 1); 
SET next_colon_pos = LOCATE2(':', gtid_set, colon_pos + 1); SET next_comma_pos = LOCATE2(',', gtid_set, colon_pos + 1); 
IF next_dash_pos < next_colon_pos AND next_dash_pos < next_comma_pos 
THEN SET result = result + SUBSTR(gtid_set, next_dash_pos + 1, 
LEAST(next_colon_pos, next_comma_pos) - (next_dash_pos + 1)) - SUBSTR(gtid_set, colon_pos + 1, next_dash_pos - (colon_pos + 1)) + 1; 
ELSE SET result = result + 1; END IF; 
SET colon_pos = next_colon_pos; 
END WHILE; RETURN result; 
END$$
​
CREATE FUNCTION gr_applier_queue_length() 
RETURNS INT DETERMINISTIC 
BEGIN RETURN 
(SELECT sys.gtid_count( GTID_SUBTRACT( (SELECT Received_transaction_set 
                                        FROM performance_schema.replication_connection_status 
                                        WHERE Channel_name = 'group_replication_applier' ), (SELECT @@global.GTID_EXECUTED) ))); 
END$$
​
CREATE FUNCTION gr_member_in_primary_partition() 
RETURNS VARCHAR(3) DETERMINISTIC BEGIN RETURN (SELECT IF( MEMBER_STATE='ONLINE' AND ((
    SELECT COUNT() FROM performance_schema.replication_group_members WHERE MEMBER_STATE != 'ONLINE') >= ((
        SELECT COUNT() FROM performance_schema.replication_group_members)/2) = 0), 'YES', 'NO' ) 
                                               FROM performance_schema.replication_group_members 
                                               JOIN performance_schema.replication_group_member_stats USING(member_id)); 
END$$
​
CREATE VIEW gr_member_routing_candidate_status AS
    SELECT 
        sys.gr_member_in_primary_partition() AS viable_candidate,
        IF((SELECT 
                    (SELECT 
                                GROUP_CONCAT(variable_value)
                            FROM
                                performance_schema.global_variables
                            WHERE
                                variable_name IN ('read_only' , 'super_read_only')) != 'OFF,OFF'
                ),
            'YES',
            'NO') AS read_only,
        sys.gr_applier_queue_length() AS transactions_behind,
        Count_Transactions_in_queue AS 'transactions_to_cert'
    FROM
        performance_schema.replication_group_member_stats$$
​
DELIMITER ;

    MySQL8.0,配置脚本为:

USE sys;
​
DELIMITER $$
​
CREATE FUNCTION IFZERO(a INT, b INT)
RETURNS INT
DETERMINISTIC
RETURN IF(a = 0, b, a)$$
​
CREATE FUNCTION LOCATE2(needle TEXT(10000), haystack TEXT(10000), offset INT)
RETURNS INT
DETERMINISTIC
RETURN IFZERO(LOCATE(needle, haystack, offset), LENGTH(haystack) + 1)$$
​
CREATE FUNCTION GTID_NORMALIZE(g TEXT(10000))
RETURNS TEXT(10000)
DETERMINISTIC
RETURN GTID_SUBTRACT(g, '')$$
​
CREATE FUNCTION GTID_COUNT(gtid_set TEXT(10000))
RETURNS INT
DETERMINISTIC
BEGIN
  DECLARE result BIGINT DEFAULT 0;
  DECLARE colon_pos INT;
  DECLARE next_dash_pos INT;
  DECLARE next_colon_pos INT;
  DECLARE next_comma_pos INT;
  SET gtid_set = GTID_NORMALIZE(gtid_set);
  SET colon_pos = LOCATE2(':', gtid_set, 1);
  WHILE colon_pos != LENGTH(gtid_set) + 1 DO
     SET next_dash_pos = LOCATE2('-', gtid_set, colon_pos + 1);
     SET next_colon_pos = LOCATE2(':', gtid_set, colon_pos + 1);
     SET next_comma_pos = LOCATE2(',', gtid_set, colon_pos + 1);
     IF next_dash_pos < next_colon_pos AND next_dash_pos < next_comma_pos THEN
       SET result = result +
         SUBSTR(gtid_set, next_dash_pos + 1,
                LEAST(next_colon_pos, next_comma_pos) - (next_dash_pos + 1)) -
         SUBSTR(gtid_set, colon_pos + 1, next_dash_pos - (colon_pos + 1)) + 1;
     ELSE
       SET result = result + 1;
     END IF;
     SET colon_pos = next_colon_pos;
  END WHILE;
  RETURN result;
END$$
​
CREATE FUNCTION gr_applier_queue_length()
RETURNS INT
DETERMINISTIC
BEGIN
  RETURN (SELECT sys.gtid_count( GTID_SUBTRACT( (SELECT
Received_transaction_set FROM performance_schema.replication_connection_status
WHERE Channel_name = 'group_replication_applier' ), (SELECT
@@global.GTID_EXECUTED) )));
END$$
​
CREATE FUNCTION gr_member_in_primary_partition()
RETURNS VARCHAR(3)
DETERMINISTIC
BEGIN
  RETURN (SELECT IF( MEMBER_STATE='ONLINE' AND ((SELECT COUNT(*) FROM
performance_schema.replication_group_members WHERE MEMBER_STATE != 'ONLINE') >=
((SELECT COUNT(*) FROM performance_schema.replication_group_members)/2) = 0),
'YES', 'NO' ) FROM performance_schema.replication_group_members JOIN
performance_schema.replication_group_member_stats USING(member_id) 
          where performance_schema.replication_group_members.member_host=@@hostname);
END$$
​
CREATE VIEW gr_member_routing_candidate_status AS
    SELECT 
        sys.gr_member_in_primary_partition() AS viable_candidate,
        IF((SELECT 
                    (SELECT 
                                GROUP_CONCAT(variable_value)
                            FROM
                                performance_schema.global_variables
                            WHERE
                                variable_name IN ('read_only' , 'super_read_only')) != 'OFF,OFF'
                ),
            'YES',
            'NO') AS read_only,
        sys.gr_applier_queue_length() AS transactions_behind,
        Count_Transactions_in_queue AS 'transactions_to_cert'
    FROM
        performance_schema.replication_group_member_stats a
            JOIN
        performance_schema.replication_group_members b ON a.member_id = b.member_id
    WHERE
        b.member_host IN (SELECT 
                variable_value
            FROM
                performance_schema.global_variables
            WHERE
                variable_name = 'hostname')$$
​
DELIMITER ;

 

 

Guess you like

Origin www.cnblogs.com/SQLServer2012/p/10972761.html