数据库系统の安全与完整性:谁来保护你的数据?
你存在银行的钱、你的社交账号密码、你的体检报告------这些数据在数据库里,到底靠什么保证不被偷看、不被乱改?
数据库的"保护伞"有两把:安全性 防的是"坏人"(非法用户),完整性防的是"坏数据"(非法操作)。这篇文章把这两把伞从里到外讲透------身份鉴别怎么验明正身、GRANT/REVOKE怎么管权限、三大完整性约束怎么防错数据、触发器怎么自动兜底。期末考试要考安全与完整性的同学,这一篇就够了。
本文目录
-
安全性概述:数据库面临哪些威胁?
-
身份鉴别:你是你吗?
-
存取控制:DAC与MAC
-
视图、审计与加密
-
完整性概述:防"坏数据"
-
三大完整性约束详解
-
高级完整性机制:触发器与断言
-
安全性 vs 完整性:一文厘清
一、安全性概述:数据库面临哪些威胁?
1.1 什么是数据库安全性?
数据库安全性 ,简单说就是:防止非法用户对数据库的非法使用,防止合法用户对数据库的非法操作。
核心目标是防止数据被泄露、篡改或破坏。

数据库安全面临的威胁与防护方法
注意一个常见混淆:安全性 ≠ 完整性。
安全性防的是"谁在操作"(Who)------不让不该碰数据的人碰到数据。
完整性防的是"操作什么"(What)------不让合法用户往数据库里塞错误数据。
打个比方:安全性是"门禁"(只有持卡人能进大楼),完整性是"规章制度"(进了大楼也不能乱扔垃圾)。
1.2 数据库面临的四大威胁
非授权用户存取数据 ------没有账号的黑客通过SQL注入等手段非法访问数据。
授权用户越权操作 ------有合法账号但干了不该干的事。比如一个普通员工偷偷查看了全公司的工资表。
数据泄露(推理攻击) ------用户虽然不能直接看到敏感数据,但可以通过多次查询的结果"推理"出来。比如查"部门A的平均工资"和"部门A除张三外的平均工资",两个一减就能算出张三的工资。
拒绝服务攻击(DoS) ------通过大量无效请求耗尽数据库资源,让正常用户无法使用。
1.3 安全控制的五大方法
面对这些威胁,DBMS提供了五层防护:
身份鉴别(Authentication) ------验明正身,确认"你是谁"。
存取控制(Authorization) ------权限管理,决定"你能做什么"。
审计(Audit) ------操作记录,追踪"你做了什么"。
数据加密(Encryption) ------数据保护,即使被偷走也看不懂。
视图机制(View) ------数据过滤,只让你看到该看的部分。
二、身份鉴别:你是你吗?
用户要访问数据库,首先得证明"我是我"。身份鉴别是安全控制的第一道关卡。
2.1 静态口令鉴别
最常见的方案:用户名 + 密码。简单、成本低,但安全性也最低------密码可能被猜到、被偷看、被暴力破解。大多数数据库系统(MySQL、Oracle等)都支持这种方式。
2.2 动态口令鉴别
一次性密码(OTP)------每次登录的密码都不同。常见形式:手机短信验证码、动态令牌(银行U盾)。比静态口令安全得多,因为即使本次密码被偷窥,下次也用不了。
2.3 生物特征鉴别
利用指纹、虹膜、面部识别等生物特征来鉴别。安全性高、不可伪造,但成本也高。目前主要用于高安全级别的场景(如银行金库、军事设施)。
2.4 数字证书鉴别
基于PKI(公钥基础设施),用数字证书证明身份。安全性最高,常用于网络传输和重要系统之间的身份认证。
三、存取控制:DAC与MAC
身份鉴别解决了"你是谁"的问题,存取控制解决"你能做什么"。
3.1 自主存取控制(DAC)

