PHP通过连接ShardingSphere-Proxy(默认3307端口)实现分库分表,需配置逻辑库名、禁用PDO模拟预处理、避免多语句和参数化LIMIT,所有SQL面向逻辑表与分片键,不可手动分片。

PHP 本身不直接支持分库分表,ShardingSphere 是 Java 生态的中间件,PHP 无法直连或配置其代理规则——你得让 PHP 连的是 ShardingSphere-Proxy,而不是 MySQL。
PHP 怎么连 ShardingSphere-Proxy
ShardingSphere-Proxy 启动后,对外暴露的是标准 MySQL 协议端口(默认 3307),PHP 的 mysqli 或 PDO 完全可以像连 MySQL 一样连它,只要把主机、端口、用户名、密码换成 Proxy 的即可。
常见错误现象:Connection refused,其实是没启动 Proxy,或防火墙拦了 3307;Access denied 则是 Proxy 的 server.yaml 里没配好认证用户(不是原 MySQL 用户)。
- Proxy 默认监听
0.0.0.0:3307,PHP 连接时 host 写127.0.0.1或 Proxy 所在机器 IP,port 填3307 - Proxy 的登录账号由
server.yaml中的users配置决定,和后端真实 MySQL 账号无关 - 数据库名填的是逻辑库名(
sharding_db),不是物理库名(ds_0、ds_1)
为什么不能在 PHP 里写分片逻辑
ShardingSphere 的核心价值是把分片下推到中间件层,PHP 层保持“无感”。一旦你在 PHP 里手动拼 INSERT INTO user_001 或用 switch($uid % 4) 选库,就等于绕过 Proxy,既失去读写分离、分布式事务能力,又和 Proxy 的分片规则冲突。
立即学习“PHP免费学习笔记(深入)”;
典型翻车场景:Proxy 配了按 user_id 取模分 4 表,PHP 却按 created_at 日期路由,结果查不到数据,还报 Table 'sharding_db.t_user' doesn't exist(因为实际表名是 t_user_000~t_user_003)。
- 所有 SQL 必须面向逻辑表名(如
t_user),不能出现物理表名或库名 - 分片键(
sharding-column)必须出现在WHERE、INSERT等关键语句中,否则走默认节点或广播,性能崩塌 - JOIN 多表时,关联字段必须都是分片键,否则 Proxy 无法路由,直接报错
PHP 需要特别注意的兼容性点
ShardingSphere-Proxy 对协议支持有边界,PHP 的某些惯用法会触发不兼容。
比如 PDO::ATTR_EMULATE_PREPARES = true 开启后,预处理会被本地模拟,Proxy 收不到完整 SQL,导致分片失效;再比如用 mysqli_multi_query() 发送多语句,Proxy 默认禁用,需在 server.yaml 显式打开 sql-show: true 和 props.sql-show: true 并确认版本支持。
- 强制关闭模拟预处理:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false) - 避免使用
SELECT * FROM t_user LIMIT ?, ?这类带问号占位符的分页——Proxy 5.x 对参数化 LIMIT 解析不稳定,改用LIMIT 0, 20字面量 - 时间函数如
NOW()、CURRENT_TIMESTAMP没问题,但SYS_GUID()或自定义函数可能不识别,报Unsupported SQL
真正难的从来不是 PHP 怎么写,而是分片键选哪个、扩容怎么平滑、跨分片聚合查询怎么收口——这些在 Proxy 配置里调参数,在 PHP 里只管发逻辑 SQL 就行。别试图在 PHP 层补中间件的活。



















