常规锁设计
分区表通过表锁+分区锁两重设计,在表和分区上分别施加8个不同级别的常规锁,来保证DQL、DML、DDL并发过程中的合理行为控制。下表给出了不同级别锁的相容行为,标记为√的两种常规锁互不阻塞,可以并行。
| - | ACCESS_SHARE | ROW_SHARE | ROW_EXCLUSIVE | SHARE_UPDATE_EXCLUSIVE | SHARE | SHARE_ROW_EXCLUSIVE | EXCLUSIVE | ACCESS_EXCLUSIVE |
|---|---|---|---|---|---|---|---|---|
| ACCESS_SHARE | √ | √ | √ | √ | √ | √ | √ | × |
| ROW_SHARE | √ | √ | √ | √ | √ | √ | × | × |
| ROW_EXCLUSIVE | √ | √ | √ | √ | × | × | × | × |
| SHARE_UPDATE_EXCLUSIVE | √ | √ | √ | × | × | × | × | × |
| SHARE | √ | √ | × | × | √ | × | × | × |
| SHARE_ROW_EXCLUSIVE | √ | √ | × | × | × | × | × | × |
| EXCLUSIVE | √ | × | × | × | × | × | × | × |
| ACCESS_EXCLUSIVE | × | × | × | × | × | × | × | × |
分区表的不同业务最终都是作用于目标分区上,数据库会给分区表和目标分区施加不同级别的表锁+分区锁,来控制并发行为。表2给出了不同业务的锁粒度控制。其中数字1~8分别代表表1给出的ACCESS_SHARE、ROW_SHARE、ROW_EXCLUSIVE、SHARE_UPDATE_EXCLUSIVE、SHARE、SHARE_ROW_EXCLUSIVE、EXCLUSIVE、ACCESS_EXCLUSIVE这8种级别的常规锁。
| 业务模型 | 分区表锁级别(表锁+分区锁) |
|---|---|
| SELECT | 1-1 |
| SELECT FOR UPDATE | 2-2 |
| DML业务,包括INSERT、UPDATE、DELETE、UPSERT、MERGE INTO、COPY | 3-3 |
| 大部分分区DDL,包括ADD、DROP、EXCHANGE、TRUNCATE、MOVE、RENAME | 4-8 |
| CREATE INDEX(非分类索引)、REBUILD INDEX | 5-5 |
| CREATE INDEX(分类索引) | 3-5 |
| REBUILD INDEX PARTITION | 1-5 |
| ANALYZE、VACUUM | 4-4 |
| 其他分区表DDL,包括SPLIT/MERGE这两种分区DDL | 8-8 |
如果业务执行施加的表锁和分区锁均满足表1,则可以支持业务并行操作,如果表锁和分区锁有任一不相容,则二者不支持业务并行。
DDL (ADD/DROP/TRUNCATE/EXCHANGE/MOVE/RENAME) 操作对分区表施加的表锁级别受GUC参数enable_partition_ddl_lowlevel_lock控制,当GUC参数enable_partition_ddl_lowlevel_lock设置为on时,对表施加4级锁;当GUC参数enable_partition_ddl_lowlevel_lock设置为off时,对表施加8级锁。