全局锁

全局锁,顾名思义就是给整个数据库加锁,命令为Flush tables with read lock,当你需要让整个数据库处于只读状态的时候可以使用该命令,使用了该命令以后会使除了查询sql其他的语句都会被阻塞。常常被用于数据库的逻辑备份中。在正常业务中,数据库处于可读状态是很危险的情况,在innoDB中,可以使用mysqldump工具在备份数据库,因为innoDB引擎支持了事务,有mvcc支持,就不需要使用全局锁这种对于业务伤害很大的方式备份数据库

表级锁

表锁

表锁的语法是lock tables … read/write,除了unlock tables主动释放锁,也可以在客户端断开连接的时候自动释放,表锁会限制线程的读写,一般不推荐使用

元数据锁(MDL)

不用显性的添加使用,在我们访问一张表的时候会被自动添加,来保证读写的正确性,在5.5版本的引入了MDL锁,当表做增删查改操作的时候使用读锁,对表结构做变更的时候添加写锁,利用读写互斥的规则来确保数据的正确性

行锁

mylsam引擎是不支持行锁的,innoDB支持行锁,这也是mylsam被替代的重要的原因之一,在innoDB中行锁是需要的时候被加上,但是不是不需要的时候就释放,而是要等事务结束了才会被释放,这个就是著名的两阶段的锁协议,在这里我们就需要了解一个规则,需要把最容易引起并发的锁往后放一放,这样可以减少锁等待时间,增加并发度。

死锁与死锁检测

只要涉及到锁的地方都会死锁的概念,在并发系统中,不同的线程持有对方想要的资源,都在等待对方释放资源的时候,就会发生死锁,在mysql中有两种策略来防止这种情况

等待超时

innodb_lock_wait_timeout字段来设置超时时间,但是当这个值设太大,业务无法接受,设置的太小,如果是锁等待怎么办,会造成误伤。

死锁检测

正常情况下,我们要使用第二种策略,即主动的死锁检测,如果发生死锁就回滚,但是因为死锁检测的时间复杂度是O(n2),对资源的开销较大,造成cpu利用率很高,但是执行不了多少事务,所以我们想要尽量从代码层面控制,高级一点就修改mysql源码,在数据进入引擎的时候排队,或者是在逻辑层面将一行改为多行来减少并发。