multiplexing , 作用是将语句分多路路由。开启了multiplexing开关 , 读/写分离、按规则路由才能进行。但有时候 , 有些语句要求路由到同一个主机组 , 甚至是同一个主机组中的同一个节点上。这时会自动禁用multiplexing。禁用multiplexing后 , 语句会根据同一个连接进行路由。
也就是说 , 在禁用multiplexing情况下 , 会将语句路由到同一个主机组中的同一个节点上。
什么情况下会禁用多路路由(disable multiplexing)?
激活事务时 : 当某连接中激活了一个事务 , 则在该事务提交或回滚之前 ,
multiplexing将一直被禁用。表被锁 : 当执行了
LOCK TABLE,LOCK TABLES或FLUSH TABLES WITH READ LOCK时 , 将一直禁用multiplexing, 直到执行UNLOCK TABLES。使用
GET_LOCK()时 , 如果执行了GET_LOCK(), 将一直禁用multiplexing, 且永不再次启用。使用某些特定的会话/用户(
session/user)变量 ,所有查询的query_digest部分包含了@的都将禁用multiplexing, 且永不再次启用。
下面的命令是类似的情况 , 都会禁用multiplexing且不再次启用:
SET SQL_SAFE_UPDATES=?,SQL_SELECT_LIMIT=?,MAX_JOIN_SIZE=?(mysql --safe-updates)SET FOREIGN_KEY_CHECKSSET UNIQUE_CHECKSSET AUTO_INCREMENT_INCREMENT(v 1.4.4+)SET AUTO_INCREMENT_OFFSET(v 1.4.4+)SET GROUP_CONCAT_MAX_LEN(v 1.4.4+)
但下面两个语句是例外 , 因为它们被硬编码为不禁用multiplexing:
SELECT @@tx_isolationSELECT @@version
之所以要硬编码这两个例外 , 是因为很多应用程序在每个连接中都会执行这两个语句。
使用
SQL_CALC_FOUND_ROWS
如果查询语句中包含了SQL_CALC_FOUND_ROWS , 那么该连接上将禁用multiplexing且不再启用。
临时表
如果执行了CREATE TEMPORARY TABLE , 那么该连接上将禁用multiplexing且不再启用。
使用
PREPARE
如果执行PREPARE语句(该语句使用文本协议准备好语句 , 而不是二进制协议) , 将禁用multiplexing且不再启用。
SQL_LOG_BIN设置为0时 , 即禁用binlog
如果SQL_LOG_BIN设置为0 , 则multiplexing将被禁用直到SQL_LOG_BIN开启。
Not handled session variables
大多数会话变量都不会自动进行处理。 例如 , 如果客户端发出了SET TX_ISOLATION=? , 将不会禁用multiplexing。 当有不同客户端使用了不同的tx_isolation时 , 这将是一个bug , 但一般所有客户端都使用默认的tx_isolation(绝大多数情况都如此)。
Ad-hoc enable/disable of multiplexing
mysql_query_rules.multiplexing允许基于匹配标准来启用/禁用multiplexing。当前该字段可接受的值有:
0 : 禁用multiplexing
1 : 启用multiplexing
2 : 对于包含了
@的查询语句不禁用multiplexing(默认包含了@的语句会禁用multiplexing)
例如 , 如果你的应用程序中使用了SET SQL_SELECT_LIMIT , 你可以创建下面两条规则来启用multiplexing:
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的语句 , 为了避免默认情况下这样的语句禁用multiplexing , 可以创建如下规则:
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);如果你的应用程序尝试要设置一个变量 , 而这可能会禁用multiplexing , 如果这个设置语句能够写规则来匹配 , 可以创建一个筛选条件返回OK而无需去执行查询 , 这样就不会修改multiplexing当前的策略:
INSERT INTO mysql_query_rules (active,match_digest,OK_msg) VALUES
('1','^SET @@wait_timeout = ?','');参考链接
MySQL中间件之ProxySQL(12):禁止多路路由 - 骏马金龙 - 博客园