DAC与MAC:两种存取控制方式对比
DAC(Discretionary Access Control)------数据的所有者可以自主决定把数据的使用权限授予谁。这是最灵活、最常用的存取控制方式。
GRANT:授权
GRANT SELECT ON TABLE Employee TO Alice;
GRANT INSERT, UPDATE ON TABLE Student TO Bob;
GRANT ALL PRIVILEGES ON TABLE Course TO Charlie;
GRANT语句的格式:GRANT 权限 ON 对象 TO 用户。权限包括SELECT(查询)、INSERT(插入)、UPDATE(修改)、DELETE(删除)、ALL PRIVILEGES(全部权限)。
WITH GRANT OPTION ------如果加上这个选项,被授权的用户还可以把权限转授给其他人。这就形成了一个"权限链":
GRANT SELECT ON TABLE Employee TO Alice WITH GRANT OPTION;
-- Alice 可以再授权给 Bob
GRANT SELECT ON TABLE Employee TO Bob; -- Alice执行
REVOKE:回收权限
REVOKE SELECT ON TABLE Employee FROM Alice;
REVOKE INSERT ON TABLE Student FROM Bob CASCADE;
CASCADE(级联回收)------如果Alice曾经把权限转授给了Bob,那么回收Alice的权限时,Bob的权限也会被一起回收。这是为了防止权限链失控。
3.2 强制存取控制(MAC)
MAC(Mandatory Access Control)------系统强制实施存取规则,用户不能自行控制。主要用于高安全性场景(军事、政府)。
MAC给每个数据对象和每个用户分别标记密级 。密级从低到高:公开 < 秘密 < 机密 < 绝密。
MAC的核心规则只有两条:
读向下(Read Down) ------用户只能读取密级不高于自己安全级别的数据。绝密级用户可以读所有数据,公开级用户只能读公开数据。
写向上(Write Up) ------用户只能写入密级不低于自己安全级别的数据。这是为了防止高密级用户把敏感信息写到低密级的数据对象中(信息泄露)。
DAC与MAC的关系------DAC是基础,MAC更严格。实际系统中,先检查DAC(用户有没有被授权),通过后再检查MAC(用户的密级是否满足要求)。
3.3 角色(Role)
当用户很多时,逐个授权太麻烦。**角色(Role)**把一组权限打包:
CREATE ROLE manager;
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE Employee TO manager;
GRANT manager TO Alice, Bob, Charlie; -- 一次性给三个人授权
角色的好处:简化权限管理。员工入职时授予角色,离职时回收角色,权限变更时只需修改角色的权限定义。

GRANT与REVOKE:权限的授予与回收
四、视图、审计与加密
4.1 视图的安全作用
视图(View)是一种虚拟表,它不存储实际数据,而是从基本表中查询数据。视图的安全作用在于:
隐藏敏感列------比如员工表有"工资"列,可以通过视图只暴露姓名、部门,隐藏工资。
限制行级访问------比如普通部门经理只能看到本部门员工的数据。
CREATE VIEW EmpView AS SELECT Ename, Dno, Job FROM Employee;
-- 用户查询EmpView时看不到Salary列
但视图的安全能力有限------它只是辅助手段,不能替代DAC和MAC。
4.2 审计(Audit)
审计就是"装监控"------记录用户对数据库的所有操作:谁在什么时间对什么数据做了什么。
审计日志用于事后追踪和安全分析。比如发现数据被篡改了,可以查审计日志找到是谁在什么时间做的修改。
审计的代价:每次操作都需要额外写日志,会影响系统性能。因此审计通常只在高安全性要求的环境中开启。
4.3 数据加密
即使攻击者绕过了所有身份鉴别和存取控制,把数据偷走了,加密也能让他们拿到的只是一堆乱码。
透明数据加密(TDE)------对应用层透明,数据库自动加密和解密。应用不需要改代码。
应用级加密------应用层加密后存入数据库,数据库本身存的是密文。安全性更高,但应用需要处理加解密逻辑。
列级加密------只对敏感列(如密码、身份证号)加密,其他列不加密。
加密算法分两类:
对称加密(如AES)------加解密使用同一个密钥,速度快,适合大量数据。
非对称加密(如RSA)------公钥加密、私钥解密,安全性更高,常用于密钥交换和数字签名。
五、完整性概述:防"坏数据"
从这一节开始,话题从"防坏人"转向"防坏数据"。
5.1 什么是完整性?
完整性(Integrity) 是指数据的正确性(Correctness) 和相容性(Compatibility)。
正确性:数据是否符合现实世界的事实。比如年龄不能是负数,性别只能是"男"或"女"。
相容性:同一事物在不同地方的描述是否一致。比如学生表里张三的学号和选课表里张三的学号必须一致。
5.2 完整性控制的三个环节
定义完整性约束------声明数据必须满足什么条件。比如"主码不能为空"、"年龄必须在0到150之间"。
检查完整性约束------每当用户执行插入、修改、删除操作时,DBMS自动检查操作是否违反了已定义的约束。
处理违约操作------如果违反了约束怎么办?拒绝操作?级联修改?还是置为空值?
六、三大完整性约束详解
6.1 实体完整性

