MySQL 5.6+才支持InnoDB FULLTEXT,phpEnv旧版常带5.5需升级;字段须为VARCHAR/TEXT且长度合规;中文搜索需启用ngram解析器并重建索引;MATCH AGAINST不支持预处理参数,须手动安全拼接。

MySQL 5.6+ 必须启用 InnoDB FULLTEXT 支持
phpEnv 是本地 PHP 环境套件,它默认捆绑的 MySQL 版本可能低于 5.6(比如旧版 phpEnv 常带 MySQL 5.5),而 InnoDB 的 FULLTEXT 索引从 MySQL 5.6 才正式支持。若你执行 ALTER TABLE articles ADD FULLTEXT(content) 报错 “Storage engine for the table doesn’t support FULLTEXT index”,大概率是 MySQL 版本太低。
解决办法只有两个:
- 升级 phpEnv 自带的 MySQL 到 5.6 或更高(推荐下载官方 MySQL 5.7/8.0 zip 包,替换 phpEnv 的
mysql目录,并重配my.ini和服务) - 临时改用
MyISAM引擎建表(仅限开发测试,MyISAM不支持事务、行锁,且已逐步弃用)
验证方式:连接 MySQL 后运行 SELECT VERSION(); 和 SHOW ENGINES;,确认 InnoDB 行的 SUPPORT 列显示 YES,且 FULLTEXT 列为 YES。
字段类型和长度必须满足 FULLTEXT 要求
即使 MySQL 版本达标,ADD FULLTEXT 仍可能失败,常见报错如 “BLOB, TEXT, or VARCHAR column ‘content’ used in key specification without a key length”。这是因为:
立即学习“PHP免费学习笔记(深入)”;
-
FULLTEXT只允许建在VARCHAR、TEXT类型字段上,不能用于CHAR(除非显式指定长度)、BLOB、INT等 -
VARCHAR字段长度不能超过 3072 字符(MySQL 5.7+ 默认 utf8mb4 下,实际限制是 3072 字节,即约 768 个汉字) -
TEXT类型无此长度限制,但需注意TINYTEXT/MEDIUMTEXT等子类型本身有容量上限
建表示例(安全写法):
CREATE TABLE articles ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(200), content TEXT, FULLTEXT(title, content) ) ENGINE=InnoDB;
中文搜索必须配置 ngram 解析器
直接对中文字段建 FULLTEXT 索引,然后用 AGAINST('数据库') 查询,几乎必然查不到结果——MySQL 原生按空白和标点分词,中文无空格,整个字段被当做一个“超长词”过滤掉(默认最小词长 4,且不匹配)。
唯一可行的内置方案是启用 ngram 解析器:
- 编辑
my.ini(Windows)或my.cnf(Linux/macOS),在[mysqld]段下添加:ngram_token_size=2
- 重启 MySQL 服务
- 重建全文索引(旧索引无效):
ALTER TABLE articles DROP INDEX ft_title_content; ALTER TABLE articles ADD FULLTEXT(title, content) WITH PARSER ngram;
注意:ngram_token_size=2 表示按 2 字切词(“数据库” → “数据”“库”),对短词(如“云”“AI”)效果差;若需更灵活分词,应跳过 MySQL 原生方案,改用 Elasticsearch 或 PHP 层预分词 + LIKE 组合。
PHP 中调用 MATCH AGAINST 不能用预处理参数占位符
这是最容易踩的坑:AGAINST(? IN NATURAL LANGUAGE MODE) 会报错 “FUNCTION db.MATCH does not exist” 或语法错误,因为 MATCH() AGAINST() 是 MySQL 的特殊语法,**不接受参数化绑定**。
正确做法只能是手动拼接关键词,但必须严格过滤:
- 只保留字母、数字、中文、空格、布尔操作符(
+-"*) - 用
preg_replace('/[^\p{Han}\p{L}\p{N}\s\+\-\*\"]+/u', ' ', $keyword)清洗 - 再用
trim()去首尾空格,避免空查询触发全表扫描 - 最终拼进 SQL:
"MATCH(title,content) AGAINST('{$cleaned}' IN BOOLEAN MODE)"
别信某些教程里写的 PDO 预处理能跑全文搜索——那是错的,MySQL 就不认。
实际部署时,ngram 对两字词还行,但遇到“人工智能”“数据库原理”这类术语,切出来的“人工”“智能”“数据”“库原”语义断裂严重。真要上线中文搜索,与其死磕 MySQL 全文索引,不如早一步接入 Elasticsearch 或使用 Sphinx。



















