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

9次阅读

mysql数据完整性靠约束强制保障而非人工校验;主键和唯一约束防并发重复;外键防孤儿记录且需InnoDB支持;NOT NULLdefault、CHECK需语义准确;约束过多会降低写入性能。

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

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

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

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

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

  • NOT NULL 应用于真正不可缺失的字段(如 created_atuser_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,或外键没建导致关联断裂——这种问题不会立刻报错,但会在某个报表、某次导出、某条聚合查询里突然崩出来。

text=ZqhQzanResources