mysql数据完整性是什么_mysql约束条件说明

来源:这里教程网 时间:2026-02-28 20:45:36 作者:

MySQL 数据完整性不是“有没有数据”,而是数据是否准确、一致、合法、可信赖——它靠约束条件来强制保障,不是靠人写代码时小心谨慎。


主键和唯一约束:为什么不能只靠程序校验?

主键(

PRIMARY KEY
)和唯一约束(
UNIQUE
)解决的是“重复”问题。比如用户注册时用程序查一遍
username
是否存在,再插入——这在并发场景下必然漏掉竞态:两个请求几乎同时通过检查,然后都插入成功。

PRIMARY KEY
=
NOT NULL
+
UNIQUE
,且一个表只能有一个
UNIQUE
列允许
NULL
,但多个
NULL
不算重复(MySQL 行为)
复合唯一约束要写成表级:
CREATE TABLE orders (
  user_id INT,
  order_no VARCHAR(20),
  UNIQUE (user_id, order_no)
);
别指望应用层“先查后插”替代唯一约束——它不原子,也不防并发

外键约束:关联表之间谁该删、谁该留?

外键(

FOREIGN KEY
)不是锦上添花的功能,它是防止“孤儿记录”的最后一道防线。比如删除客户前没清理订单,就会留下指向不存在客户的
customer_id

启用外键需存储引擎为
InnoDB
MyISAM
不支持)
被引用的列必须有索引(通常是主键或唯一索引),否则建外键会失败 级联行为要显式声明:
ON DELETE CASCADE
ON DELETE RESTRICT
,默认是
RESTRICT
线上环境慎用
CASCADE
:一个
DELETE
可能触发多层隐式删除,难以追溯

非空、默认值与检查约束:哪些字段真该强制?

NOT NULL
DEFAULT
看似简单,但错配会导致数据“看似存在,实则无效”。例如
status TINYINT DEFAULT 0
,但业务中
0
并不表示“未设置”,而是“已取消”——这就让默认值失去语义。

NOT NULL
应用于真正不可缺失的字段(如
created_at
user_id
),而非所有字段都加
DEFAULT
推荐用确定性表达式:
CURRENT_TIMESTAMP
'1970-01-01'
更可靠
CHECK
约束从 MySQL 8.0.16 起才完整支持(早期版本会解析但忽略),例如:
CREATE TABLE products (
  price DECIMAL(10,2),
  CHECK (price >= 0)
);
避免用
CHECK
做复杂逻辑(如正则邮箱校验),性能差且难调试;这类应交由应用层或触发器

约束不是越多越好:它们怎么悄悄拖慢你的 SQL?

每个约束都是实时校验点。主键索引加速查询,但也让每次

INSERT/UPDATE
多一次 B+ 树查找;外键会锁住被引用行(即使是
SELECT
),引发死锁风险;
CHECK
在批量导入时可能成为瓶颈。

高频写入表(如日志、埋点)通常禁用外键,靠应用层保证关系 临时表、ETL 中间表可先去掉约束,等数据清洗完成再加回
SHOW CREATE TABLE t
查看真实生效的约束,注意某些 ORM 或迁移工具会静默跳过不支持的约束(比如旧版 MySQL 忽略
CHECK
约束名最好自定义(如
fk_orders_customer_id
),否则报错信息里只显示系统生成的乱码名,排查困难

约束真正的价值,不在“加了就安全”,而在“没它就一定出错”。很多线上数据异常,追根溯源都是某张表少了一个

NOT NULL
,或外键没建导致关联断裂——这种问题不会立刻报错,但会在某个报表、某次导出、某条聚合查询里突然崩出来。

相关推荐