PHPKonf 2020 Online

连接池与切换

插件控制 PHP MySQL 链接,完成同步和负载均衡,他并不会改变现有的 PHP MySQL 扩展的方法使用 (mysqli, mysql, 和 PDO_MYSQL) 现有的应用并不需要 更新他们代码,或者使用新的 API,但是若操作行为改变,还是需要一些修改的。

插件结果下面这些扩展对于 MySQL 连接的控制, mysqli, mysql, 和 PDO_MYSQL。 并且为 mysqli, mysql, 和 PDO_MYSQL 提供一个本地的连接池 完成 MySQL 主从同步的 master 和 slave 通讯控制。插件会代理所有的 到达 master 和 slave 的查询请求。 在某一时刻一个连接到 master 的链接,会在稍后变更为 slave 连接,或者 依然保持 master 连接。在执行非事务处理中,控制和替换 PHP MySQL 的网络链接。

每个 MySQL 连接都有他的状态,在连接池中的每个连接可以有不同的状态。 当插件将一个写入连接变更为另外一个的时候,链接状态可能被改变。应用 需要关注这个问题。

下面列出连接状态的内容,他可能并不完整。

  • 事务状态
  • 临时表
  • 表锁
  • Session 系统变量和用户变量
  • 当前使用的数据库 USE 和其他束缚 SQL 指令的状态
  • 预执行语句
  • HANDLER 变量
  • 通过 GET_LOCK () 获得的锁

连接替换将在语句执行前进行,在下一个语句执行以前,插件不会变更连接。

Note: 同步的问题

请参考 MySQL 参考手册中关于 » replication features 的相关内容。一些限制跟这个 PHP 插件无感,但是与 MySQL 的主从同步相关。

广播消息

插件的设计哲学是只有完全控制的链接,插件会在连接池排列连接的状态,或者由于 一些安全因素也会这么做。只有很少的操作改变连接状态会失败,在这样的分类当中。

下面列出了哪些客户端的库,会改变连接状态,并且会将它广播到连接池中所有 打开的链接当中。

任何下面列出的内容被执行,插件会轮循所有打开的 master 和 slave 连接, 轮循会在操作了所有的服务器后停止。这个轮循不会影响服务器连接失败的状态。 库函数的触发器可能以备检测到失败,并且通过用户 API 函数广播。

Library call Notes Version
change_user() Called by the mysqli_change_user() user API call. Also triggered upon reuse of a persistent mysqli connection. Since 1.0.0.
select_db Called by the following user API calls: mysql_select_db(), mysql_list_tables(), mysql_db_query(), mysql_list_fields(), mysqli_select_db(). Note, that SQL USE is not monitored. Since 1.0.0.
set_charset() Called by the following user API calls: mysql_set_charset(). mysqli_set_charset(). Note, that SQL SET NAMES is not monitored. Since 1.0.0.
set_server_option() Called by the following user API calls: mysqli_multi_query(), mysqli_real_query(), mysqli_query(), mysql_query(). Since 1.0.0.
set_client_option() Called by the following user API calls: mysqli_options(), mysqli_ssl_set(), mysqli_connect(), mysql_connect(), mysql_pconnect(). Since 1.0.0.
set_autocommit() Called by the following user API calls: mysqli_autocommit(), PDO::setAttribute(PDO::ATTR_AUTOCOMMIT). Since 1.0.0. PHP >= 5.4.0.
ssl_set() Called by the following user API calls: mysqli_ssl_set(). Since 1.1.0.

广播和被动连接

连接打开以后,插件无法代理或者记录其上所有的设定。如果采用 lazy connections. 这非常重要。被动连接方式,客户端在发起第一次指令的时候,连接才被建立。 插件默认的采用这种被动连接方式。

下面的这些库调用,将在被动连接建立以后执行。这有助于确信所有连接池中 连接的状态存在可比性。

Library call Notes Version
change_user() User, password and database recorded for future use. Since 1.1.0.
select_db Database recorded for future use. Since 1.1.0.
set_charset() Calls set_client_option(MYSQL_SET_CHARSET_NAME, charset) on lazy connection to ensure charset will be used upon opening the lazy connection. Since 1.1.0.
set_autocommit() Adds SET AUTOCOMMIT=0|1 to the list of init commands of a lazy connection using set_client_option(MYSQL_INIT_COMMAND, "SET AUTOCOMMIT=...%quot;). Since 1.1.0. PHP >= 5.4.0.
Caution

连接状态

连接状态不仅仅会被 API 调用改变。所以,即使插件监控了所有的 API 调用, 应用也要在这方面关注变化。最后,对于连接状态的维护,是应用应该完成的事情。

字符集和字符串换码

当使用默认的被动连接时,若应用尝试在连接建立以前对 SQL 语句中的字符进行转码, 是不可能完成的。因为连接建立以前,并不知道连接需要的字符集是甚么。

在 1.4.0 以后版本中,通过配置中的 server_charset 设置可以解决这个问题。

需要注意已经转换为某种字符集,但是连接的结果采用了另外一种不同的字符集。 插件控制的链接和连接池中的每个连接可能采用了不同的默认字符集,所以建议配置 服务器采用统一的默认字符集设定。配置文件中的 server_charset 可以很好的处理这种情况,如果使用它,插件将对每一个新打开的链接设定默认的字符集。

add a note add a note

User Contributed Notes 1 note

up
1
m at louislivi dot com
1 year ago
SMProxy
A MySQL database connection pool based on MySQL protocol and Swoole.
https://github.com/louislivi/SMProxy
To Top