三大完整性约束:实体完整性、参照完整性、用户定义完整性
规则:主码不能为空(NOT NULL),且主码值必须唯一。
为什么?因为主码的作用是唯一标识一个元组(一行记录)。如果主码为空,就无法区分不同的元组;如果主码重复,就无法唯一确定某个元组。
定义方式:
-- 列级约束
CREATE TABLE Student (
Sno CHAR(9) PRIMARY KEY,
Sname VARCHAR(20) NOT NULL
);
-- 表级约束
CREATE TABLE SC (
Sno CHAR(9),
Cno CHAR(4),
Grade INT,
PRIMARY KEY (Sno, Cno) -- 复合主码
);
违反处理:直接拒绝插入或更新操作。比如试图插入一条Sno为空的记录,DBMS会报错并拒绝。
6.2 参照完整性
规则:外码的值必须是被引用关系主码的有效值,或者为空值(NULL)。
为什么?因为外码表示的是"引用关系"------比如学生表里的"院系编号"引用了院系表的主码。如果学生的院系编号在院系表中不存在,就意味着这个学生属于一个"不存在的院系"------这显然是不合理的。
定义方式:
CREATE TABLE Student (
Sno CHAR(9) PRIMARY KEY,
Sname VARCHAR(20),
Dno CHAR(3),
FOREIGN KEY (Dno) REFERENCES Department(Dno)
);

