SQL 四大语言分类详解
一、数据定义语言(DDL - Data Definition Language)
作用:定义和管理数据库结构(表、视图、索引等)
主要命令:
| 命令 | 功能 | 示例 |
|---|---|---|
| CREATE | 创建数据库对象 | CREATE TABLE students (...) |
| ALTER | 修改数据库对象 | ALTER TABLE students ADD COLUMN age INT |
| DROP | 删除数据库对象 | DROP TABLE students |
| TRUNCATE | 清空表数据(保留结构) | TRUNCATE TABLE students |
| RENAME | 重命名对象 | RENAME TABLE old TO new |
特点:
-
自动提交(隐式提交事务)
-
操作的是数据库结构,不是数据本身
-
执行后立即生效,无法回滚(部分数据库支持回滚DDL)
二、数据操纵语言(DML - Data Manipulation Language)
作用 :对数据库中的数据进行增删改查操作
主要命令:
| 命令 | 功能 | 示例 |
|---|---|---|
| SELECT | 查询数据 | SELECT * FROM students |
| INSERT | 插入数据 | INSERT INTO students VALUES (...) |
| UPDATE | 更新数据 | UPDATE students SET age=20 WHERE id=1 |
| DELETE | 删除数据行 | DELETE FROM students WHERE id=1 |
| MERGE | 合并数据(UPSERT) | MERGE INTO target USING source ON ... |
特点:
-
需要显式提交(COMMIT)或回滚(ROLLBACK)
-
操作的是表中的数据
-
支持事务控制
-
最常用的SQL命令类别
三、数据控制语言(DCL - Data Control Language)
作用:控制数据库访问权限和安全性
主要命令:
| 命令 | 功能 | 示例 |
|---|---|---|
| GRANT | 授予权限 | GRANT SELECT ON students TO user1 |
| REVOKE | 撤销权限 | REVOKE INSERT ON students FROM user1 |
| DENY | 拒绝权限(SQL Server特有) | DENY DELETE ON students TO user1 |
权限类型:
-
系统权限:CREATE TABLE、CREATE USER等
-
对象权限:SELECT、INSERT、UPDATE、DELETE、EXECUTE等
语法示例:
sql
-- 授予多个权限
GRANT SELECT, INSERT, UPDATE ON students TO user1;
-- 授予所有权限
GRANT ALL PRIVILEGES ON students TO user1;
-- 允许用户授权他人
GRANT SELECT ON students TO user1 WITH GRANT OPTION;
四、事务控制语言(TCL - Transaction Control Language)
作用:管理数据库事务,确保数据一致性
主要命令:
| 命令 | 功能 | 示例 |
|---|---|---|
| COMMIT | 提交事务,保存更改 | COMMIT; |
| ROLLBACK | 回滚事务,撤销更改 | ROLLBACK; |
| SAVEPOINT | 设置保存点 | SAVEPOINT sp1; |
| SET TRANSACTION | 设置事务属性 | SET TRANSACTION READ ONLY; |
ACID特性:
-
原子性(Atomicity):事务全部完成或全部不完成
-
一致性(Consistency):事务前后数据保持一致
-
隔离性(Isolation):事务间互不干扰
-
持久性(Durability):提交后永久保存
事务示例:
sql
START TRANSACTION; -- 或 BEGIN
UPDATE account SET balance = balance - 100 WHERE id = 1;
UPDATE account SET balance = balance + 100 WHERE id = 2;
-- 检查余额是否足够等业务逻辑
COMMIT; -- 或 ROLLBACK;
快速对比表
| 类别 | 命令举例 | 作用对象 | 是否需要提交 | 是否可以回滚 |
|---|---|---|---|---|
| DDL | CREATE, ALTER | 数据库结构 | 自动提交 | 一般不可以 |
| DML | SELECT, INSERT | 表数据 | 需要显式提交 | 可以 |
| DCL | GRANT, REVOKE | 用户权限 | 自动提交 | 不可以 |
| TCL | COMMIT, ROLLBACK | 事务 | - | - |
执行顺序与依赖关系
典型工作流程:
-
管理员:用 DDL 创建表结构
-
管理员:用 DCL 给用户分配权限
-
用户:用 DML 操作数据
-
用户:用 TCL 控制事务提交/回滚
权限依赖示例:
sql
-- 1. DDL:创建表
CREATE TABLE employees (id INT, name VARCHAR(50));
-- 2. DCL:授权给用户
GRANT INSERT, SELECT ON employees TO alice;
-- 3. 用户alice使用DML
INSERT INTO employees VALUES (1, '张三');
-- 4. 用户提交事务
COMMIT;
一、数据库加密的三个层面
| 层面 | 加密对象 | 典型技术 | 主要目的 |
|---|---|---|---|
| 传输层加密 | 网络传输的数据包 | SSL/TLS | 防止网络窃听 |
| 存储层加密 | 磁盘文件/备份文件 | TDE(透明数据加密)、文件系统加密 | 防止物理介质被盗 |
| 数据层加密 | 具体的字段/记录 | 字段加密、应用层加密 | 防止DBA或越权访问 |
我们主要讨论数据层加密,即字段级别的加密。
二、绝对不可以加密的字段
1. 主键字段
sql
CREATE TABLE users (
user_id INT PRIMARY KEY, -- ❌ 不能加密
username VARCHAR(50),
password_hash VARCHAR(100)
);
为什么不能加密?
-
主键用于唯一标识记录
-
加密后无法保证唯一性(相同明文加密后可能不同)
-
无法建立主键索引(索引基于加密值就失去意义)
2. 外键字段
sql
CREATE TABLE orders (
order_id INT PRIMARY KEY,
user_id INT, -- ❌ 不能加密(如果是外键)
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
为什么不能加密?
-
破坏引用完整性检查
-
无法匹配被引用表的主键值
-
连接查询(JOIN)无法工作
3. 索引字段(用于快速查找的列)
sql
CREATE INDEX idx_email ON users(email); -- 如果email加密,索引无效
为什么不能加密?
-
加密后的值失去原有顺序和模式
-
WHERE条件无法匹配:
WHERE email = 'alice@example.com' -
范围查询无法工作:
WHERE age BETWEEN 20 AND 30 -
例外:如果只是用索引判断"是否存在",且查询时提供加密值,理论上可以,但一般不这样做。
4. 用于排序的字段
sql
-- 按注册时间排序
SELECT * FROM users ORDER BY register_time; -- ❌ 如果register_time加密
为什么不能加密?
-
加密打乱时间顺序
-
ORDER BY无法正确排序
5. 用于分组的字段
sql
-- 按部门统计
SELECT department, COUNT(*)
FROM employees
GROUP BY department; -- ❌ 如果department加密
为什么不能加密?
-
相同部门名称加密后变成不同值
-
GROUP BY结果错误
6. 表连接字段
sql
-- 连接查询
SELECT *
FROM users u
JOIN orders o ON u.user_id = o.user_id; -- ❌ 如果连接字段加密
为什么不能加密?
- 无法匹配连接条件
7.关系运算的比较字段
一、事务的概念与特性(ACID)
1. 事务(Transaction)
-
定义 :数据库操作的逻辑工作单元,包含一个或多个操作序列
-
特点:要么全部执行,要么全部不执行
-
状态:
text
BEGIN → 活动 → 部分提交 → 提交 ↓ 失败 → 回滚 → 终止
2. ACID特性
| 特性 | 含义 | 破坏后果 | 保障机制 |
|---|---|---|---|
| A 原子性 (Atomicity) | 事务不可分割:要么全做,要么全不做 | 部分操作失败导致数据不一致 | 日志(UNDO) |
| C 一致性 (Consistency) | 事务使数据库从一个一致状态转到另一个一致状态 | 违反业务规则和完整性约束 | 应用逻辑+DBMS检查 |
| I 隔离性 (Isolation) | 并发事务互不干扰 | 脏读、不可重复读、幻读 | 并发控制协议 |
| D 持久性 (Durability) | 事务提交后结果永久保存 | 系统故障导致提交结果丢失 | 日志(REDO)+备份 |
二、事务调度(Scheduling)
1. 基本概念
-
调度:多个事务的操作按时间顺序的排列
-
串行调度:事务一个接一个执行,无交叉
-
并行(并发)调度:事务操作交叉执行
-
可串行化调度 :并发执行结果 等价于某个串行调度的结果
2. 调度正确性标准
text
可串行化调度 ⊆ 可恢复调度 ⊆ 无级联回滚调度
3. 可串行化类型
-
冲突可串行化(重点)
-
视图可串行化(更强但难判断)
三、冲突可串行化调度
1. 冲突操作
两个操作冲突当且仅当:
-
属于不同事务
-
操作同一数据项
-
至少有一个是写操作
| 操作对 | 是否冲突 | 原因 |
|---|---|---|
| Read(A)-Read(A) | ❌ | 都是读,不改变值 |
| Read(A)-Write(A) | ✅ | 读后写可能读到旧值 |
| Write(A)-Read(A) | ✅ | 写后读可能读到未提交值 |
| Write(A)-Write(A) | ✅ | 写覆盖顺序影响结果 |
2. 冲突等价
两个调度是冲突等价的,如果:
-
包含相同事务的相同操作
-
每一对冲突操作的顺序相同
3. 冲突可串行化判定
方法:前驱图(Precedence Graph / Serialization Graph)
构建步骤:
-
为每个事务创建一个节点
-
对于每对冲突操作 Ti → Tj(Ti的操作在Tj之前),画边 Ti → Tj
-
如果图无环,则调度是冲突可串行化的
示例:
调度:r1(A) w1(A) r2(A) w2(A) r1(B) w1(B) r2(B) w2(B)
text
冲突对:
r1(A)-w2(A) → T1→T2
w1(A)-r2(A) → T1→T2
w1(A)-w2(A) → T1→T2
r1(B)-w2(B) → T1→T2
w1(B)-r2(B) → T1→T2
w1(B)-w2(B) → T1→T2
图:T1 → T2(无环) → 冲突可串行化(等价于T1;T2)
四、基于锁的并发控制
1. 锁的基本类型
| 锁类型 | 符号 | 允许的操作 | 兼容性 |
|---|---|---|---|
| 共享锁 (S) | LOCK-S | 读操作 | 与S锁兼容,与X锁不兼容 |
| 排他锁 (X) | LOCK-X | 写操作 | 与任何锁都不兼容 |
2. 两阶段封锁协议(2PL)
-
增长阶段:只能获得锁,不能释放锁
-
缩减阶段:只能释放锁,不能获得锁
-
封锁点:获得最后一个锁的时刻
特点:
-
保证冲突可串行化
-
但可能死锁
3. 锁的升级
-
升级:S锁 → X锁
-
降级:X锁 → S锁(只能在缩减阶段)
4. 多粒度锁
粒度层次:
text
数据库 → 表 → 页 → 记录
意向锁:
| 锁类型 | 含义 | 用途 |
|---|---|---|
| IS锁 | 意向共享锁 | 将在下层加S锁 |
| IX锁 | 意向排他锁 | 将在下层加X锁 |
| SIX锁 | 共享意向排他锁 | 已有S锁,将在下层加X锁 |
兼容矩阵:
text
| S | X | IS | IX | SIX
----|----|----|----|----|-----
S | ✓ | ✗ | ✓ | ✗ | ✗
X | ✗ | ✗ | ✗ | ✗ | ✗
IS | ✓ | ✗ | ✓ | ✓ | ✓
IX | ✗ | ✗ | ✓ | ✓ | ✗
SIX | ✗ | ✗ | ✓ | ✗ | ✗
五、基于时间戳的并发控制
1. 时间戳(Timestamp)
-
每个事务分配唯一时间戳 TS(T)
-
通常用系统时钟 或逻辑计数器
-
反映事务开始的先后顺序
2. 基本规则
每个数据项X维护:
-
RTM(X):读时间戳(最后成功读X的事务时间戳)
-
WTM(X):写时间戳(最后成功写X的事务时间戳)
读操作规则:
text
if TS(T) < WTM(X) then
回滚T(读到未来值)
else
执行读,RTM(X) = max(RTM(X), TS(T))
写操作规则:
text
if TS(T) < RTM(X) or TS(T) < WTM(X) then
回滚T(覆盖未来读或未来写)
else
执行写,WTM(X) = TS(T)
3. Thomas写规则优化
如果 TS(T) < WTM(X) 但 ≥ RTM(X),则:
-
忽略写操作(因为后续值已被覆盖)
-
不执行,不回滚
六、事务隔离级别
1. 读现象(隔离问题)
| 现象 | 描述 | 示例 |
|---|---|---|
| 脏读 | 读到未提交的数据 | T1写A未提交,T2读A |
| 不可重复读 | 同一事务内两次读结果不同 | T1读A,T2修改A并提交,T1再读A |
| 幻读 | 同一查询返回不同行数 | T1查询age>20得2行,T2插入age=25并提交,T1再查得3行 |
2. SQL标准隔离级别
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 实现机制 |
|---|---|---|---|---|
| 读未提交 (READ UNCOMMITTED) | 允许 | 允许 | 允许 | 无锁或读不加锁 |
| 读已提交 (READ COMMITTED) | 防止 | 允许 | 允许 | 读时加锁,读完释放 |
| 可重复读 (REPEATABLE READ) | 防止 | 防止 | 允许 | 读时加锁,事务结束释放 |
| 可串行化 (SERIALIZABLE) | 防止 | 防止 | 防止 | 范围锁/表锁 |
注意:MySQL的REPEATABLE READ通过MVCC防止了幻读。
七、基于日志的恢复技术
1. 日志(Log)
日志记录类型:
sql
-- 1. 事务开始
<Ti, START>
-- 2. 更新记录(重要!)
<Ti, X, V_old, V_new>
-- Ti:事务ID
-- X:数据项
-- V_old:旧值(UNDO用)
-- V_new:新值(REDO用)
-- 3. 提交
<Ti, COMMIT>
-- 4. 中止/回滚
<Ti, ABORT>
日志原则:
-
先写日志(WAL):日志先于数据写入磁盘
-
日志必须持久化:提交前,日志必须写入磁盘
2. 检查点(Checkpoint)
作用:
-
减少恢复时间
-
确定恢复起点
检查点记录:
text
<CHECKPOINT, 活跃事务列表>
检查点类型:
| 类型 | 过程 | 恢复复杂度 |
|---|---|---|
| 静止检查点 | 暂停所有事务,写脏页 | 简单 |
| 非静止检查点 | 记录活跃事务,继续运行 | 复杂 |
3. 恢复过程
分析阶段:
-
确定故障时活跃事务集合
-
读取日志,建立事务表
REDO阶段:
-
重做所有已提交事务的更新
-
从最早的检查点开始
-
规则:即使数据已写入磁盘,也要重做(保证持久性)
UNDO阶段:
-
回滚所有未提交事务的更新
-
按日志反向扫描,恢复旧值
4. 恢复列表
| 列表 | 包含事务 | 处理方式 |
|---|---|---|
| REDO列表 | 检查点前开始,故障时已提交或未提交 | 需要重做 |
| UNDO列表 | 故障时未提交 | 需要回滚 |
关键定理:已提交的事务进REDO列表,未提交的事务进UNDO列表。