mysql实例是运行中的mysqld进程及其内存结构、线程池等资源总和,负责sql解析、事务执行与文件操作;数据库是实例内的逻辑容器,一个实例可管理多个数据库,但数据库不能跨实例存在。

MySQL 实例是进程,不是“数据库”本身
你连的不是某个库,而是 mysqld 这个正在跑的服务进程。它在内存里维护缓冲池、日志、线程,负责解析 SQL、执行事务、管理文件——所有操作都经它中转。没这个进程,.ibd 文件就是一堆无法读写的二进制数据。
常见错觉:“我重启了数据库”,实际是 systemctl restart mysqld;“我备份了数据库”,其实要分清:只 dump 数据用 mysqldump,整实例迁移得复制 datadir + 配置 + 日志。
一个服务器可以起多个实例(不同端口、不同 datadir),彼此完全不共享内存或磁盘路径,哪怕名字都叫 mysql,也是独立进程。
数据库是命名空间和权限边界,不是文件夹
CREATE DATABASE app_db 不是在磁盘建个空目录,而是在数据字典注册一个逻辑容器:它定义默认字符集、校对规则,并作为权限分配的最小单位。用户能被授予 SELECT ON app_db.*,但不能跨库隐式访问。
表名只在库内唯一:app_db.users 和 hr_db.users 完全无关;删库 DROP DATABASE app_db 会直接递归删掉 datadir/app_db/ 下所有文件,不可恢复。
容易踩的坑:
- 忘记
USE app_db就执行CREATE TABLE,结果表建到了information_schema或默认库,报错ERROR 1046 (3D000): No database selected - 误以为改数据库字符集就能统一所有表——其实只影响后续新建表的默认值,已有表字段仍保持原编码
表才是存数据的地方,结构决定行为
字段类型、主键、索引、外键约束全由表定义。数据库不存任何业务数据,也不管你字段能不能为 NULL、要不要自增——这些都在 CREATE TABLE 里写死。
物理落地方式取决于引擎:
- InnoDB(MySQL 8.0 默认):一张表对应一个
.ibd文件,含数据+索引;删掉它,数据彻底丢失 - MyISAM(已弃用):拆成
.MYD(数据)、.MYI(索引)、.sdi(结构定义)三个文件
外键生效有硬约束:REFERENCES 的两张表必须都是 InnoDB,关联字段类型必须严格一致(INT 不能对 BIGINT),且被引用列要有索引(通常是主键)。
建表必须绑定数据库上下文
两种合法写法:
- 先切换:
USE app_db;,再CREATE TABLE users (...) - 显式限定:
CREATE TABLE app_db.users (...)
不推荐省略库名直接建表,尤其在脚本或自动化部署中——一旦连接时未指定默认库或 USE 失败,表就建到错地方,线上事故常见于此。
真正麻烦的是跨库查询:你不能写 SELECT * FROM users JOIN orders 就自动关联两个库的表,必须写成 SELECT * FROM app_db.users JOIN finance_db.orders,否则 MySQL 默认只查当前库。











