17_Multiplexing

备注:文章编写时间201904-201905期间,后续官方在github的更新没有被写入

多路复用[Multiplexing]

多路复用既单一链接的复用;通过多路复用配置后,可以大幅度降低后端节点的连接数。

一、多路复用不可用的情况[Conditions where multiplexing is disabled]

1、活跃的事务[active transaction]

当事务在连接中处于活动状态时,将禁用多路复用,直到事务提交或回滚为止。

2、表被加锁[table(s) locked]

如果执行了 LOCK TABLE,LOCK TABLES或FLUSH TABLES WITH READ LOCK,则禁用多路复用,直到执行UNLOCK TABLES。

3、use of GET_LOCK()

如果执行了GET_LOCK()函数,则禁用多路复用,并且永远不会再次启用。

4、使用特定的 会话/用户 变量[use of specific session/user variables]

在query_digest(查询概要)中具有@(引用变量)的所有查询都将禁用多路复用,并且永远不会再次启用它。 注意:如果您正在select一个变量(例如,select @test_var)并且没有按预期获得结果,则很可能是由于查询规则将您的语句路由到另一个主机组(这时请查看您的查询规则)。

同样,如果执行以下这些命令,也会发生同样的情况: 1)SET SQL_SAFE_UPDATES=?,SQL_SELECT_LIMIT=?,MAX_JOIN_SIZE=? (mysql --safe-updates) 2)SET FOREIGN_KEY_CHECKS 3)SET UNIQUE_CHECKS 4)SET AUTO_INCREMENT_INCREMENT (v 1.4.4+) 5)SET AUTO_INCREMENT_OFFSET (v 1.4.4+) 6)SET GROUP_CONCAT_MAX_LEN (v 1.4.4+)

但主要,在Proxy SQL中硬编码有2个例外,它们不会禁用多路复用: 1)SELECT @@tx_isolation 2)SELECT @@version 以上这些例外语句是硬编码的,因为许多应用程序在每个连接中运行它们。

5、use of SQL_CALC_FOUND_ROWS

如果查询包含MySQL的 SQL_CALC_FOUND_ROWS (SELECT语句中选项),则禁用多路复用,并且永远不会再次启用该连接。

6、Temporary tables

如果执行了 CREATE TEMPORARY TABLE 语句,则禁用多路复用,并且永远不会再次在连接上启用多路复用。

7、use of PREPARE

如果执行MySQL的 PREPARE 语句(使用TEXT协议而不是BINARY协议创建预准备语句),则禁用多路复用,并且永远不会再次启用。

8、会话关闭了binlog[SQL_LOG_BIN sets to 0]

如果SQL_LOG_BIN设置为0,则禁用多路复用,直到SQL_LOG_BIN设置回1。

二、不处理会话变量[Not handled session variables]

大多数会话变量不会被自动处理。 例如,如果客户端发出 SET TX_ISOLATION=? ,则多路复用不会被禁用。 但如果您的客户端使用了不同的tx_isolation,这样的使用方式是有问题的;推荐将所有客户端指定相同的tx_isolation,这也是默认的。(根据我的经验,使用通一的隔离级别才是大众选择)。

三、启用/禁用多路复用[Ad-hoc enable/disable of multiplexing]

在 mysql_query_rules.multiplexing 中允许根据匹配条件来控制启用或禁用多路复用。

该字段目前接受以下值: 0 : 禁用多路复用 1 : 启用多路复用 2 : 对包含@变量的该特定查询,不禁用多路复用。

例如,在您的应用程序中使用 SET SQL_SELECT_LIMIT 提示语句,您可以创建以下两个规则:

INSERT INTO mysql_query_rules (active,match_digest,multiplex) VALUES
('1','^SET SQL_SELECT_LIMIT=?',0), (1,'^SET SQL_SELECT_LIMIT=DEFAULT,1);

如果您的应用程序发送了类似 SELECT @@ max_allowed_packet 的内容,并且您希望阻止因此而禁用多路复用,则可以创建以下规则:

INSERT INTO mysql_query_rules (active,match_digest,multiplex) VALUES
('1','^SELECT @@max_allowed_packet',2);

......甚至可以缓存它:

INSERT INTO mysql_query_rules (active,match_digest,multiplex,cache_ttl) VALUES
('1','^SELECT @@max_allowed_packet',2,60000);

如果您的应用程序正在尝试设置一些将导致禁用多路复用的变量,并且您认为可以对其进行过滤,则可以创建一个在不执行查询的情况下返回OK的过滤器:

INSERT INTO mysql_query_rules (active,match_digest,OK_msg) VALUES
('1','^SET @@wait_timeout = ?','');

完毕!