├── .DS_Store ├── .history ├── README_20230103120954.md ├── README_20230118165016.md └── docs │ └── mysql │ ├── mysql锁总结_20230118102231.md │ ├── mysql锁总结_20230118102242.md │ ├── mysql锁总结_20230118102336.md │ ├── mysql锁总结_20230118102409.md │ ├── mysql锁总结_20230118102438.md │ ├── mysql锁总结_20230118102509.md │ ├── mysql锁总结_20230118102548.md │ ├── mysql锁总结_20230118102608.md │ ├── mysql锁总结_20230118102704.md │ ├── mysql锁总结_20230118102729.md │ ├── mysql锁总结_20230118102827.md │ ├── mysql锁总结_20230118102859.md │ ├── mysql锁总结_20230118103000.md │ ├── mysql锁总结_20230118103012.md │ ├── mysql锁总结_20230118103040.md │ ├── mysql锁总结_20230118103121.md │ ├── mysql锁总结_20230118103133.md │ ├── mysql锁总结_20230118103152.md │ ├── mysql锁总结_20230118103217.md │ ├── mysql锁总结_20230118103234.md │ ├── mysql锁总结_20230118103329.md │ ├── mysql锁总结_20230118103400.md │ ├── mysql锁总结_20230118103419.md │ ├── mysql锁总结_20230118103500.md │ ├── mysql锁总结_20230118103511.md │ ├── mysql锁总结_20230118103531.md │ ├── mysql锁总结_20230118103626.md │ ├── mysql锁总结_20230118103808.md │ ├── mysql锁总结_20230118103851.md │ ├── mysql锁总结_20230118103905.md │ ├── mysql锁总结_20230118103916.md │ ├── mysql锁总结_20230118103933.md │ ├── mysql锁总结_20230118103954.md │ ├── mysql锁总结_20230118104019.md │ ├── mysql锁总结_20230118104046.md │ ├── mysql锁总结_20230118104141.md │ ├── mysql锁总结_20230118104214.md │ ├── mysql锁总结_20230118104310.md │ ├── mysql锁总结_20230118104327.md │ ├── mysql锁总结_20230118104342.md │ ├── mysql锁总结_20230118104421.md │ ├── mysql锁总结_20230118104511.md │ ├── mysql锁总结_20230118104607.md │ ├── mysql锁总结_20230118104636.md │ ├── mysql锁总结_20230118104642.md │ ├── mysql锁总结_20230118104713.md │ ├── mysql锁总结_20230118104813.md │ ├── mysql锁总结_20230118104844.md │ ├── mysql锁总结_20230118104933.md │ ├── mysql锁总结_20230118104952.md │ ├── mysql锁总结_20230118105034.md │ ├── mysql锁总结_20230118105326.md │ ├── mysql锁总结_20230118105515.md │ ├── mysql锁总结_20230118105523.md │ ├── mysql锁总结_20230118105548.md │ ├── mysql锁总结_20230118105652.md │ ├── mysql锁总结_20230118105714.md │ ├── mysql锁总结_20230118105742.md │ ├── mysql锁总结_20230118105830.md │ ├── mysql锁总结_20230118105913.md │ ├── mysql锁总结_20230118110001.md │ ├── mysql锁总结_20230118110257.md │ ├── mysql锁总结_20230118110315.md │ ├── mysql锁总结_20230118110328.md │ ├── mysql锁总结_20230118110406.md │ ├── mysql锁总结_20230118110426.md │ ├── mysql锁总结_20230118110639.md │ ├── mysql锁总结_20230118110732.md │ ├── mysql锁总结_20230118110806.md │ ├── mysql锁总结_20230118110856.md │ ├── mysql锁总结_20230118110928.md │ ├── mysql锁总结_20230118110941.md │ ├── mysql锁总结_20230118111042.md │ ├── mysql锁总结_20230118111114.md │ ├── mysql锁总结_20230118111251.md │ ├── mysql锁总结_20230118111319.md │ ├── mysql锁总结_20230118111537.md │ ├── mysql锁总结_20230118111925.md │ ├── mysql锁总结_20230118111938.md │ ├── mysql锁总结_20230118112119.md │ ├── mysql锁总结_20230118113018.md │ ├── mysql锁总结_20230118113037.md │ ├── mysql锁总结_20230118113156.md │ ├── mysql锁总结_20230118113327.md │ ├── mysql锁总结_20230118113918.md │ ├── mysql锁总结_20230118114129.md │ ├── mysql锁总结_20230118120732.md │ ├── mysql锁总结_20230118120841.md │ ├── mysql锁总结_20230118120934.md │ ├── mysql锁总结_20230118121017.md │ ├── mysql锁总结_20230118121325.md │ ├── mysql锁总结_20230118121554.md │ ├── mysql锁总结_20230118121841.md │ ├── mysql锁总结_20230118122111.md │ ├── mysql锁总结_20230118122317.md │ ├── mysql锁总结_20230118122453.md │ ├── mysql锁总结_20230118122521.md │ ├── mysql锁总结_20230118122603.md │ ├── mysql锁总结_20230118122655.md │ ├── mysql锁总结_20230118122741.md │ ├── mysql锁总结_20230118122840.md │ ├── mysql锁总结_20230118123008.md │ ├── mysql锁总结_20230118123055.md │ ├── mysql锁总结_20230118123249.md │ ├── mysql锁总结_20230118124504.md │ ├── mysql锁总结_20230118125341.md │ ├── mysql锁总结_20230118125350.md │ ├── mysql锁总结_20230118125404.md │ ├── mysql锁总结_20230118125421.md │ ├── mysql锁总结_20230118125443.md │ ├── mysql锁总结_20230118125505.md │ ├── mysql锁总结_20230118125554.md │ ├── mysql锁总结_20230118125704.md │ ├── mysql锁总结_20230118125728.md │ ├── mysql锁总结_20230118130021.md │ ├── mysql锁总结_20230118130104.md │ ├── mysql锁总结_20230118130154.md │ ├── mysql锁总结_20230118130210.md │ ├── mysql锁总结_20230118130226.md │ ├── mysql锁总结_20230118130403.md │ ├── mysql锁总结_20230118130520.md │ ├── mysql锁总结_20230118130553.md │ ├── mysql锁总结_20230118130705.md │ ├── mysql锁总结_20230118130711.md │ ├── mysql锁总结_20230118130801.md │ ├── mysql锁总结_20230118130841.md │ ├── mysql锁总结_20230118130901.md │ ├── mysql锁总结_20230118130929.md │ ├── mysql锁总结_20230118130953.md │ ├── mysql锁总结_20230118131048.md │ ├── mysql锁总结_20230118141025.md │ ├── mysql锁总结_20230118141230.md │ ├── mysql锁总结_20230118141303.md │ ├── mysql锁总结_20230118141351.md │ ├── mysql锁总结_20230118141422.md │ ├── mysql锁总结_20230118141540.md │ ├── mysql锁总结_20230118141631.md │ ├── mysql锁总结_20230118141714.md │ ├── mysql锁总结_20230118141732.md │ ├── mysql锁总结_20230118141839.md │ ├── mysql锁总结_20230118141851.md │ ├── mysql锁总结_20230118141859.md │ ├── mysql锁总结_20230118141922.md │ ├── mysql锁总结_20230118142013.md │ ├── mysql锁总结_20230118142046.md │ ├── mysql锁总结_20230118142308.md │ ├── mysql锁总结_20230118142325.md │ ├── mysql锁总结_20230118142858.md │ ├── mysql锁总结_20230118142906.md │ ├── mysql锁总结_20230118142919.md │ ├── mysql锁总结_20230118142930.md │ ├── mysql锁总结_20230118143142.md │ ├── mysql锁总结_20230118143218.md │ ├── mysql锁总结_20230118143349.md │ ├── mysql锁总结_20230118143747.md │ ├── mysql锁总结_20230118144037.md │ ├── mysql锁总结_20230118144052.md │ ├── mysql锁总结_20230118144118.md │ ├── mysql锁总结_20230118144158.md │ ├── mysql锁总结_20230118144236.md │ ├── mysql锁总结_20230118144333.md │ ├── mysql锁总结_20230118144418.md │ ├── mysql锁总结_20230118144433.md │ ├── mysql锁总结_20230118161532.md │ ├── mysql锁总结_20230118164930.md │ └── mysql锁总结_20230118165024.md ├── README.md ├── assets ├── align1.png ├── align2.png ├── chan1.png ├── chan2.png ├── chan3.png ├── channel1.png ├── channel2.png ├── channel3.png ├── channel4.png ├── context1.png ├── context2.png ├── gc1.png ├── gc2.png ├── gc3.png ├── gc4.png ├── gc5.png ├── gc6.png ├── gc7.png ├── gc8.png ├── gc9.png ├── gmm1.png ├── gmm2.png ├── go.png ├── if1.png ├── if2.png ├── logo.jpg ├── rw1.jpg ├── sched1.png ├── sched2.png ├── server1.png ├── server10.png ├── server11.png ├── server12.png ├── server13.png ├── server14.png ├── server15.png ├── server16.png ├── server2.png ├── server3.png ├── server4.png ├── server5.png ├── server6.png ├── server7.png ├── server8.png ├── server9.png ├── tcc.png ├── wg1.png └── wg1.svg └── docs ├── Go语言HappensBefore原则.md ├── Go语言上下文Context.md ├── Go语言中的nil.md ├── Go语言中的类型内嵌.md ├── Go语言内存对齐.md ├── Go语言垃圾收集器.md ├── Go语言并发同步原语和锁.md ├── Go语言通道Channel.md ├── Go面试Channel.md ├── Go面试结构体.md ├── etcd └── 分布式一致性协议.md ├── golang ├── golang内存管理.md ├── golang汇编代码阅读手册.md ├── golang调度器之GMP组成.md ├── golang面试之map.md ├── golang面试题汇总.md ├── runtime包解读之golang程序启动流程.md ├── runtime包解读之mgc.md ├── runtime包解读之proc.md ├── runtime包解读之调度器入口mainPC.md ├── runtime包解读之调度器初始化scheinit.md ├── 如何优雅地关闭channel.md ├── 探究Go语言中的Interface.md └── 探究golang的GC过程.md ├── grpc之Server启动.md ├── grpc之passthrough解析器.md ├── grpc之拦截器.md ├── mysql ├── mysql索引汇总.md ├── mysql进阶面试题.md ├── mysql锁总结.md └── mysql面试题.md ├── redis ├── Redis操作手册速查.md ├── redis压缩列表.md └── redis面试题汇总.md ├── slice源码解读.md ├── sync包之map.md ├── sync包之mutex.md ├── sync包之once.md ├── sync包之waitGroup.md ├── unsafe.Pointer非安全类型指针.md └── 分布式事务.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/.DS_Store -------------------------------------------------------------------------------- /.history/README_20230103120954.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | ------ 4 | 5 | ## Go基础 6 | 7 | * [空类型nil](/docs/Go语言中的nil.md) 8 | * [类型内嵌](/docs/Go语言中的类型内嵌.md) 9 | * [内存对齐](docs/Go语言内存对齐.md) 10 | * [通道channel](/docs/Go面试Channel.md) 11 | * [结构体struct](/docs/Go面试结构体.md) 12 | * [字典map](/docs/golang/golang面试之map.md) 13 | * [切片slice](docs/slice源码解读.md) 14 | * [非安全类型unsafe](/docs/unsafe.Pointer非安全类型指针.md) 15 | * [接口interface](/docs/golang/探究Go语言中的Interface.md) 16 | 17 | ## Go内存管理 18 | 19 | * **GC垃圾收集** 20 | * [happens-before原则](/docs/Go语言HappensBefore原则.md) 21 | * [初步认识垃圾收集](/docs/Go语言垃圾收集器.md) 22 | * [On-The-Fly算法](https://lamport.azurewebsites.net/pubs/garbage.pdf) 23 | * [不使用STW进行垃圾收集复制](https://people.cs.umass.edu/~moss/papers/oopsla-2003-mark-copy.pdf) 24 | * [runtime包源码解读——mgc(1)(待完成)](/docs/golang/runtime包解读之mgc.md) 25 | * [runtime包源码解读——mbarrier(待完成.)]() 26 | 27 | ## Go调度器 28 | 29 | * [runtime包源码解读——golang程序的启动流程](/docs/golang/runtime包解读之golang程序启动流程.md) 30 | * [runtime包源码解读——调度器的初始化schedinit](/docs/golang/runtime包解读之调度器初始化scheinit.md) 31 | * [runtime包源码解读——调度器的入口mainPC](/docs/golang/runtime包解读之调度器入口mainPC.md) 32 | * [runtime包源码解读——proc调度器模型](/docs/golang/runtime包解读之proc.md) 33 | 34 | ## Go并发编程 35 | 36 | * [并发编程之同步原语和锁机制](docs/Go语言并发同步原语和锁.md) 37 | * [并发编程之上下文context](/docs/Go语言上下文Context.md) 38 | * [并发编程之通道chan](/docs/Go语言通道Channel.md) 39 | * [并发编程之sync.Mutex](/docs/sync包之mutex.md) 40 | * [并发编程之sync.Map](/docs/sync包之map.md) 41 | * [并发编程之sync.WaitGroup](/docs/sync包之waitGroup.md) 42 | * [并发编程之sync.Once](/docs/sync包之once.md) 43 | 44 | ## Go微服务 45 | 46 | * [grpc之Interceptor拦截器](/docs/grpc之拦截器.md) 47 | * [grpc之Server启动流程](/docs/grpc之Server启动.md) 48 | 49 | ## 场景 50 | 51 | * [如何优雅关闭channel](/docs/golang/如何优雅地关闭channel.md) 52 | 53 | ## 数据库 54 | 55 | * **Redis** 56 | * [Redis命令手册速记](/docs/redis/Redis操作手册速查.md) 57 | * [Redis面试题汇总](/docs/redis/redis面试题汇总.md) 58 | 59 | ## 分布式 60 | 61 | * [分布式一致性协议](/docs/etcd/分布式一致性协议.md) 62 | * [分布式事务](/docs/分布式事务.md) -------------------------------------------------------------------------------- /.history/README_20230118165016.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | ------ 4 | 5 | ## Go基础 6 | 7 | * [空类型nil](/docs/Go语言中的nil.md) 8 | * [类型内嵌](/docs/Go语言中的类型内嵌.md) 9 | * [内存对齐](docs/Go语言内存对齐.md) 10 | * [通道channel](/docs/Go面试Channel.md) 11 | * [结构体struct](/docs/Go面试结构体.md) 12 | * [字典map](/docs/golang/golang面试之map.md) 13 | * [切片slice](docs/slice源码解读.md) 14 | * [非安全类型unsafe](/docs/unsafe.Pointer非安全类型指针.md) 15 | * [接口interface](/docs/golang/探究Go语言中的Interface.md) 16 | 17 | ## Go内存管理 18 | 19 | * **GC垃圾收集** 20 | * [happens-before原则](/docs/Go语言HappensBefore原则.md) 21 | * [初步认识垃圾收集](/docs/Go语言垃圾收集器.md) 22 | * [On-The-Fly算法](https://lamport.azurewebsites.net/pubs/garbage.pdf) 23 | * [不使用STW进行垃圾收集复制](https://people.cs.umass.edu/~moss/papers/oopsla-2003-mark-copy.pdf) 24 | * [runtime包源码解读——mgc(1)(待完成)](/docs/golang/runtime包解读之mgc.md) 25 | * [runtime包源码解读——mbarrier(待完成.)]() 26 | 27 | ## Go调度器 28 | 29 | * [runtime包源码解读——golang程序的启动流程](/docs/golang/runtime包解读之golang程序启动流程.md) 30 | * [runtime包源码解读——调度器的初始化schedinit](/docs/golang/runtime包解读之调度器初始化scheinit.md) 31 | * [runtime包源码解读——调度器的入口mainPC](/docs/golang/runtime包解读之调度器入口mainPC.md) 32 | * [runtime包源码解读——proc调度器模型](/docs/golang/runtime包解读之proc.md) 33 | 34 | ## Go并发编程 35 | 36 | * [并发编程之同步原语和锁机制](docs/Go语言并发同步原语和锁.md) 37 | * [并发编程之上下文context](/docs/Go语言上下文Context.md) 38 | * [并发编程之通道chan](/docs/Go语言通道Channel.md) 39 | * [并发编程之sync.Mutex](/docs/sync包之mutex.md) 40 | * [并发编程之sync.Map](/docs/sync包之map.md) 41 | * [并发编程之sync.WaitGroup](/docs/sync包之waitGroup.md) 42 | * [并发编程之sync.Once](/docs/sync包之once.md) 43 | 44 | ## Go微服务 45 | 46 | * [grpc之Interceptor拦截器](/docs/grpc之拦截器.md) 47 | * [grpc之Server启动流程](/docs/grpc之Server启动.md) 48 | 49 | ## 场景 50 | 51 | * [如何优雅关闭channel](/docs/golang/如何优雅地关闭channel.md) 52 | 53 | ## 数据库 54 | 55 | * **Redis** 56 | * [Redis命令手册速记](/docs/redis/Redis操作手册速查.md) 57 | * [Redis面试题汇总](/docs/redis/redis面试题汇总.md) 58 | * **MySQL** 59 | * [MySQL加锁场景总结](/docs/mysql/mysql%E9%94%81%E6%80%BB%E7%BB%93.md) 60 | 61 | ## 分布式 62 | 63 | * [分布式一致性协议](/docs/etcd/分布式一致性协议.md) 64 | * [分布式事务](/docs/分布式事务.md) -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102231.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/.history/docs/mysql/mysql锁总结_20230118102231.md -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102242.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102336.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## RC(Read-Commited)隔离级别解析 4 | 5 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102409.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## RC(Read-Commited)隔离级别解析 4 | 5 | * 查询条件为等值查询 6 | * -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102438.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## RC(Read-Commited)隔离级别 4 | 5 | | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102509.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## RC(Read-Commited)隔离级别 4 | 5 | * 查询条件为等值查询: 6 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102548.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## RC(Read-Commited)隔离级别 4 | 5 | * 查询条件为等值查询: 6 | 7 | |SQL模版|SQL示例|加锁情况| 8 | |:---:|:---:|:---:| 9 | | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102608.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## RC(Read-Commited)隔离级别 4 | 5 | * 查询条件为等值查询: 6 | 7 | |SQL模版|SQL示例|加锁情况| 8 | |:---:|:---:|:---:| 9 | |`select * from ... -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102704.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 4 | 5 | * 查询条件为等值查询: 6 | 7 | |SQL模版|SQL示例|加锁情况| 8 | |:---:|:---:|:---:| 9 | |`select * from ... where pk = ... for update`|`select -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102729.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 表情况 6 | 7 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 8 | 9 | * 查询条件为等值查询: 10 | 11 | |SQL模版|SQL示例|加锁情况| 12 | |:---:|:---:|:---:| 13 | |`select * from ... where pk = ... for update`|`select -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102827.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | | 8 | 9 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 10 | 11 | * 查询条件为等值查询: 12 | 13 | |SQL模版|SQL示例|加锁情况| 14 | |:---:|:---:|:---:| 15 | |`select * from ... where pk = ... for update`|`select -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118102859.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | 10 | 11 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 12 | 13 | * 查询条件为等值查询: 14 | 15 | |SQL模版|SQL示例|加锁情况| 16 | |:---:|:---:|:---:| 17 | |`select * from ... where pk = ... for update`|`select -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103000.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况| 21 | |:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103012.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况| 21 | |:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select * from t where -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103040.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况| 21 | |:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 20 for update`| -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103121.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况| 21 | |:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在 -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103133.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况| 21 | |:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁 -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103152.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况| 21 | |:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即lock_x -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103217.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况| 21 | |:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`| 23 | | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103234.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况| 21 | |:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`| 23 | |`select * from ... where pk -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103329.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|记录存在| 23 | |`select * from ... where pk = ... for update`|`select -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103400.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|记录存在| 23 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下, -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103419.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|记录存在| 23 | |`select * from ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103500.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103511.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`| -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103531.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`| -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103626.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103808.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103851.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103905.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103916.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`| -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103933.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c2=20记录上加X锁,即`LOCK_X -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118103954.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c2=20记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在| 26 | | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104019.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c2=20记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104046.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)| 8 | |:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c2=20记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在 -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104141.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20 -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104214.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要 -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104310.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104327.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ... -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104342.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`| -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104421.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104511.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | |SQL模版|SQL示例|加锁情况|说明| 32 | |:---:|:---:|:---:|:---:| 33 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104607.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | 36 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104636.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk = ...`| 36 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104642.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`| 36 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104713.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`|`select * from t where c1 >= 10`|会对`<10, 20, 30, 40>` 36 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104813.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | | 37 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104844.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ...`|`select * from t where c1 <= 20 37 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104933.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ...`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续 37 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118104952.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ...`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | 38 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118105034.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ...`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set 38 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118105326.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ...`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118105515.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ...`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引 42 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118105523.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ...`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | 44 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118105548.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ...`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ...`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ...`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ...`| 46 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118105652.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`| 46 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118105714.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update` 46 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118105742.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上加 46 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118105830.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键 46 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118105913.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`| 47 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110001.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select 48 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110257.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where 48 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110315.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where 48 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110328.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`| 48 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110406.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | 49 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110426.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`| 49 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110639.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁, 49 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110732.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update 50 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110806.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,主键记录, 50 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110856.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | 51 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110928.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`| 51 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118110941.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引 51 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118111042.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118111114.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118111251.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高, -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118111319.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,因此会对c1=`<>` -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118111537.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118111925.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... w -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118111938.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index() -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118112119.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118113018.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对c2=`<11, 21, 31>`全部加X锁,但是不会释放掉c2 -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118113037.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对c1=`<10, 20, 30>`全部加X锁,但是不会释放掉c2 -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118113156.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`和对应的主键行全部加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118113327.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`和对应的主键行全部加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118113918.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21>`和对应的主键行全部加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118114129.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`加X锁,并且对c1=`<10, 20>`加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118120732.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`加X锁,并且对c1=`<10, 20>`加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | |`select ... force index(...) where uk <= ... for update`| 60 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118120841.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`加X锁,并且对c1=`<10, 20>`加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | |`select ... force index(...) where uk <= ... for update`|`select * from t force index(i_c2) where c2 <= 21 for update`|依然不同于`>=`,会将c2 60 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118120934.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`加X锁,并且对c1=`<10, 20>`加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | |`select ... force index(...) where uk <= ... for update`|`select * from t force index(i_c2) where c2 <= 21 for update`|依然不同于`>=`,会将c2=`<11, 21, 31>`加X锁,对c1=`<10, 20>`主键记录加X锁|唯一索引范围查询,记录存在| 60 | 61 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118121017.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`加X锁,并且对c1=`<10, 20>`加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | |`select ... force index(...) where uk <= ... for update`|`select * from t force index(i_c2) where c2 <= 21 for update`|依然不同于`>=`,会将c2=`<11, 21, 31>`加X锁,对c1=`<10, 20>`主键记录加X锁|唯一索引范围查询,记录存在| 60 | |`update ... where uk >= ...`|`update t set 61 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118121325.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`加X锁,并且对c1=`<10, 20>`加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | |`select ... force index(...) where uk <= ... for update`|`select * from t force index(i_c2) where c2 <= 21 for update`|依然不同于`>=`,会将c2=`<11, 21, 31>`加X锁,对c1=`<10, 20>`主键记录加X锁|唯一索引范围查询,记录存在| 60 | |`update ... where uk >= ...`|`update t set c4 = 100 where c2 >= 21`|对c2=`<21, 31, 41>`和c1=`<20, 30, 40>`全部加X锁|唯一索引范围查询并更新,记录存在,且不更新索引列| 61 | |`update ... where uk <= ...`|`update t set c4 = 100 where c2 <= 21`|对c2=`<11, 21, 31>`和c1=`<10, 20, 30>`全部加X锁,然后**随机释放c1=30或c2=31的X锁**|唯一索引范围查询并更新,不更新索引列| 62 | 63 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118121554.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`加X锁,并且对c1=`<10, 20>`加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | |`select ... force index(...) where uk <= ... for update`|`select * from t force index(i_c2) where c2 <= 21 for update`|依然不同于`>=`,会将c2=`<11, 21, 31>`加X锁,对c1=`<10, 20>`主键记录加X锁|唯一索引范围查询,记录存在| 60 | |`update ... where uk >= ...`|`update t set c4 = 100 where c2 >= 21`|对c2=`<21, 31, 41>`和c1=`<20, 30, 40>`全部加X锁|唯一索引范围查询并更新,记录存在,且不更新索引列| 61 | |`update ... where uk <= ...`|`update t set c4 = 100 where c2 <= 21`|对c2=`<11, 21, 31>`和c1=`<10, 20, 30>`全部加X锁,并且不会释放|唯一索引范围查询并更新,不更新索引列| 62 | 63 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118121841.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`加X锁,并且对c1=`<10, 20>`加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | |`select ... force index(...) where uk <= ... for update`|`select * from t force index(i_c2) where c2 <= 21 for update`|依然不同于`>=`,会将c2=`<11, 21, 31>`加X锁,对c1=`<10, 20>`主键记录加X锁|唯一索引范围查询,记录存在| 60 | |`update ... where uk >= ...`|`update t set c4 = 100 where c2 >= 21`|对c2=`<21, 31, 41>`和c1=`<20, 30, 40>`全部加X锁|唯一索引范围查询并更新,记录存在,且不更新索引列| 61 | |`update ... where uk <= ...`|`update t set c4 = 100 where c2 <= 21`|对c2=`<11, 21, 31>`和c1=`<10, 20, 30>`全部加X锁,并且不会释放|唯一索引范围查询并更新,不更新索引列| 62 | |`update ... force index(...) 63 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118122111.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`加X锁,并且对c1=`<10, 20>`加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | |`select ... force index(...) where uk <= ... for update`|`select * from t force index(i_c2) where c2 <= 21 for update`|依然不同于`>=`,会将c2=`<11, 21, 31>`加X锁,对c1=`<10, 20>`主键记录加X锁|唯一索引范围查询,记录存在| 60 | |`update ... where uk >= ...`|`update t set c4 = 100 where c2 >= 21`|对c2=`<21, 31, 41>`和c1=`<20, 30, 40>`全部加X锁,并且不会释放|唯一索引范围查询并更新,记录存在,且不更新索引列| 61 | |`update ... where uk <= ...`|`update t set c4 = 100 where c2 <= 21`|对c2=`<11, 21, 31>`和c1=`<10, 20, 30>`全部加X锁,并且不会释放|唯一索引范围查询并更新,不更新索引列| 62 | |`update ... force index(...) set ... where uk >= ...`|`update t force index(i_c2) set c4 = 100 where c2 >= 21`|对c2=`<21, 31, 41>`和c1=`<20, 30, 40>`主键记录全部加X锁|唯一索引范围查询并更新,且更新字段不属于索引字段| 63 | |`update ... force index(...) set ... where uk <= ...`|`update t force index(i_c2) set c4 = 100 where c2 <= 21`|同上|同上| 64 | 65 | -------------------------------------------------------------------------------- /.history/docs/mysql/mysql锁总结_20230118122317.md: -------------------------------------------------------------------------------- 1 | # MySQL锁总结 2 | 3 | ## 前言 4 | 5 | 加锁情况样例表格: 6 | 7 | |c1(pk)|c2(uk)|c3(index)|c4| 8 | |:---:|:---:|:---:|:---:| 9 | |10|11|12|13| 10 | |20|21|22|23| 11 | |30|31|32|33| 12 | |40|41|42|43| 13 | 14 | 其中,c1为主键,c2为唯一索引,c3为普通索引,c4为普通列。 15 | 16 | ## RC(Read-Commited)和RU(Read-UnCommited)隔离级别 17 | 18 | * 查询条件为主键等值查询: 19 | 20 | |SQL模版|SQL示例|加锁情况|说明| 21 | |:---:|:---:|:---:|:---:| 22 | |`select ... where pk = ... for update`|`select * from t where c1 = 20 for update`|在c1=20的主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 23 | |`select ... where pk = ... for update`|`select * from t where c1 = 15 for update`|不加锁|在RC和RU级别下,主键等值查询不匹配,不进行加锁| 24 | |`select ... where pk = ... lock in share mode`|`select * from t where c1 = 20 lock in share mode`|在c1=20的主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|主键等值查询记录存在| 25 | |`update ... where pk = ...`|`update t set c4 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键等值查询并更新,记录存在,且未更新索引列| 26 | |`update ... where pk = ...`|`update t set c2 = 12 where c1 = 20`|在c1=20主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,还需要在c2索引上加同样的锁(同理c3)|主键等值查询并更新,记录存在,且更新索引列| 27 | |`delete from ...`|`delete from t where c1 = 20`|对主键,各个索引记录都加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|删除表| 28 | 29 | * 查询条件为主键范围查询: 30 | 31 | **查询条件为范围查询时,需要对匹配的行依次加上等值查询时需要加的锁** 32 | 33 | |SQL模版|SQL示例|加锁情况|说明| 34 | |:---:|:---:|:---:|:---:| 35 | |`select ... where pk >= ... for update`|`select * from t where c1 >= 10 for update`|会对c1=`<10, 20, 30, 40>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询,记录存在| 36 | |`select ... where pk <= ... for update`|`select * from t where c1 <= 20 for update`|初始时刻,会对c1=`<10, 20, 30>`加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询,记录存在| 37 | |`update ... where pk >= ...`|`update t set c2 = c2 + 1 where c1 >= 10`|对c1=`<10, 20, 30, 40>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|主键范围查询并更新,记录存在| 38 | |`update ... where pk <= ...`|`update t set c2 = c2 + 1 where c1 <= 20`|对c1=`<10, 20, 30>`主键记录和c2索引列加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,后续释放c1=30的锁|主键范围查询并更新,记录存在| 39 | 40 | 41 | * 查询条件为唯一索引等值查询: 42 | 43 | |SQL模版|SQL示例|加锁情况|说明| 44 | |:---:|:---:|:---:|:---:| 45 | |`select ... where uk = ... for update`|`select * from t where c2 = 21 for update`|在c2=21唯一索引记录上和主键记录上加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 46 | |`select ... where uk = ... for update`|`select * from t where c2 = 20 for update`|不加锁|唯一索引查询条件对应的记录不存在,不会加锁| 47 | |`select ... where uk = ... lock in share mode`|`select * from t where c2 = 21 lock in share mode`|在c2=21唯一索引记录和主键记录上加S锁,即`LOCK_S|LOCK_REC_NOT_GAP`|唯一索引等值查询,记录存在| 48 | |`update ... where uk = ...`|`update t set c4 = 100 where c2 = 21`|对c2=21唯一索引记录和主键记录加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`,其余索引不加锁|唯一索引等值查询并更新,但不更新索引列| 49 | |`update ... where uk = ...`|`update t set c3 = 100 where c2 = 21`|对c2=21唯一索引记录,c1主键记录,c3索引记录全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并更新,更新列包含索引列| 50 | |`delete ... where uk = ...`|`delete from t where c2 = 21`|对c2=21唯一索引记录加X锁,根据唯一索引找到主键,将主键和其余索引全部加上X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引等值查询并删除| 51 | 52 | * 查询条件为唯一索引范围查询: 53 | 54 | |SQL模版|SQL示例|加锁情况|说明| 55 | |:---:|:---:|:---:|:---:| 56 | |`select ... where uk >= ... for update`|`select * from t where c2 >= 21 for update`|不会对唯一索引进行加锁,优化器会判断此时对主键索引加锁性能更高,但初始时刻会对全部主键记录加上X锁,即在c1=`<10, 20, 30, 40>`加上`LOCK_X|LOCK_REC_NOT_GAP` ,后续会释放掉c1=10的锁,因此最终加锁情况是c1=`<20, 30, 40>`|唯一索引范围查询,记录存在| 57 | |`select ... force index(...) where uk >= ... for update`|`select * from t force index(idx_c2) where c2 >= 21 for update`|不会初始时刻全部加锁,然后释放,而是依次对满足条件的记录唯一索引记录和主键记录依次加X锁,即`LOCK_X|LOCK_REC_NOT_GAP`|唯一索引范围查询,记录存在| 58 | |`select ... where uk <= ... for update`|`select * from t where c2 <= 21 for update`|这里`<=`和`>=`情况不一样,此时会对**c2=`<11, 21, 31>`加X锁,并且对c1=`<10, 20>`加X锁,但是不会释放掉c2=31对应的锁** ,原因是索引下推|唯一索引范围查询,记录存在| 59 | |`select ... force index(...) where uk <= ... for update`|`select * from t force index(i_c2) where c2 <= 21 for update`|依然不同于`>=`,会将c2=`<11, 21, 31>`加X锁,对c1=`<10, 20>`主键记录加X锁|唯一索引范围查询,记录存在| 60 | |`update ... where uk >= ...`|`update t set c4 = 100 where c2 >= 21`|对c2=`<21, 31, 41>`和c1=`<20, 30, 40>`全部加X锁,并且不会释放|唯一索引范围查询并更新,记录存在,且不更新索引列| 61 | |`update ... where uk <= ...`|`update t set c4 = 100 where c2 <= 21`|对c2=`<11, 21, 31>`和c1=`<10, 20, 30>`全部加X锁,并且不会释放|唯一索引范围查询并更新,不更新索引列| 62 | |`update ... force index(...) set ... where uk >= ...`|`update t force index(i_c2) set c4 = 100 where c2 >= 21`|对c2=`<21, 31, 41>`和c1=`<20, 30, 40>`主键记录全部加X锁|唯一索引范围查询并更新,且更新字段不属于索引字段| 63 | |`update ... force index(...) set ... where uk <= ...`|`update t force index(i_c2) set c4 = 100 where c2 <= 21`|同上|同上| 64 | |`update ... where 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | ------ 4 | 5 | ## Go基础 6 | 7 | * [空类型nil](/docs/Go语言中的nil.md) 8 | * [类型内嵌](/docs/Go语言中的类型内嵌.md) 9 | * [内存对齐](docs/Go语言内存对齐.md) 10 | * [通道channel](/docs/Go面试Channel.md) 11 | * [结构体struct](/docs/Go面试结构体.md) 12 | * [字典map](/docs/golang/golang面试之map.md) 13 | * [切片slice](docs/slice源码解读.md) 14 | * [非安全类型unsafe](/docs/unsafe.Pointer非安全类型指针.md) 15 | * [接口interface](/docs/golang/探究Go语言中的Interface.md) 16 | 17 | ## Go内存管理 18 | 19 | * **GC垃圾收集** 20 | * [happens-before原则](/docs/Go语言HappensBefore原则.md) 21 | * [初步认识垃圾收集](/docs/Go语言垃圾收集器.md) 22 | * [On-The-Fly算法](https://lamport.azurewebsites.net/pubs/garbage.pdf) 23 | * [不使用STW进行垃圾收集复制](https://people.cs.umass.edu/~moss/papers/oopsla-2003-mark-copy.pdf) 24 | * [runtime包源码解读——mgc(1)(待完成)](/docs/golang/runtime包解读之mgc.md) 25 | * [runtime包源码解读——mbarrier(待完成.)]() 26 | 27 | ## Go调度器 28 | 29 | * [runtime包源码解读——golang程序的启动流程](/docs/golang/runtime包解读之golang程序启动流程.md) 30 | * [runtime包源码解读——调度器的初始化schedinit](/docs/golang/runtime包解读之调度器初始化scheinit.md) 31 | * [runtime包源码解读——调度器的入口mainPC](/docs/golang/runtime包解读之调度器入口mainPC.md) 32 | * [runtime包源码解读——proc调度器模型](/docs/golang/runtime包解读之proc.md) 33 | 34 | ## Go并发编程 35 | 36 | * [并发编程之同步原语和锁机制](docs/Go语言并发同步原语和锁.md) 37 | * [并发编程之上下文context](/docs/Go语言上下文Context.md) 38 | * [并发编程之通道chan](/docs/Go语言通道Channel.md) 39 | * [并发编程之sync.Mutex](/docs/sync包之mutex.md) 40 | * [并发编程之sync.Map](/docs/sync包之map.md) 41 | * [并发编程之sync.WaitGroup](/docs/sync包之waitGroup.md) 42 | * [并发编程之sync.Once](/docs/sync包之once.md) 43 | 44 | ## Go微服务 45 | 46 | * [grpc之Interceptor拦截器](/docs/grpc之拦截器.md) 47 | * [grpc之Server启动流程](/docs/grpc之Server启动.md) 48 | 49 | ## 场景 50 | 51 | * [如何优雅关闭channel](/docs/golang/如何优雅地关闭channel.md) 52 | 53 | ## 数据库 54 | 55 | * **Redis** 56 | * [Redis命令手册速记](/docs/redis/Redis操作手册速查.md) 57 | * [Redis面试题汇总](/docs/redis/redis面试题汇总.md) 58 | * **MySQL** 59 | * [MySQL加锁场景总结](/docs/mysql/mysql%E9%94%81%E6%80%BB%E7%BB%93.md) 60 | 61 | ## 分布式 62 | 63 | * [分布式一致性协议](/docs/etcd/分布式一致性协议.md) 64 | * [分布式事务](/docs/分布式事务.md) -------------------------------------------------------------------------------- /assets/align1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/align1.png -------------------------------------------------------------------------------- /assets/align2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/align2.png -------------------------------------------------------------------------------- /assets/chan1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/chan1.png -------------------------------------------------------------------------------- /assets/chan2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/chan2.png -------------------------------------------------------------------------------- /assets/chan3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/chan3.png -------------------------------------------------------------------------------- /assets/channel1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/channel1.png -------------------------------------------------------------------------------- /assets/channel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/channel2.png -------------------------------------------------------------------------------- /assets/channel3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/channel3.png -------------------------------------------------------------------------------- /assets/channel4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/channel4.png -------------------------------------------------------------------------------- /assets/context1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/context1.png -------------------------------------------------------------------------------- /assets/context2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/context2.png -------------------------------------------------------------------------------- /assets/gc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gc1.png -------------------------------------------------------------------------------- /assets/gc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gc2.png -------------------------------------------------------------------------------- /assets/gc3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gc3.png -------------------------------------------------------------------------------- /assets/gc4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gc4.png -------------------------------------------------------------------------------- /assets/gc5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gc5.png -------------------------------------------------------------------------------- /assets/gc6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gc6.png -------------------------------------------------------------------------------- /assets/gc7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gc7.png -------------------------------------------------------------------------------- /assets/gc8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gc8.png -------------------------------------------------------------------------------- /assets/gc9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gc9.png -------------------------------------------------------------------------------- /assets/gmm1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gmm1.png -------------------------------------------------------------------------------- /assets/gmm2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/gmm2.png -------------------------------------------------------------------------------- /assets/go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/go.png -------------------------------------------------------------------------------- /assets/if1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/if1.png -------------------------------------------------------------------------------- /assets/if2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/if2.png -------------------------------------------------------------------------------- /assets/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/logo.jpg -------------------------------------------------------------------------------- /assets/rw1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/rw1.jpg -------------------------------------------------------------------------------- /assets/sched1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/sched1.png -------------------------------------------------------------------------------- /assets/sched2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/sched2.png -------------------------------------------------------------------------------- /assets/server1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server1.png -------------------------------------------------------------------------------- /assets/server10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server10.png -------------------------------------------------------------------------------- /assets/server11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server11.png -------------------------------------------------------------------------------- /assets/server12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server12.png -------------------------------------------------------------------------------- /assets/server13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server13.png -------------------------------------------------------------------------------- /assets/server14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server14.png -------------------------------------------------------------------------------- /assets/server15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server15.png -------------------------------------------------------------------------------- /assets/server16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server16.png -------------------------------------------------------------------------------- /assets/server2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server2.png -------------------------------------------------------------------------------- /assets/server3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server3.png -------------------------------------------------------------------------------- /assets/server4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server4.png -------------------------------------------------------------------------------- /assets/server5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server5.png -------------------------------------------------------------------------------- /assets/server6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server6.png -------------------------------------------------------------------------------- /assets/server7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server7.png -------------------------------------------------------------------------------- /assets/server8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server8.png -------------------------------------------------------------------------------- /assets/server9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/server9.png -------------------------------------------------------------------------------- /assets/tcc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/assets/tcc.png -------------------------------------------------------------------------------- /docs/Go语言内存对齐.md: -------------------------------------------------------------------------------- 1 | # Golang面试——内存对齐 2 | 3 | ## Golang对于变量类型的大小保证 4 | 5 | 在go中,如果两个值的类型为同一种类的类型,并且他们的类型的种类不为接口,数组和结构体,则这连个值的尺寸总是相等的 6 | 7 | 目前(go1.14),至少对于官方标准编译器来说,任何一个特定类型的所有值的尺寸都是相等的,所以我们也常说一个值的尺寸为此值的类型的尺寸 8 | 9 | 下表列出了各种种类的类型的尺寸(对标准编译器1.14来说): 10 | 11 | ![](../assets/align1.png) 12 | 13 | ## Golang对于变量的对齐保证 14 | 15 | 官方文档中的对齐保证的要求只有如下解释谷歌翻译结果:(原文就是圈红部分的上面的三条) 16 | 17 | * 对于任何类型的变量x,unsafe.Alignof(x)的结果最小为1; 18 | 19 | * 对于结构类型的变量x:对于x的每个字段f,unsafe.Alignof(x)是所有值unsafe.Alignof(x.f)中的最大值,但至少为1。 20 | 21 | * 对于数组类型的变量x:unsafe.Alignof(x)与数组元素类型的变量的对齐方式相同 22 | 23 | ![](../assets/align2.png) 24 | 25 | ## 内存对齐特征 26 | 27 | * 一个结构体类型的尺寸取决于它的各个字段的类型尺寸和这些字段的排列顺序 28 | * 一个数组类型的尺寸取决于它的元素类型的尺寸和它的长度,它的尺寸为它的元素类型的尺寸和它的长度的乘积 29 | * **如果结构或者数组类型包含大小为0的字段或者元素,则其大小为0,两个不同的零大小变量在内存中可能具有相同的地址** 30 | 31 | ## 例题 32 | 33 | ```go 34 | type T1 struct { 35 | a struct{} 36 | b int64 37 | } 38 | 39 | type T2 struct { 40 | a int64 41 | b struct{} 42 | } 43 | ``` 44 | 45 | * T1的大小为8字节,因为a不位于末尾,又是零大小字段,因此T1仅有8B 46 | * T2的大小在64位机上为16B,在32位机上为12B,因为T2.b位于结构体末尾,虽然大小为0,但是需要填充,结构体的大小为结构体中最大的元素a的大小的整数倍,因此64位机上填充8B,32位机上填充4B 47 | 48 | ```go 49 | type T struct { 50 | a struct{} 51 | b [0]int 52 | } 53 | ``` 54 | 55 | T的大小为0B,因为仅有零大小字段 56 | 57 | ```go 58 | type T struct { 59 | a int8 60 | b struct{} 61 | c [0]int 62 | } 63 | ``` 64 | 65 | T的大小为16B,a的大小为1B,b ,c 都为零大小字段, 66 | 67 | -------------------------------------------------------------------------------- /docs/etcd/分布式一致性协议.md: -------------------------------------------------------------------------------- 1 | # 分布式一致性协议 2 | 3 | ## 分布式系统设计的目标 4 | 5 | 1. **可用性** :核心需求,用于衡量一个分布式系统持续对外提供服务的能力 6 | 2. **可扩展性** :增加机器后不会改变系统的行为,并且能获得性能提升 7 | 3. **容错性** :系统发生错误时,具有对错误进行规避以及从错误中恢复的能力 8 | 4. **性能** :对外服务的响应延时和吞吐率要能满足用户的需求 9 | 10 | ## CAP原理 11 | 12 | * **Consistency(一致性)** :这里一致性指**强一致性** ,也就是说所有节点的数据时刻保持同步,系统的行为是串行的 13 | * **Availability(可用性)** :任何非故障节点都应该在有限的时间内给出请求的响应,不论该请求是否成功 14 | * **Tolerance to the partition of network(分区容忍性)** : 当节点之间发生无法通信的情况的时候,在丢失任意多的消息的情况下,系统仍然能够正常工作 15 | 16 | ## CAP三者不可兼得 17 | 18 | * **AP满足但是C不满足** :如果要求分区容错,那么一致性就无法保证。因为一旦发生网络通信节点故障,每个节点只能本地提供服务,就无法保证一致性 19 | * **CP满足但是A不满足** :如果要求强一致,那么可用性就得不到保证 20 | * **CA满足但是P不满足** :要求强一致性和可用性就必然放弃分区容错 21 | 22 | 就好像永远不可能发明永动机一样。 23 | 24 | ## 一致性协议 25 | 26 | 分布式系统的一致性是一个具备容错能力的分布式系统需要解决的基本问题。而一致性协议就是解决一致性问题的协议。 27 | 28 | ## 衡量一致性协议的标准 29 | 30 | * **可终止性** :非失败进程在有限时间内能够做出决定 31 | * **一致性** :所有进程必须对最终的决定达成一致 32 | * **合法性** :算法做出的决定必须在其他进程的期望值范围之内 33 | 34 | ## 一致性模型 35 | 36 | ### 强一致性(Strong Consistency) 37 | 38 | 强一致性也称原子一致性,**是最严格的一致性模型** ,具体要求如下: 39 | 40 | * 任何一次读都能读到该数据最近一次写入的数据 41 | * 系统中任何进程,看到的操作顺序,都与全局时钟下的顺序一致 42 | 43 | ### 顺序一致性(Sequential Consistency) 44 | 45 | 顺序一致性也称可序列化,比强一致性弱一点,但是要求也比较高。全局时钟导致一致性很难实现,**顺序一致性改为分布式逻辑时钟实现** 。顺序一致性要求所有的进程都以相同的顺序看到所有的修改,读操作未必能够及时得到此前其他进程对同一数据的写更新,但是每个进程读到的该数据的不同值的顺序是一致的。 46 | 47 | 满足顺序一致性的存储系统需要一个额外的逻辑时钟服务。 48 | 49 | ### 因果一致性(Causal Consistency) 50 | 51 | * **本地顺序** :本进程中,事件执行的顺序即为本地因果顺序 52 | * **异地顺序** :如果读操作返回的是写操作的值,那么该写操作在顺序上一定在读操作之前 53 | * **闭包传递** :与时钟向量里面定义一样,如果`a->b`,且`b->c`,就一定有`a->c` 54 | 55 | ### 可串行化一致性(Serializable Consistency) 56 | 57 | 大致意思就是程序并没有对调用者的调用和完成时间进行限制,但是操作的顺序等同于原子顺序。 58 | 59 | ### 最终一致性(Eventual Consistency) 60 | 61 | 放弃强一致性,保证程序的最终一致性。 62 | 63 | ## FPL不可能性定理 64 | 65 | **在异步通信场景下,任何一致性协议都不能保证,即使只有一个进程失败,其他非失败进程能达成一致。** 即任何分布式一致性协议都存在**不可终止性问题** 。而Paxos和Raft都只是通过随机的方式降低了发生不可终止问题的概率。 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /docs/golang/golang内存管理.md: -------------------------------------------------------------------------------- 1 | # Golang内存管理 2 | 3 | 4 | * 1. [前言](#) 5 | * 2. [Go的虚拟内存演变](#Go) 6 | * 2.1. [Go1.10版本之前的堆区内存——线性内存](#Go1.10) 7 | * 2.1.1. [线性堆内存的弊端](#-1) 8 | * 2.2. [Go1.11版本开始的堆区内存——稀疏内存](#Go1.11) 9 | * 3. [Go语言的内存管理组件](#Go-1) 10 | 11 | 15 | 16 | 17 | ## 1. 前言 18 | 19 | 在计算机系统中,主存`Memory`被组织成一个由连续字节组成的数组,每一个字节都有唯一的物理地址(`Physic Address`)。现代处理器使用的是一种虚拟寻址的方式(`Virtual Address`)的寻址形式,最少的寻址单位是字。虚拟地址向物理地址的转换是`MMU`查询页表进行转换完成的,页表存储在物理存储器中,一般来说,物理页的大小和虚拟页的大小相等。 20 | 21 | ## 2. Go的虚拟内存演变 22 | 23 | ### 2.1. Go1.10版本之前的堆区内存——线性内存 24 | 25 | Go在1.10版本之前启动的时候会初始化整个虚拟内存,并且**堆区的内存空间都是连续的**,如下所示的三个区域`spans`, `bitmap`, `arena`分别预留了`512MB`, `16GB`, `512GB`的内存空间,**这些内存并不是真正的物理内存,而是虚拟内存** 。 26 | 27 |
28 | 29 | 30 | 31 | - `spans` 区域存储了指向内存管理单元 `runtime.mspan`的指针,每个内存单元会管理几页的内存空间,每页大小为 8KB,**一些页的组合被称为`mspan`** 32 | - `bitmap` 用于标识 `arena` 区域中的那些地址保存了对象,并且用4bit来表示对象是否包含指针,GC标记信息。`bitmap`中的一个字节大小对应了`arena`区域4个指针的大小的内存,所以`bitmap`区域的大小为`512GB/(4*8B)=16GB` 33 | - `arena` 区域是真正的堆区,运行时会将 8KB 看做一页,这些内存页中存储了所有在堆上初始化的对象; 34 | 35 | 对于任意的地址,我们都可以根据`arena`的基地址计算该地址所在的页数并通过`spans`数组获得管理该片内存的管理单元`runtime.mspan`,`spans`数组多个连续的位置可能对应一个`runtime.mspan`结构。 36 | 37 | #### 2.1.1. 线性堆内存的弊端 38 | 39 | 线性堆内存虽然很简单和方便,但是在C和Go混合使用的时候会导致程序的崩溃: 40 | 41 | * 分配的内存地址发生冲突,导致堆的初始化和扩容失败。 42 | * 没有预留的大块内存可能被分配给C语言的二进制,导致扩容后的堆不连续。 43 | 44 | ### 2.2. Go1.11版本开始的堆区内存——稀疏内存 45 | 46 | 稀疏内存是 Go 语言在 1.11 中提出的方案,使用稀疏的内存布局不仅能移除堆大小的上限,还能解决 C 和 Go 混合使用时的地址空间冲突问题。不过因为基于稀疏内存的内存管理失去了内存的连续性这一假设,这也使内存管理变得更加复杂: 47 | 48 |
49 | 50 | **具体的稀疏内存涉及比较难和底层的东西,目前我的水平只能整理这么多内容,将来有能力了再补充** 。 51 | -------------------------------------------------------------------------------- /docs/golang/golang汇编代码阅读手册.md: -------------------------------------------------------------------------------- 1 | # Go语言汇编代码阅读手册 2 | 3 | 4 | 5 | 9 | 10 | 11 | ## 伪汇编 12 | 13 | Go 编译器会输出一种抽象可移植的汇编代码,这种汇编并不对应某种真实的硬件架构。之后 Go 的汇编器使用这种伪汇编,为目标硬件生成具体的机器指令。伪汇编这一个额外层可以带来很多好处,最主要的一点是方便将Go移植到新的架构上。 14 | 15 | ## Go编译指示 16 | 17 | ### `//go:noinline` 18 | 19 | `Inline`,是在编译期间发生的,将函数调用调用处替换为被调用函数主体的一种编译器优化手段。使用内联有如下的好处: 20 | 21 | - 减少函数调用的开销,提高执行速度。 22 | - 复制后的更大函数体为其他编译优化带来可能性,如 [过程间优化](https://link.segmentfault.com/?url=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FInterprocedural_optimization) 23 | - 消除分支,并改善空间局部性和指令顺序性,同样可以提高性能。 24 | 25 | 也有如下的缺点: 26 | 27 | - 代码复制带来的空间增长。 28 | - 如果有大量重复代码,反而会降低缓存命中率,尤其对 CPU 缓存是致命的。 29 | 30 | 例如下面的代码: 31 | 32 | ```go 33 | func appendStr(word string) string { 34 | return "new " + word 35 | } 36 | ``` 37 | 38 | 执行 `GOOS=linux GOARCH=386 go tool compile -S main.go > main.S` 39 | 部分展出它编译后的样子: 40 | 41 | ```go 42 | 0x0015 00021 (main.go:4) LEAL ""..autotmp_3+28(SP), AX 43 | 0x0019 00025 (main.go:4) PCDATA $2, $0 44 | 0x0019 00025 (main.go:4) MOVL AX, (SP) 45 | 0x001c 00028 (main.go:4) PCDATA $2, $1 46 | 0x001c 00028 (main.go:4) LEAL go.string."new "(SB), AX 47 | 0x0022 00034 (main.go:4) PCDATA $2, $0 48 | 0x0022 00034 (main.go:4) MOVL AX, 4(SP) 49 | 0x0026 00038 (main.go:4) MOVL $4, 8(SP) 50 | 0x002e 00046 (main.go:4) PCDATA $2, $1 51 | 0x002e 00046 (main.go:4) LEAL go.string."hello"(SB), AX 52 | 0x0034 00052 (main.go:4) PCDATA $2, $0 53 | 0x0034 00052 (main.go:4) MOVL AX, 12(SP) 54 | 0x0038 00056 (main.go:4) MOVL $5, 16(SP) 55 | 0x0040 00064 (main.go:4) CALL runtime.concatstring2(SB) 56 | ``` 57 | 58 | 可以看到,它并没有调用 `appendStr` 函数,而是直接把这个函数体的功能内联了。 59 | 60 | 如果你不想被内联,怎么办呢?此时就该使用 `go//:noinline` 了,像下面这样写: 61 | 62 | ```go 63 | //go:noinline 64 | func appendStr(word string) string { 65 | return "new " + word 66 | } 67 | ``` 68 | 69 | 编译后是: 70 | 71 | ```go 72 | 0x0015 00021 (main.go:4) LEAL go.string."hello"(SB), AX 73 | 0x001b 00027 (main.go:4) PCDATA $2, $0 74 | 0x001b 00027 (main.go:4) MOVL AX, (SP) 75 | 0x001e 00030 (main.go:4) MOVL $5, 4(SP) 76 | 0x0026 00038 (main.go:4) CALL "".appendStr(SB) 77 | ``` 78 | 79 | 此时编译器就不会做内联,而是直接调用 `appendStr` 函数。 80 | 81 | ### `//go:nosplit` 82 | 83 | `nosplit` 的作用是:**跳过栈溢出检测。** 正是因为一个 Goroutine 的起始栈大小是有限制的,且比较小的,才可以做到支持并发很多 Goroutine,并高效调度。 84 | [stack.go](https://link.segmentfault.com/?url=https%3A%2F%2Fgithub.com%2Fgolang%2Fgo%2Fblob%2Fmaster%2Fsrc%2Fruntime%2Fstack.go%23L71) 源码中可以看到,`_StackMin` 是 2048 字节,也就是 2k,它不是一成不变的,当不够用时,它会动态地增长。那么,必然有一个检测的机制,来保证可以及时地知道栈不够用了,然后再去增长。回到话题,`nosplit` 就是将这个跳过这个机制。 85 | 86 | **显然地,不执行栈溢出检查,可以提高性能,但同时也有可能发生 `stack overflow` 而导致编译失败。** 87 | 88 | ### `//go:noescape` 89 | 90 | `noescape` 的作用是:**禁止逃逸,而且它必须指示一个只有声明没有主体的函数。** 91 | 92 | **什么是逃逸?** Go 相比 C、C++ 是内存更为安全的语言,主要一个点就体现在它可以自动地将超出自身生命周期的变量,从函数栈转移到堆中,逃逸就是指这种行为。 93 | 94 | **禁止逃逸的优劣** :最显而易见的好处是,GC 压力变小了。因为它已经告诉编译器,下面的函数无论如何都不会逃逸,那么当函数返回时,其中的资源也会一并都被销毁。**不过,这么做代表会绕过编译器的逃逸检查,一旦进入运行时,就有可能导致严重的错误及后果。** 95 | 96 | ### `//go:norace` 97 | 98 | `norace` 的作用是:**跳过竞态检测**。我们知道,在多线程程序中,难免会出现数据竞争,正常情况下,当编译器检测到有数据竞争,就会给出提示。 99 | 100 | **禁止静态检测的优劣** :使用 `norace` 除了减少编译时间,我想不到有其他的优点了。但缺点却很明显,那就是数据竞争会导致程序的不确定性。 101 | 102 | ### 总结 103 | 104 | **绝大多数情况下,无需在编程时使用 `//go:` Go 语言的编译器指示,除非你确认你的程序的性能瓶颈在编译器上,否则你都应该先去关心其他更可能出现瓶颈的事情。** 105 | 106 | ## 待完善 107 | 108 | -------------------------------------------------------------------------------- /docs/golang/golang调度器之GMP组成.md: -------------------------------------------------------------------------------- 1 | # Golang调度器源码分析——GMP 2 | 3 | -------------------------------------------------------------------------------- /docs/golang/golang面试之map.md: -------------------------------------------------------------------------------- 1 | # golang面试之map 2 | 3 | 4 | * 1. [什么类型的值可以作为map的key](#mapkey) 5 | * 2. [math.NaN作为key](#math.NaNkey) 6 | * 3. [map的key为什么是无序的](#mapkey-1) 7 | * 4. [map是线程安全的吗](#map) 8 | 9 | 13 | 14 | 15 | ## 1. 什么类型的值可以作为map的key 16 | 17 | 从整体上来说,只要是支持比较的类型都可以作为key,除开slice, map, functions这几种类型,其他类型都是可行的、 18 | 19 | 而**任何类型都可以作为map的value** 。 20 | 21 | ## 2. math.NaN作为key 22 | 23 | 下面的程序代码输出几行? 24 | 25 | ```go 26 | func NanAsKey() { 27 | m := make(map[interface{}]interface{}) 28 | m[math.NaN()] = 1 29 | m[math.NaN()] = 2 30 | 31 | for k, v := range m { 32 | fmt.Println(k, v) 33 | } 34 | } 35 | ``` 36 | 37 | 程序最后输出2行: 38 | 39 | ```go 40 | PS D:\Github\repo\Go-Backend\src\g_map> go run main.go 41 | NaN 2 42 | NaN 1 43 | ``` 44 | 45 | **因为NaN有如下特性** : 46 | 47 | * `NaN != NaN` 48 | 49 | * `hash(NaN) != hash(NaN)` 50 | 51 | ## 3. map的key为什么是无序的 52 | 53 | 因为map会发生扩容,原先的一些bucket中的元素可能搬迁到另外一个完全不同的位置(也取决于被hash的值),因此是无序的。 54 | 55 | ## 4. map是线程安全的吗 56 | 57 | map不是线程安全的,在查找,赋值,遍历,删除的过程中都会检测写标志,一旦发现写标志置位为1,则直接panic 58 | 59 | -------------------------------------------------------------------------------- /docs/golang/golang面试题汇总.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OxCaffee/go-backend/6eb9a3195665e4505e83269088ed2add4e8ef970/docs/golang/golang面试题汇总.md -------------------------------------------------------------------------------- /docs/golang/runtime包解读之golang程序启动流程.md: -------------------------------------------------------------------------------- 1 | # runtime包解读之Go程序启动流程 2 | 3 | 4 | * 1. [前言](#) 5 | * 2. [Golang程序的入口——rt0_xxxx_amd64.s](#Golangrt0_xxxx_amd64.s) 6 | * 3. [Go引导的流程图](#Go) 7 | * 4. [总结](#-1) 8 | 9 | 13 | 14 | 15 | ## 1. 前言 16 | 17 | 这篇文章对于后续理解Go的调度器模型有很好的意义,因为在调度器启动的过程中,很多函数都是调用的汇编代码,单单看源码的话没有办法将整个流程给串联起来,因此,先了解整个Golang程序的启动流程是很重要的。 18 | 19 | ## 2. Golang程序的入口——rt0_xxxx_amd64.s 20 | 21 | 对于不同计算机架构,例如MacOS或者Windows,Go的程序入口时不同的,例如: 22 | 23 | * MacOS在`src/runtime/rt0_darwin_amd64.s` 24 | * Linux在`src/runtime/rt0_linux_amd64.s` 25 | * Windows在`src/runtime/rt0_windows_amd64.s` 26 | 27 | `rt0`是`runtime0`的缩写,代表**运行时的创世,上帝** 。 28 | 29 | 以linux操作系统为例: 30 | 31 | ```assembly 32 | TEXT _rt0_amd64_linux(SB),NOSPLIT,$-8 33 | JMP _rt0_amd64(SB) 34 | ``` 35 | 36 | 会发现`rt0_linux_amd64`最终跳转到了`_rt0_amd64` ,其实无论对于哪种架构,最终入口都会被指向为`_rt0_amd64`。`_rt0_amd64`在`runtime/asm_amd64.s`文件中,内容如下: 37 | 38 | ```assembly 39 | TEXT _rt0_amd64(SB),NOSPLIT,$-8 40 | MOVQ 0(SP), DI // argc 41 | LEAQ 8(SP), SI // argv 42 | JMP runtime·rt0_go(SB) 43 | ``` 44 | 45 | 该代码的作用是将输入的`argc`和`argv`从内存移入到寄存器当中,执行完成之后,栈指针SP的前两个值分别为`argc`和`argv`,其对应参数的数量和具体参数值。 46 | 47 | `_rt0_amd64`设置完`argc`和`argv`之后将程序跳转到`rt0_go`里。`rt0_go`位于`runtime/asm_wasm.s`中: 48 | 49 | ```assembly 50 | TEXT runtime·rt0_go(SB), NOSPLIT|NOFRAME|TOPFRAME, $0 51 | // save m->g0 = g0 52 | MOVD $runtime·g0(SB), runtime·m0+m_g0(SB) 53 | // save m0 to g0->m 54 | MOVD $runtime·m0(SB), runtime·g0+g_m(SB) 55 | // set g to g0 56 | MOVD $runtime·g0(SB), g 57 | CALLNORESUME runtime·check(SB) 58 | CALLNORESUME runtime·args(SB) 59 | CALLNORESUME runtime·osinit(SB) 60 | CALLNORESUME runtime·schedinit(SB) 61 | MOVD $runtime·mainPC(SB), 0(SP) 62 | CALLNORESUME runtime·newproc(SB) 63 | CALL runtime·mstart(SB) // WebAssembly stack will unwind when switching to another goroutine 64 | UNDEF 65 | ``` 66 | 67 | - `runtime.check`:运行时类型检查,主要是校验编译器的翻译工作是否正确,是否有 “坑”。基本代码均为检查 `int8` 在 `unsafe.Sizeof` 方法下是否等于 1 这类动作。 68 | - `runtime.args`:系统参数传递,主要是将系统参数转换传递给程序使用。 69 | - `runtime.osinit`:系统基本参数设置,主要是获取 CPU 核心数和内存物理页大小。 70 | - `runtime.schedinit`:进行各种运行时组件的初始化,包含调度器、内存分配器、堆、栈、GC 等一大堆初始化工作。会进行 p 的初始化,并将 m0 和某一个 p 进行绑定。 71 | - `runtime.main`:主要工作是运行 main goroutine,虽然在`runtime·rt0_go` 中指向的是`$runtime·mainPC`,但实质指向的是 `runtime.main`。 72 | - `runtime.newproc`:创建一个新的 goroutine,且绑定 `runtime.main` 方法(也就是应用程序中的入口 main 方法)。并将其放入 m0 绑定的p的本地队列中去,以便后续调度。 73 | - `runtime.mstart`:启动 m,调度器开始进行循环调度。 74 | 75 | 在 `runtime·rt0_go` 方法中,其主要是完成各类运行时的检查,系统参数设置和获取,并进行大量的 Go 基础组件初始化。 76 | 77 | 初始化完毕后进行主协程(main goroutine)的运行,并放入等待队列(GMP 模型),最后调度器开始进行循环调度。 78 | 79 | ## 3. Go引导的流程图 80 | 81 |
82 | 83 | ## 4. 总结 84 | 85 | 以上就是golang程序的引导和启动过程,有了上面大概的了解,我们对于后面的`schedinit`,`mstart`等就有了更深的理解,后面的`runtime`包源码阅读也会按照上面启动的顺序进行。 -------------------------------------------------------------------------------- /docs/golang/runtime包解读之mgc.md: -------------------------------------------------------------------------------- 1 | # Golang runtime包源码解读——mgc(1) 2 | 3 | 4 | * 1. [不同阶段的GC行为](#GC) 5 | * 1.1. [Sweep Termination](#SweepTermination) 6 | * 1.2. [Mark Phase](#MarkPhase) 7 | * 1.3. [Mark Termination](#MarkTermination) 8 | * 1.4. [Sweep Phase](#SweepPhase) 9 | * 2. [并发清扫(Concurrent Sweep)](#ConcurrentSweep) 10 | * 3. [GC Rate](#GCRate) 11 | * 4. [Oblets分割](#Oblets) 12 | 13 | 17 | 18 | 19 | ## 1. 不同阶段的GC行为 20 | 21 | ### 1.1. Sweep Termination 22 | 23 | 1. STW,这会让所有的P都到达安全点`safe point` 24 | 2. 清除所有未被清除的`spans`,注意,未被清除的`spans`的存在只有一种可能:**GC循环被强制提前执行,导致还有`spans`未被清理** 25 | 26 | ### 1.2. Mark Phase 27 | 28 | 1. 设置`gcphase`变量从`_GCoff`到`_Gcmark` 29 | 2. 开启所有的写屏障`write barrier` 30 | 3. 将根标记任务`root mark job`入队列(**注意,在所有的P开启写屏障之前,不会有任何的对象被扫描** ) 31 | 4. `Start the world` 。从这个时间点开始,GC工作将由调度器指定的`mark workers`和内存分配器的协助完成。写屏障将会**着色(shading)所有对重写指针(overwritten pointer)和新指针(new pointer)** 。新分配的指针对象会被立即标注为黑色。 32 | 33 | ```markdown 34 | 疑问: 何为overwritten指针?这个疑问可能要等mbarrier.go源码读完之后才知道。 35 | ``` 36 | 37 | 5. 根标记任务将会被执行(`root marking jobs`) 。执行的操作包括扫描所有堆栈,着色所有全局变量,以及着色任何堆指针、堆外运行时数据结构。扫描堆栈会停止一个 goroutine,遮蔽在其堆栈上找到的任何指针,然后恢复 goroutine。 38 | 39 | 6. 取出所有的灰色对象,将所有的灰色对象标注为黑色对象,并将与该灰色对象“连接”的对象标记为灰色(这意味着又有新的指针被加入队列) 40 | 7. GC使用了分布式标记终止算法来检测没有其他标记任务或者灰色对象(详情请见`gcMarkDone`) 。至此,GC任务将会过度到`mark termination`阶段。 41 | 42 | ### 1.3. Mark Termination 43 | 44 | 1. STW 45 | 2. 将`gcphase`变量设置为`_GCmarktermination` ,禁用所有的`gc workers`和`gc assists` 46 | 47 | ### 1.4. Sweep Phase 48 | 49 | 1. 将`gcphase`设置为`_GCoff` ,设置sweep状态并且禁用所有的写屏障 50 | 2. `Start the world` 。从这个时间点开始,新分配的对象为白色。**必要时可以分配待清扫的spans去使用** 51 | 52 | ```markdown 53 | go源码中原文是这么说的: 54 | Start the world. From this point on, newly allocated objects are white, and allocating sweeps spans before use if necessary 55 | ``` 56 | 57 | 3. GC 在后台执行并发清除的同时并响应分配。 58 | 59 | ## 2. 并发清扫(Concurrent Sweep) 60 | 61 | 在清扫阶段(`sweep phase`),所有的程序正常运行,堆内存中的`span`会\一个一个地被回收,并且是采用懒回收地方式(当一个goroutine需要另外一个span的时候才会触发清扫),清扫任务交由一个后台goroutine执行(`background`),在STW `mark termination`阶段,所有的`spans`都会被标记为`needs sweeping` 。 62 | 63 | 为了避免请求过多的OS内存,当一个goroutine需要另外一个`span`的时候,它会首先执行回收操作`reclaim memory by sweeping`。 64 | 65 | * 当一个goroutine需要一个小对象(`small-size-object`),会优先回收小对象大小的`span` 66 | * 当一个goroutine需要一个大对象(`large-size-object`),会优先回收大对象大小的`span` 67 | 68 | **在一种情况下这可能还不够:如果一个 goroutine 将两个不相邻的单页跨度清除并释放到堆中,它将分配一个新的两页跨度,但仍然可以有其他一页未扫描跨度,这种情况下仍然可以被合并成一个两页的span。** 69 | 70 | ## 3. GC Rate 71 | 72 | `Next GC`发生在分配了与已使用内存成正比的额外内存之后。这个比例由`GOGC`环境变量控制,例如`GOGC=100`,当使用了4M内存,那么下一次GC的内存将会是8M,这个比例是线性的。 73 | 74 | ## 4. Oblets分割 75 | 76 | 为了避免扫描大对象造成的gc停顿,GC会将超过`maxObletsBytes`的大对象分割为`maxObletsBytes`大小的对象。分割后的对象会被当成新的对象处理后面的GC。 77 | -------------------------------------------------------------------------------- /docs/golang/runtime包解读之调度器入口mainPC.md: -------------------------------------------------------------------------------- 1 | # runtime包解读——调度器的入口mainPC 2 | 3 | 在`asm_wasm.s`我们知道,在所有的初始化完成之后,golang world开始运转,此时程序会跳转到入口主函数`mainPC`位置: 4 | 5 | ```assembly 6 | // asm_wasm.s 7 | TEXT runtime·rt0_go(SB), NOSPLIT|NOFRAME|TOPFRAME, $0 8 | // save m->g0 = g0 9 | MOVD $runtime·g0(SB), runtime·m0+m_g0(SB) 10 | // save m0 to g0->m 11 | MOVD $runtime·m0(SB), runtime·g0+g_m(SB) 12 | // set g to g0 13 | MOVD $runtime·g0(SB), g 14 | CALLNORESUME runtime·check(SB) 15 | CALLNORESUME runtime·args(SB) 16 | CALLNORESUME runtime·osinit(SB) 17 | CALLNORESUME runtime·schedinit(SB) 18 | MOVD $runtime·mainPC(SB), 0(SP) 19 | CALLNORESUME runtime·newproc(SB) 20 | CALL runtime·mstart(SB) // WebAssembly stack will unwind when switching to another goroutine 21 | UNDEF 22 | ``` 23 | 24 | 可以看到初始化完成之后,会通过`MOVD`将`mainPC`压入`SP`栈顶,`mainPC`的声明同样在`asm_wasm.s`中: 25 | 26 | ```assembly 27 | DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) 28 | GLOBL runtime·mainPC(SB),RODATA,$8 29 | ``` 30 | 31 | 在程序跳转指示中,可以看到`mainPC`实际上就是指向`runtime.main`,即调度器的入口主函数。 32 | 33 | ```assembly 34 | runtime.mainPC -> runtime.main 35 | ``` 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /docs/golang/如何优雅地关闭channel.md: -------------------------------------------------------------------------------- 1 | # 如何优雅地关闭channel 2 | 3 | 4 | * 1. [关闭channel的难点](#channel) 5 | * 2. [关闭channel的原则](#channel-1) 6 | * 3. [不优雅的关闭方法](#) 7 | * 3.1. [defer-recover兜底](#defer-recover) 8 | * 3.2. [使用sync.Once保证只关闭一次](#sync.Once) 9 | * 4. [优雅的关闭方法](#-1) 10 | * 4.1. [一个sender,一个receiver](#senderreceiver) 11 | * 4.2. [一个sender,M个receiver](#senderMreceiver) 12 | * 4.3. [N个sender,一个receiver](#Nsenderreceiver) 13 | * 4.4. [N个sender,M个receiver](#NsenderMreceiver) 14 | 15 | 19 | 20 | 21 | ## 1. 关闭channel的难点 22 | 23 | * 在不改变channel自身状态下,无法获知一个channel是否关闭 24 | * 关闭一个closed channel会导致panic。所以,如果关闭channel的一方在不知道channel是否关闭的情况下就去贸然关闭channel是很危险的事情 25 | * 向一个closed channel发送数据会导致panic。所以,如果向channel发送数据的一方不知道channel被关闭就去发送数据很危险 26 | 27 | ## 2. 关闭channel的原则 28 | 29 | **不要从一个 receiver 侧关闭 channel,也不要在有多个 sender 时,关闭 channel。** 30 | 31 | ## 3. 不优雅的关闭方法 32 | 33 | ### 3.1. defer-recover兜底 34 | 35 | 使用defer-recover机制,放心大胆关闭channel或者向channel发送数据。即使发生了panic,有defer-recover机制兜底 36 | 37 | ### 3.2. 使用sync.Once保证只关闭一次 38 | 39 | 利用sync.Once特性保证只关闭channel一次。**这种方法保证了channel只被关闭一次,但是无法保证被关闭后没有sender发送数据** 40 | 41 | ## 4. 优雅的关闭方法 42 | 43 | **增加一个关闭信号的channel,receiver通过信号channel下达关闭数据channel指令,sender接收到关闭信号之后,停止接收数据。** 44 | 45 | ### 4.1. 一个sender,一个receiver 46 | 47 | 直接从sender端关闭即可 48 | 49 | ### 4.2. 一个sender,M个receiver 50 | 51 | 直接从sender端关闭即可 52 | 53 | ### 4.3. N个sender,一个receiver 54 | 55 | 在这种情况下,优雅地关闭channel的方法就是receiver负责通知sender不要再发送数据了,然后关闭它。 56 | 57 | ```go 58 | func main() { 59 | datach := make(chan int, 100) 60 | stopch := make(chan struct{}) 61 | 62 | // senders 63 | for i := 0; i < 100; i++ { 64 | go func() { 65 | for { 66 | select { 67 | case <-stopch: 68 | return 69 | case datach <-rand.Intn(100): 70 | } 71 | } 72 | }() 73 | } 74 | 75 | // receiver 76 | go func() { 77 | for val := range datach { 78 | if val == 100 { 79 | fmt.Println("please stop the sender") 80 | // 关闭stopch,让gc代劳 81 | close(stopch) 82 | return 83 | } 84 | fmt.Println(val) 85 | } 86 | }() 87 | 88 | <-time.After(time.Second) 89 | } 90 | ``` 91 | 92 | ### 4.4. N个sender,M个receiver 93 | 94 | 这里有 M 个 receiver,如果直接还是采取第 3 种解决方案,由 receiver 直接关闭 stopCh 的话,就会重复关闭一个 channel,导致 panic。因此需要增加一个中间人,M 个 receiver 都向它发送关闭 dataCh 的“请求”,中间人收到第一个请求后,就会直接下达关闭dataCh 的指令(通过关闭 stopCh,这时就不会发生重复关闭的情况,因为 stopCh 的发送方只有 中间人一个)。另外,这里的 N 个 sender 也可以向中间人发送关闭 dataCh 的请求。 95 | 96 | ```go 97 | func CloseChanElegantly() { 98 | // datach := make(chan int, 100) 99 | stopch := make(chan struct{}) 100 | tostop := make(chan string, 1) 101 | 102 | var stopsignal string 103 | 104 | go func() { 105 | stopsignal = <-tostop 106 | fmt.Println(stopsignal) 107 | close(stopch) 108 | }() 109 | 110 | for i := 0; i < 3; i++ { 111 | go func(i int) { 112 | fmt.Printf("这是第%d个sender\n", i) 113 | if i == 2 { 114 | fmt.Println("第2个sender决定关闭channel") 115 | tostop <- "stop!!!!!" 116 | } 117 | 118 | select { 119 | case <-tostop: 120 | return 121 | default: 122 | } 123 | }(i) 124 | } 125 | 126 | for i := 0; i < 4; i++ { 127 | go func(i int) { 128 | fmt.Printf("这是第%d个receiver\n", i) 129 | if i == 2 { 130 | fmt.Println("第2个receiver决定关闭channel") 131 | tostop <- "stop!!!!!" 132 | } 133 | select { 134 | case <-tostop: 135 | return 136 | default: 137 | } 138 | }(i) 139 | } 140 | 141 | <-time.After(3*time.Second) 142 | } 143 | ``` 144 | 145 | -------------------------------------------------------------------------------- /docs/golang/探究golang的GC过程.md: -------------------------------------------------------------------------------- 1 | # 探究Golang的GC过程 2 | 3 | ## GC的行为 4 | 5 | 当GC**开始**的时候,要经历3个阶段,其中2个阶段需要`STW(Stop The World)`,这3个阶段分别为: 6 | 7 | * `Mark Setup` :需要`STW` 8 | * `Concurrently Marking` :并发标记阶段 9 | * `Mark Termination` :需要`STW` 10 | 11 | ### Mark Setup 12 | 13 | 当GC开始的时候,Golang内核的第一件事情就是开启写屏障(`Write Barrier`),开启写屏障的原因是:**为了保持Heap内的数据具有一致性(data integrity),因为GC和用户协程(application goroutines)是并发运行的,如果在GC工作期间,Heap上的对象发生变化,那么就会给程序带来不可估量的后果,比如一个本不该被回收的对象被回收了,那么就会触发空指针异常** 。 14 | 15 | 为了让写屏障能够正常开启,所有的用户协程都需要停止所有的活动,这个阶段被称为`STW`,这个阶段往往时间很快,一般只有10~30ms。 16 | 17 | **这就来了一个问题,`STW`阶段是如何让所有的goroutine停止的?** 18 | 19 | 唯一的办法就是GC观察所有的goroutine并且等待所有的goroutine去进行一次**系统调用(system function call)** ,系统调用能够保证所有的goroutine能够在一个**安全点(safe point)**停止 20 | 21 | -------------------------------------------------------------------------------- /docs/grpc之passthrough解析器.md: -------------------------------------------------------------------------------- 1 | # gRPC之passthrough解析器 2 | 3 | ## 何时会使用 4 | 5 | * 当gRPC客户端在执行Dial的时候,假如没有指定链接地址的schema,将会默认使用passthrough解析器,schema即访问地址前缀字符串,例如`dns://www.baidu.com/xxx.yy` ,schema就是dns。 6 | * 当用户指定使用passthrough解析器 -------------------------------------------------------------------------------- /docs/mysql/mysql索引汇总.md: -------------------------------------------------------------------------------- 1 | # MySQL索引汇总 2 | 3 | ## 聚簇索引和非聚簇索引的区别是什么? 4 | 5 | MySQL的索引类型跟存储引擎是相关联的,**InnoDB存储引擎数据文件跟索引文件全部都放在ibd文件中,而MyISAM的数据文件放在myd,索引放在myi文件中** 。其实区分聚簇索引和非聚簇索引**只要判断数据跟索引是否存储在一起就可以了** 。 6 | 7 | InnoDB存储引擎在进行数据插入的时候,数据必须要跟索引放置在一起,如果有主键就使用主键,没有主键就使用UNIQUE KEY,没有UNIQUE KEY就使用6字节的rowid,因此跟数据绑定在一起的就是聚簇索引,而为了避免数据冗余存储,其他的索引的叶子节点存储的都是聚簇索引的Key值,因此InnoDB中既有聚簇索引也有非聚簇索引,而MyISAM中仅仅只有非聚簇索引。 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /docs/mysql/mysql进阶面试题.md: -------------------------------------------------------------------------------- 1 | # MySQL进阶面试题 2 | 3 | ## ACID靠什么保证 4 | 5 | * 原子性由undo log保证,它记录了需要回滚的日志信息,事务回滚的时候就撤销已经执行成功的SQL 6 | * 一致性由其他三大特征来保证,程序代码要保证业务上的一致性 7 | * 隔离性是由MVCC保证的 8 | * 持久性由redo log保证,MySQL在修改数据的时候会在redo log中记录一份日志数据,就算数据没有保存成功,只要日志保存成功了,数据仍然不会丢失 -------------------------------------------------------------------------------- /docs/redis/redis压缩列表.md: -------------------------------------------------------------------------------- 1 | # Redis压缩列表ziplist 2 | 3 | -------------------------------------------------------------------------------- /docs/sync包之map.md: -------------------------------------------------------------------------------- 1 | # Go sync包源码阅读—map 2 | 3 | -------------------------------------------------------------------------------- /docs/sync包之once.md: -------------------------------------------------------------------------------- 1 | # Go并发编程——深入理解sync.Once 2 | 3 | 4 | * 1. [Once结构体定义](#Once) 5 | * 2. [#Do](#Do) 6 | * 2.1. [错误的使用](#) 7 | * 3. [#doSlow](#doSlow) 8 | 9 | 13 | 14 | 15 | ## 1. Once结构体定义 16 | 17 | ```go 18 | type Once struct { 19 | done uint32 20 | m Mutex 21 | } 22 | ``` 23 | 24 | done 用于判定函数是否执行,如果不为 0 会直接返回。 25 | 26 | ## 2. #Do 27 | 28 | ```go 29 | func (o *Once) Do(f func()) { 30 | // Note: Here is an incorrect implementation of Do: 31 | // 32 | // if atomic.CompareAndSwapUint32(&o.done, 0, 1) { 33 | // f() 34 | // } 35 | // 36 | // Do guarantees that when it returns, f has finished. 37 | // This implementation would not implement that guarantee: 38 | // given two simultaneous calls, the winner of the cas would 39 | // call f, and the second would return immediately, without 40 | // waiting for the first's call to f to complete. 41 | // This is why the slow path falls back to a mutex, and why 42 | // the atomic.StoreUint32 must be delayed until after f returns. 43 | 44 | if atomic.LoadUint32(&o.done) == 0 { 45 | // Outlined slow-path to allow inlining of the fast-path. 46 | o.doSlow(f) 47 | } 48 | } 49 | ``` 50 | 51 | 在上面官方的说法是,使用`atomic.CompareAndSwapUint32(...)`是错误的用法。**经过测试,这种写法,虽然能保证f()最多执行一次,但是无法保证f()最少执行一次,因为如果一个goroutine先行抢占了`o.done`,其他goroutine不会等当前f()执行成功,而是会立即返回** 。 52 | 53 | ### 2.1. 错误的使用 54 | 55 | ```go 56 | func (o *MyOnce) Do(f func()) { 57 | if atomic.CompareAndSwapUint32(&o.done, 0, 1) { 58 | f() 59 | } 60 | } 61 | ``` 62 | 63 | ## 3. #doSlow 64 | 65 | ```go 66 | func (o *Once) doSlow(f func()) { 67 | o.m.Lock() 68 | defer o.m.Unlock() 69 | if o.done == 0 { 70 | // 这里只有f()成功执行完成,才会设置o.done为1 71 | defer atomic.StoreUint32(&o.done, 1) 72 | f() 73 | } 74 | } 75 | ``` 76 | 77 | --------------------------------------------------------------------------------