触发器(⭐⭐)
一.介绍
二. 案例1(insert类型)
例子:
三.案例2(update类型)
四.案例3(delete类型)
总结:
触发器是:表发生增删改时,数据库自动执行一段逻辑。
- 致命问题:逻辑隐形!代码层看不到这个逻辑,你在 Java 更新表,它偷偷在数据库里执行操作。排查 bug 极其痛苦,事务、死锁、数据异常很难定位。
- 适用场景极少:历史数据归档、审计日志(极少数场景)。
- 踩坑例子:更新 A 表,触发器改 B 表,B 表又有触发器改 A 表 → 循环触发,直接炸库。
- 尽量不要写,老项目维护,新项目不新增。
锁(⭐⭐⭐⭐⭐)
一.介绍
二.全局锁
1.介绍![]()
![]()
演示
2.一致性数据备份
创建全局锁后,只读,增删改会被阻塞:
全局锁释放掉后,可以增删改数据:
特点:
mysqldump --single-transaction 原理:
适用引擎:InnoDB,底层依靠MVCC实现,不锁表,业务可以正常读写,拿到一个统一时间点的一致性快照。
核心流程:
- 备份开始时,mysqldump 开启一个事务,隔离级别是
REPEATABLE READ(RR)。 - 执行
START TRANSACTION WITH CONSISTENT SNAPSHOT;这句话的作用:开启事务的瞬间,就创建 Read View 快照。 - 之后所有读表操作,全部基于这一份快照读取数据。
- 别的线程新增、修改数据,不会影响当前备份会话读到的数据(undo log 版本链,多版本)
- 不会加表锁,业务 DML 增删改可以正常执行,不会阻塞业务。
- 遍历所有表,把快照里的数据导出到 sql 文件。
- 事务结束,备份完成。
关键要点:
✅ 优点:无锁备份,不阻塞线上业务,拿到一致性备份
❌ 限制:
- 只支持 InnoDB;MyISAM 引擎没有事务和 MVCC,这个参数无效。
- 备份过程中,不能执行 DDL(alter、drop、truncate),如果备份中途别人改表结构,会破坏快照,直接报错,备份失败。
- 原理是快照读,不是冻结数据库。备份期间业务数据照常写入,只是备份读取旧版本数据。
三.表级锁
介绍:
1.表锁
(1)读锁
读锁不会阻塞其他客户端的读,但会阻塞其他客户端的写:
释放锁后,解除阻塞状态:
(2)写锁
设置锁的客户端又能读又能写,其他客户端读写都会阻塞:
释放锁后,解除阻塞状态:
2.元数据锁
两个客户端开始事务后,执行 select 和 update 语句,系统自动加上了 SHARED_READ 和 SHARED_WRITE 锁,这两个锁是兼容的:
提交事务后,重新启动一个事务,客户端1 执行 select 语句,客户端2 执行 alter table 语句来修改表结构,这时客户端2会阻塞,因为 EXCLUSIVE 锁和其他 MDL 互斥:
此时客户端1 提交事务,客户端2会解除阻塞状态,来修改表结构。
怎么验证是元数据锁起了作用呢?
很明显执行了对应的语句后,系统自动加上了相应的元数据锁:
3.意向锁![]()
加表锁时会根据判断是否兼容意向锁来决定是否创建,兼容则创建表锁,不兼容则阻塞到事务提交
引入意向锁后,创建表锁只要判断是否兼容意向锁 而不用逐行检查行锁情况
测试:
IS:
IX:
四.行级锁
1.介绍
2.行锁
演示![]()
1.
2.
此时客户端2 修改id为3的数据, 阻塞 , 原因是客户端1 根据name修改 但是name没有创建索引 ,行锁升级为表锁,给name创建索引后,就能解决:
3.间隙锁和临键锁![]()
1.id为5的记录不存在 ,优化为间隙锁 ,锁住了3-8这个间隙,此时插入id=7的数据,阻塞
2.给age创建普通索引 ,查询age=3的数据 ,发现age=3这行数据被锁住,3之前的间隙和之后的间隙也被锁住
3.范围查询 id>=19的数据 19这一行数据被行锁锁住 一个临键锁锁住了25这一行,和前面的间隙,另一个临键锁 锁住了正无穷大和其到25之间的间隙
注意事项