【MySQL】触发器、日志、锁机制 深度解析
文章目录
- 一、触发器
- (一)触发器、存储过程 的区别
- (二)触发器三要素
- (三)NEW 与 OLD 的使用
- (四)创建语法
- (五)触发器管理(查看/删除)
- (六)注意事项
- 1. 避免递归循环触发:
- 2. 性能损耗问题:
- 二、日志
- (一)错误日志(Error Log)
- (二)二进制日志(BINLOG)
- 三、锁机制
- 一、锁的分类
- 二、MyISAM 表锁实操指南
一、触发器
与表关联的特殊存储过程,无需手动调用,当对表执行 INSERT、UPDATE、DELETE 这三类 DML 操作时,会自动触发执行预设的 SQL 逻辑。
核心特性:
- 自动性:触发事件发生时无需人工干预,自动执行。
- 关联性:必须依附于某张具体表,无法独立存在(表删除时触发器同步删除)。
- 行级触发:MySQL 仅支持「行级触发」(FOR EACH ROW),即每影响一行数据就执行一次触发器逻辑。
- 数据访问性:通过 NEW(新数据)和 OLD(旧数据)关键字,可访问触发前后的数据。
(一)触发器、存储过程 的区别
| 对比维度 | 触发器(Trigger) | 存储过程(Stored Procedure) |
|---|---|---|
执行方式 | 自动触发(DML 事件驱动) | 手动调用(CALL 存储过程名()) |
| 关联对象 | 必须绑定某张表,无法独立存在 | 独立存在,可跨表调用逻辑 |
| 适用场景 | 数据校验、日志记录、自动同步、强制业务规则 | 复杂业务逻辑封装、批量数据处理 |
(二)触发器三要素
| 要素 | 可选值/说明 |
|---|---|
| 触发时机 | BEFORE(事件执行前)、AFTER(事件执行后) |
| 触发事件 | INSERT(插入数据)、UPDATE(更新数据)、DELETE(删除数据) |
| 触发粒度 | FOR EACH ROW(行级触发,MySQL 唯一支持的粒度,每影响一行执行一次) |
(三)NEW 与 OLD 的使用
触发器中通过 NEW 和 OLD 关键字访问触发前后的数据,二者适用场景随触发事件不同而变化:
| 触发事件 | NEW关键字作用 | OLD 关键字作用 | 适用场景示例 |
|---|---|---|---|
INSERT | 表示「将要插入」或「已插入」的新数据 | 不支持(无旧数据可引用) | 插入订单时,用 NEW.product_id 关联商品表 |
UPDATE | 表示「将要更新」或「已更新」的新数据 | 表示「更新前」的旧数据 | 修改用户余额时,用 OLD.balance 记录历史值 |
DELETE | 不支持(无新数据) | 表示「将要删除」或「已删除」的旧数据 | 删除用户时,用 OLD.id 记录被删用户 ID |
使用语法:NEW.字段名 或 OLD.字段名(如 NEW.quantity、OLD.email)。
(四)创建语法
-- 单语句触发器(无需 BEGIN/END)
CREATE TRIGGER 触发器名
BEFORE/AFTER INSERT/UPDATE/DELETE ON 表名
FOR EACH ROW
单条执行语句-- 多语句触发器(需 BEGIN/END 与自定义结束符)
DELIMITER $$
-- 创建触发器
CREATE TRIGGER 触发器名
BEFORE/AFTER INSERT/UPDATE/DELETE ON 表名
FOR EACH ROW
BEGIN执行语句列表
END $$
DELIMITER ;
当逻辑包含多条 SQL 语句时,需用 BEGIN…END 包裹,并通过 DELIMITER 修改 SQL 结束符(避免与触发器内的 ; 冲突):
(五)触发器管理(查看/删除)
-- 查看当前数据库所有触发器
SHOW TRIGGERS;-- 删除触发器
DROP TRIGGER [IF EXISTS] 触发器名;
(六)注意事项
1. 避免递归循环触发:
严禁对触发器关联的表执行 INSERT / UPDATE / DELETE 操作,否则会触发“触发器→表操作→再触发触发器”的无限循环。
2. 性能损耗问题:
- 触发器是「行级触发」,若一次性操作大量数据(如批量插入 1000 行),会触发 1000 次触发器,严重拖慢执行速度;
- 复杂逻辑(如多表关联查询、嵌套条件)会进一步增加数据库负担,建议轻量逻辑用触发器,复杂逻辑用应用层或 ETL 工具。
二、日志
MySQL 日志用于记录数据库运行过程中的各类事件,帮助管理员追踪操作、排查故障、恢复数据。
核心作用:
- 故障排查:定位数据库启动/运行中的错误
- 数据恢复:灾难场景下还原数据
- 主从复制:支撑集群数据同步(依赖 binlog)
- 审计追踪:记录关键数据操作行为
(一)错误日志(Error Log)
MySQL 最重要的日志之一,记录关键事件:
- mysqld 服务的启动、停止过程
- 运行中发生的严重错误(如崩溃、权限不足、配置错误)
- 数据库无法正常使用时,优先查看此日志
默认配置 :
- 开启状态:默认自动开启,无需手动配置
- 存放目录:MySQL 数据目录(与数据文件同路径)
- 日志文件名:默认
hostname.err(hostname 为服务器主机名)
-- 查看日志位置
show variables like 'log_error%';
(二)二进制日志(BINLOG)
- 记录内容:所有 DDL 语句和 DML 语句,不包含数据查询语句
- 核心用途:灾难数据恢复、主从复制(MySQL 集群同步的核心依赖)
- 开启状态:MySQL 8.0 默认开启;低版本(如 5.7 及以下)需手动配置
手动开启与配置,需修改配置文件,不同系统路径不同:
- Windows 系统:配置文件为 my.ini
- Linux 系统:配置文件为 my.cnf
# 开启 binlog 日志,指定日志文件前缀 mysqlbin
log_bin = mysqlbin# 配置 binlog 日志格式
binlog_format = STATEMENT
| 日志格式 | 记录内容 | 核心特点 |
|---|---|---|
| STATEMENT | 记录完整的 SQL 语句(如 UPDATE tb_book SET status=‘1’) | 日志体积小,可读性强;主从复制时从库重新执行 SQL |
| ROW | 记录每一行数据的变更(而非 SQL 语句) | 日志体积大;避免 SQL 函数(如 NOW())导致的主从数据不一致,准确性更高 |
| MIXED | 混合 STATEMENT 和 ROW 格式 | 系统自动判断场景:简单 SQL 用 STATEMENT,复杂场景(如含函数、批量更新)用 ROW,兼顾性能与准确性 |
三、锁机制
MySQL 锁机制相对简单,最显著特点是不同存储引擎支持不同锁机制,核心作用是控制并发访问、避免数据冲突。
一、锁的分类
按操作粒度划分:
- 表锁:操作时锁定整个表,锁定粒度大。
- 行锁:操作时仅锁定当前操作行,锁定粒度小。
按操作类型划分:
- 读锁(共享锁):同一份数据可支持多个同时读操作,互不影响。
- 写锁(排它锁):操作未完成前,会阻断其他读锁和写锁。
| 存储引擎 | 行级锁支持情况 |
|---|---|
| MyISAM | 不支持 |
| InnoDB | 支持 |
| MEMORY | 不支持 |
| BDB | 不支持 |
| 锁类型 | 核心特点 |
|---|---|
| 表级锁 | 偏向 MyISAM 存储引擎;开销小、加锁快;无死锁;并发度最低,锁冲突概率最高 |
| 行级锁 | 偏向 InnoDB 存储引擎;开销大、加锁慢;可能出现死锁;并发度最高,锁冲突概率最低 |
锁的适用场景:
- 表级锁:适合查询为主、仅少量按索引条件更新数据的应用(如 Web 应用)。
- 行级锁:适合大量按索引条件并发更新少量数据,且存在并发查询的应用(如 OLTP 在线事务处理系统)。
二、MyISAM 表锁实操指南
- 自动加锁规则(无需手动干预)
- 执行查询语句(SELECT)前,自动为涉及的表加读锁。
- 执行更新操作(UPDATE、DELETE、INSERT 等)前,自动为涉及的表加写锁。
- 手动加锁语法
-- 为表加读锁
lock table table_name read;-- 为表加写锁
lock table table_name write;
