引言
MySQL 经常被概括成“业务 CRUD 数据库”。这个说法没错,但不完整。以 InnoDB 为核心,MySQL 还提供事务、JSON、多值索引、全文检索、空间索引、事件调度和复制能力,足以覆盖很多中小型系统。
这篇文章沿用 PostgreSQL for Everything 和 SQLite for Everything 的思路:先使用已有数据库解决问题,只有真实需求超出边界时才增加组件。MySQL 的重点不是模仿 PostgreSQL,而是把它已经成熟的能力用好。
本文中的建表示例以 MySQL 8.0.16 及以上为前提。旧版本对 CHECK 约束、排序规则和部分 JSON 索引能力的支持不同。
稳定可靠
MySQL 使用时间长、生态大、运维经验丰富。InnoDB 的事务、行锁、索引和崩溃恢复已经是大量业务系统的默认底座。数据库的“无聊”是一种生产力:遇到问题时更容易找到文档、工具和有经验的人。
易于运行、安装和扩展
本地可以直接安装 MySQL 或使用 Docker,线上也有大量托管服务。主从复制、备份、监控和扩容有成熟工具可用。托管服务依旧需要关注连接数、慢查询、磁盘、binlog 保留和恢复演练,但不必自建所有控制面。
简化 IT 架构
MySQL 也不只有一组表和几个 CRUD 语句。很多中小型场景可以先让它同时承担搜索、文档字段、小型队列、定时维护和数据同步。
用户、订单、库存、支付这类数据需要原子更新和约束,首先应该使用 InnoDB、主键、唯一索引和明确的事务边界:
CREATE TABLE orders (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
status VARCHAR(32) NOT NULL,
amount DECIMAL(18, 2) NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY orders_user_created_idx (user_id, created_at),
CONSTRAINT orders_amount_ck CHECK (amount >= 0)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
金额使用 DECIMAL,不要使用浮点数;时间和字符集在建表时确定;索引按照实际查询建立,而不是把每个字段都加上索引。数据库能保证的约束,优先交给数据库。
MySQL 可以替代 Solr 和 Elastic:FULLTEXT
InnoDB 支持 FULLTEXT 索引和 MATCH ... AGAINST 查询:
CREATE TABLE documents (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
body TEXT NOT NULL,
FULLTEXT KEY documents_search_idx (title, body) WITH PARSER ngram
) ENGINE = InnoDB;
SELECT id, title,
MATCH(title, body) AGAINST ('数据库' IN NATURAL LANGUAGE MODE) AS score
FROM documents
WHERE MATCH(title, body) AGAINST ('数据库' IN NATURAL LANGUAGE MODE)
ORDER BY score DESC;
中文、日文、韩文需要使用 ngram parser 或其他分词方案,不能默认英文按空格切词的行为适合中文。上面的示例使用 WITH PARSER ngram,实际部署还要根据最大词长调整 ngram_token_size。站内文章、产品说明和后台文档可以先用 FULLTEXT;如果要做复杂相关性、拼写纠错、推荐召回或搜索集群独立扩容,再考虑专用搜索引擎。
MySQL 可以替代 MongoDB:JSON 文档
MySQL 的 JSON 列适合商品扩展属性、第三方响应、配置快照等结构变化比较频繁的数据:
CREATE TABLE products (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
attributes JSON NOT NULL
);
INSERT INTO products(name, attributes)
VALUES ('键盘', '{"layout":"75%","wireless":true}');
SELECT id, name
FROM products
WHERE attributes->>'$.wireless' = 'true';
如果某个 JSON 路径变成高频过滤条件,就把它提升为生成列,或者使用合适的多值索引。JSON 不是逃避建模的借口:订单状态、用户 ID、金额、关联关系仍然应该是有类型和约束的普通列。
MySQL 可以替代 Kafka 和 RabbitMQ:小型队列
MySQL 8.0 之后,FOR UPDATE SKIP LOCKED 可以用于领取待处理任务:
START TRANSACTION;
SELECT id, payload
FROM jobs
WHERE status = 'pending' AND available_at <= CURRENT_TIMESTAMP
ORDER BY id
LIMIT 1
FOR UPDATE SKIP LOCKED;
UPDATE jobs
SET status = 'running', started_at = CURRENT_TIMESTAMP
WHERE id = ?;
COMMIT;
它适合和业务事务在同一个 MySQL 实例里的小型后台任务。要补上失败重试、超时回收和幂等键;如果任务量巨大、消费者很多、需要独立回放或消息保留,消息队列更合适。
MySQL 可以替代 ClickHouse:有限的时序场景
按时间分区、时间索引和批量写入足够覆盖订单流水、操作日志和中小型指标表。它适合时序数据需要和用户、订单等业务表一起查询的场景;如果主要负载变成高吞吐写入和大范围聚合,ClickHouse 或专用时序数据库更合适。
MySQL 可以替代向量数据库:只在有明确产品支持时
MySQL 本身不应被宣传成所有版本都自带的向量数据库。使用 MySQL HeatWave Vector Store、兼容扩展或旁路向量服务前,要确认版本、部署形态、索引能力和费用。普通业务搜索不要为了“AI”额外引入一套向量基础设施,简单 embedding 可以先和业务数据保持可追溯的关联。
MySQL 可以替代 Redis:有限的缓存场景
短期缓存可以用带过期时间的表,或者评估 MEMORY 引擎;但高并发、淘汰策略、内存上限和低延迟访问仍然是 Redis 更擅长的领域。MySQL 的优势是缓存和业务事务在同一个系统里,而不是它会自动变成内存数据库。
MySQL 可以替代文件系统:保存小型对象的元数据
小型 BLOB 可以放在 MySQL 中,但大文件、图片和视频通常应该进入对象存储。数据库保存对象地址、类型、权限和哈希值,通常比把整套文件系统塞进业务库更容易扩展。
MySQL 可以替代图数据库:树形数据
简单树形数据可以通过邻接表、路径字段或递归查询处理;复杂图遍历不应硬塞进 MySQL。另一方面,一些只负责查询数据库并返回 JSON 的薄微服务,可以直接用 SQL、视图或存储过程减少胶水代码,但认证、业务规则和跨服务边界仍应留在应用层。
MySQL 作为 GraphDB 和 Neo4J 的替代方案
MySQL 可以处理有限的关系遍历,但没有 PostgreSQL 的 AGE 这类图扩展,也不适合把复杂图算法硬写成 SQL。只有组织树、分类树和简单依赖关系时,使用递归 CTE 才是合理的简化。
MySQL 可以替代微服务
MySQL 的二进制日志可以支持复制和变更数据捕获。报表、搜索索引或异步同步可以从 binlog 构建下游流程,避免业务代码在每次写入时手动维护多份数据。
MySQL Event Scheduler 也能执行简单的定时 SQL,例如清理过期数据:
使用前需要确认 event_scheduler 已开启,并且当前账号拥有创建事件的权限。
如果通过 mysql 客户端执行,还需要先调整语句分隔符:
DELIMITER //
CREATE EVENT cleanup_sessions
ON SCHEDULE EVERY 1 HOUR
DO
DELETE FROM sessions
WHERE expires_at < CURRENT_TIMESTAMP//
DELIMITER ;
事件调度适合简单、低风险的数据库内维护任务。复杂工作流、重试编排和跨服务调用不要塞进 Event Scheduler;它应该保持短小且可观测。
MySQL 不能替代 PlayStation 5
用 SQL 写游戏可以当作演示,但和生产系统无关。数据库的能力边界应该由真实查询和运维指标决定。
结论
下面这些情况通常值得引入其他组件:
- 搜索需要复杂中文分词、相关性调优、海量索引和独立扩展。
- 缓存访问量远高于业务写入,并且需要专门的淘汰和内存策略。
- 消息需要高吞吐、长时间保留、多个消费组和独立回放。
- 时序数据主要是持续高频写入和大范围聚合,事务表已经成为瓶颈。
- 大文件应该进入对象存储,MySQL 只保存元数据和地址。
专用系统的引入成本并不只是安装一个服务,还包括权限、监控、备份、故障恢复和数据一致性。先用 MySQL 的事务、索引和 binlog 打通业务闭环,再依据指标拆分,通常更稳。
MySQL 的“简单”是优点:生态成熟、运维人员多、InnoDB 的业务模型清楚。它不需要承担所有搜索、缓存和消息场景,但在很多项目里,关系数据、JSON、全文检索、小队列和同步链路已经足够构成一个完整系统。
先问“能不能用 MySQL 的表、索引、事务或 binlog 解决”,再问“要不要新增一个服务”。答案如果是否定的,再引入专用工具;答案如果是肯定的,就少维护一套系统。
官方资料:InnoDB 全文索引、全文检索、ngram parser、生成列和索引。