锁
锁与事务的关系
-
锁是给事务占用的
- 目的就是避免多并发的事务下,出现数据更新查询的冲突问题
- 如果没有显式开启事务,那么一条语句就是一个事务,执行完语句后自动提交
-
一个事务只要没有被提交,它都是一直占有着获取到的锁不放的!!!
- 所以事务不能持续时间太长,也不能同时的并发量太高,更不能对同一行进行多事务下的多并发
表级锁
-
【注意】
- 尽管里面含有ROW字样,但一样是表级锁!!!!
- 两个事务在同一时刻不能在同一个表上持有属于相互冲突模式的锁,但是,一个事务决不会和自身冲突
-
4大分类记忆(共8种类型)
-
极端锁
-
AccessShareLock最软- 纯SELECT,只读取而不修改都会获取这个锁
- 最好相处,只会跟最硬的锁冲突
-
AccessExclusiveLock最硬- 触发命令(大操作)
- DROP
- TRUNCATE
- VACUUM FULL
不能相处,拒绝其他所有操作
- 触发命令(大操作)
-
-
行级的读写锁
- 读锁
RowShareLock- SELECT 搭配 FOR UPDATE 或 FOR SHARE,会获取这个锁
很好相处,只会跟最硬的锁,还有极少出现的EXCLUSIVE冲突
- 写锁
RowExclusiveLock- INSERT/UPDATE/DELETE等变更操作某,会获取这个锁
很好相处,只会跟最硬的锁,还有极少出现的EXCLUSIVE,还有创建索引的SHARE冲突
- 读锁
-
表级(传统)的读写锁
-
ShareLock- 触发命令
- Create index(不带Concurently)
- 不自斥——可同时创建多个索引
很难相处,只允许其他人获取ACCESS SHARE和ROW SHARE
- 触发命令
-
【极少出现】
EXCLUSIVE- REFRESH MAT和VIEW CONCURRENTLY
最难相处,只允许最软的锁
-
-
特殊的排它锁
ShareUpdateExclusiveLock- 触发命令
- VACUUM(不带FULL)
- ANALYZE
- Create index (Concurently)
很难相处,只允许其他人获取ACCESS SHARE和ROW SHARE和ROW EXCLUSIVE
- 触发命令
- 【极少出现】
SHARE ROW EXCLUSIVE- CREATE TRIGGER 创建触发器
很难相处,只允许其他人获取ACCESS SHARE和ROW SHARE
-
行级锁
- 分类
- 软锁
- FOR KEY SHARE最软
- 会阻塞其他事务执行修改KEY键值的DELETE或者UPDATE,但不会阻塞其他UPDATE
- 最好相处,允许各种SHARE和NO KEY UPDATE,在外键检查时会使用此锁
- FOR SHARE
- 会阻塞各种UPDATE和DELETE
- 较好相处,允许各种SHARE
- FOR KEY SHARE最软
- 硬锁
- FOR NO KEY UPDATE
- UPDATE命令时如果没有获取到FOR UPDATE锁的情况下会获取到该锁,对除主键外的的字段进行更新
- 较难相处,只允许FOR KEY SHARE
- FOR UPDATE最硬
- 可以使得SELECT语句获取行级锁,锁定该行,防止该行在本次的操作过程中,被其他的事务获取锁或者进行更改删除操作
- 不能相处,拒绝其他所有操作
- FOR NO KEY UPDATE
- 软锁
关于ShareLock和exclusiveLock
-
含义
ShareLock- 共享锁,又称读锁
- 允许其他人读,但不允许其他人写
exclusiveLock- 排它锁
- 既不允许其他人读,也不允许其他人写
-
例子
- A开启事务a
- 执行select for share
- 获取到表T中行L的读锁
读成功
- 执行select for share
- B紧接着开启事务b
- 也执行select for share
- 也获取到表T中行L的读锁
读成功
- 然后尝试update 行L
- 因为A手上拿了读锁
写失败- 等A把事务a COMMIT,读锁释放,B才
写成功 - 同时,通过update操作,B获取到了行L的排它锁
- 也执行select for share
- A再开启事务c
- 通过select for share
- 因为B手上有排它锁
读失败- 等B把事务b COMMIT,排它锁释放,B才
读成功
- 通过select for share
- A开启事务a
【问题】select......for update会锁表还是锁行?
死锁问题