参照完整性的四种违约处理策略
违约处理策略------当操作导致参照完整性被违反时,有四种处理方式:
NO ACTION(拒绝)------直接拒绝导致违约的操作。这是默认策略,也是最安全的。
CASCADE(级联)------连带执行相关操作。比如删除一个院系时,自动删除该院系下所有学生。
SET NULL(置空)------将外码值设为NULL。比如删除一个院系时,该院系学生的院系编号设为空。
SET DEFAULT(置默认值)------将外码值设为预定义的默认值。
CREATE TABLE Student (
Sno CHAR(9) PRIMARY KEY,
Dno CHAR(3),
FOREIGN KEY (Dno) REFERENCES Department(Dno)
ON DELETE CASCADE -- 删除院系时级联删除学生
ON UPDATE SET NULL -- 修改院系编号时将学生院系置空
);
选择哪种策略取决于具体业务需求。一般情况下NO ACTION最安全,CASCADE适合"父子关系"(订单和订单明细)。
6.3 用户定义完整性
除了实体完整性和参照完整性这两种"通用"约束,每个应用还有自己特定的数据约束------这就是用户定义完整性。
NOT NULL------非空约束。某些属性不能为空(如姓名)。
UNIQUE------唯一约束。某些属性的值不能重复(如身份证号)。
CHECK------检查约束。属性值必须满足指定条件:
CREATE TABLE Student (
Sno CHAR(9) PRIMARY KEY,
Sname VARCHAR(20) NOT NULL,
Sage INT CHECK (Sage >= 15 AND Sage <= 45),
Ssex CHAR(2) CHECK (Ssex IN ('男', '女')),
Dno CHAR(3) UNIQUE
);
DEFAULT------默认值。如果插入时没有指定该列的值,自动使用默认值。
七、高级完整性机制:触发器与断言
7.1 触发器(Trigger)
触发器是一种特殊的存储过程------在特定事件发生时自动执行。
CREATE TRIGGER delete_student_courses
AFTER DELETE ON Student
FOR EACH ROW
BEGIN
DELETE FROM SC WHERE Sno = OLD.Sno;
END;
这个触发器的含义:当从Student表中删除一条记录时,自动从SC(选课)表中删除该学生的所有选课记录。
触发器三要素:触发事件 (INSERT/UPDATE/DELETE)、触发时机 (BEFORE/AFTER)、触发器体(要执行的SQL语句)。
触发器的用途很广:实现复杂的完整性约束(跨表约束)、自动审计(记录谁在什么时间修改了什么数据)、自动维护派生数据(如自动更新统计表)。
7.2 存储过程(Stored Procedure)
存储过程是预编译的SQL语句集合,可以包含业务逻辑和完整性检查。
CREATE PROCEDURE enroll_student(IN sno CHAR(9), IN cno CHAR(4))
BEGIN
DECLARE max_cap INT;
SELECT capacity INTO max_cap FROM Course WHERE Cno = cno;
IF (SELECT COUNT(*) FROM SC WHERE Cno = cno) < max_cap THEN
INSERT INTO SC VALUES (sno, cno, NULL);
ELSE
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '课程已满';
END IF;
END;
存储过程的好处:封装业务逻辑(选课人数限制在过程里检查,不用每个应用都写一遍)、减少网络传输(一次调用完成多个操作)、提高性能(预编译,不用每次解析SQL)。
7.3 断言(Assertion)
断言是一种更一般化的完整性约束,可以涉及多个表的全局约束:
CREATE ASSERTION student_course_limit
CHECK (NOT EXISTS (
SELECT Sno FROM SC
GROUP BY Sno
HAVING COUNT(*) > 10
));
这个断言的含义:每个学生最多选10门课。
断言功能强大,但目前大多数主流DBMS(MySQL、PostgreSQL等)并不完全支持断言。实际开发中,通常用触发器或存储过程来替代断言实现类似的全局约束。
八、安全性 vs 完整性:一文厘清

安全性与完整性:两种不同的数据保护机制
这两个概念容易混淆,这里做一个清晰的对比:
| 对比维度 | 安全性(Security) | 完整性(Integrity) |
|---|---|---|
| 保护对象 | 防止非法用户/非法操作 | 防止错误数据/不一致数据 |
| 核心问题 | Who------谁能访问数据? | What------什么数据是合法的? |
| 比喻 | 门禁系统 | 规章制度 |
| 主要手段 | 身份鉴别、授权、加密、审计 | 约束、触发器、存储过程 |
| SQL实现 | GRANT/REVOKE | PRIMARY KEY/FOREIGN KEY/CHECK/触发器 |
| 违反后果 | 数据泄露、被篡改、被破坏 | 数据错误、不一致、失去意义 |
两者的联系:它们相辅相成,共同保护数据库。视图既是安全机制(限制用户只能看到部分数据),也是完整性的辅助手段。触发器可以同时服务于安全(审计触发器记录操作)和完整性(约束触发器检查数据)。
总结
数据库的"保护伞"有两把,缺一不可:
安全性------五层防护层层把关:身份鉴别(你是谁)→ 存取控制(你能做什么,DAC用GRANT/REVOKE管理权限,MAC用密级控制读写)→ 视图(只让你看该看的)→ 审计(记录你做了什么)→ 加密(即使偷走也看不懂)。
完整性------三个环节环环相扣:定义约束(声明规则)→ 检查约束(操作时自动验证)→ 处理违约(拒绝/级联/置空/默认值)。三大完整性约束各司其职:实体完整性保主码、参照完整性保引用、用户定义完整性保业务规则。高级机制(触发器、存储过程、断言)处理更复杂的场景。
一句话总结:安全性是"不让不该碰数据的人碰到数据",完整性是"不让合法的人往数据库里塞垃圾数据"------一个防外贼,一个防内鬼(的失误)。