从库报“table 'xxx' doesn't exist”绝大多数因主从元数据不一致或复制上下文错位,非表真丢失;应先连从库执行use+show tables或information_schema交叉验证存在性,再查引擎、relay log上下文、gtid对齐、过滤规则、权限及lower_case_table_names配置。

从库报 Table 'xxx' doesn't exist 错误,绝大多数情况不是表真丢了,而是主从元数据不一致或复制上下文错位。直接查备份或重做从库是过度反应,先按链路顺序排查。
确认从库是否真的“没这张表”
别信报错本身——它常发生在 SQL 线程执行 relay log 时找不到上下文表,但表可能就在那儿。
- 先连上从库,执行
USE your_db;,再跑SHOW TABLES LIKE 'xxx';—— 如果能看见,说明表存在,问题出在复制过程 - 跨库查更准:
SELECT table_name FROM information_schema.tables WHERE table_schema = 'your_db' AND table_name = 'xxx';,这个不依赖当前库上下文 - 检查表引擎:
SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA='your_db' AND TABLE_NAME='xxx';,InnoDB 表缺失.ibd文件会报这错,但 MyISAM 缺.MYD或.MYI同样触发
查 relay log 里那条出错的语句到底在操作什么
错误日志(log_error 配置路径下的文件)里通常带具体 SQL,比如 INSERT INTO user_log ...。重点看它有没有带库名前缀。
- 如果语句是
INSERT INTO user_log ...(无库前缀),而当前 SQL 线程的默认库不是your_db,就会去错地方找表——用SELECT @@default_database;查当前上下文 - 如果语句是
INSERT INTO myapp.user_log ...(带库前缀),但从库上压根没有myapp这个库,说明主库建库操作没同步过来,或者被replicate-ignore-db过滤了 - 用
mysqlbinlog --base64-output=decode-rows -v /path/to/relay-log.000001 | grep -A 5 -B 5 'user_log'定位原始事件,确认是不是 DDL 被跳过(如DROP TABLE或CREATE TABLE没执行)
检查复制过滤规则和 GTID 一致性
MySQL 5.7+ 和 8.0 默认开启 GTID,一旦主从 GTID set 不对齐,某些事务会被跳过,导致表结构不同步。
- 在从库执行
SELECT @@gtid_executed;和SELECT @@gtid_purged;,对比主库输出;若gtid_executed缺失某段,说明有事务没应用 - 检查是否启用了
replicate-do-db、replicate-ignore-table等过滤参数,它们会静默丢弃特定库/表的事件——SHOW SLAVE STATUS\G里的Replicate_Do_DB字段就是证据 - 如果主库用
CREATE TABLE IF NOT EXISTS建表,但从库已有同名表且结构不兼容,后续 DML 可能因列数/类型不匹配失败,错误却报成 “table doesn't exist”(尤其 ORM 自动生成 schema 时常见)
物理文件缺失或权限问题(Linux 从库特有)
从库进程(mysqld)用户对 datadir 下某个库目录无读取权限,会导致它扫描不到该库下的任何表,SHOW DATABASES 都不显示,自然报错。
- 用
SELECT @@datadir;查路径,再ls -ld /var/lib/mysql/your_db看属主和权限——必须至少有r-x给 mysql 用户 - CentOS/RHEL 上还要看 SELinux:
sestatus若为 enforcing,且audit.log里有 avc denied 记录,就得sudo setsebool -P mysqld_disable_transitive 1 - 检查
lower_case_table_names:主库 Windows(=1)导出的 SQL 在 Linux 从库(=0)执行CREATE TABLE User,再查SELECT * FROM user就会失败——用SELECT @@lower_case_table_names;对比主从值
最易被忽略的是:从库 SQL 线程卡在某个事务里,后续所有事件都积压,而你看到的 “table doesn't exist” 其实是更早一条被跳过的 DDL 导致的连锁反应。别只盯最后一行错误,得顺着 Relay_Master_Log_File 和 Exec_Master_Log_Pos 去翻 relay log 才能找到根因。











