全局锁
- 做全局逻辑备份:整个库只能只读无法更新和新增删除
- 命令是Flush tables with read lock
- 一致性读需要引擎支持隔离级别,myisam只能使用ftwrl,(在ftwrl之前会保证所有的事务都是提交状态)
- 官方自带逻辑备份日记mysqldump,当mysqldump使用参数-single-transaction的时候.开启一个事务来保证视图的一致性,mvcc的支持所以这时候是可以更新的,但是这个方法只适用于所有表使用事务引擎的库,
- 之所以不用read-only,是因为readonly的影响面更大,如果是FTWRL的情况是如果系统处异常,会主动释放全局锁,但是readonly是会一直锁住
表级锁:
- lock tables …read/write:用unlock tables来释放,这个锁除了会限制其他线程的读写,也会限制本线程除了锁内的操作之外,其余操作也不行
- MDL:当对数据增删改查的时候,会加MDL读锁,对表结构做修改是,加- MDL写锁:读锁和读锁之前不互斥,但是读锁和写锁,写锁和写锁之间是互斥的,保证变更表结构操作的安全性,
- MDL可能出现的bug:在读锁a发生时,刚好写锁b发生了,b就要等a事务提交之后才能进行,那也是说如果a一直没有提交,有b阻塞住, 那这个表是没办法读写(互斥),可能会出现在访问频繁的表中,
- 解决方法是:优先解决长事务,事务一直不提交,就没办法进行下一步,如果访问频繁,直接设置MDL写锁的过期时间,
行锁
- myisam不支持行锁:
- 两阶段锁:事务中,行锁是需要才加上的,但是并不是不需要了就释放,而是要在事务commit之后才释放行锁,两阶段锁协议(所以行锁在事务中不能停留太久,加锁和释放之间要最短)
死锁和死锁检测
- 如果两个线程一直在等待其他线程的锁,
- 死锁策略:
- 1进入等待:设置超时时间 (innordb_lock_wait_timeout设置)
- 2:主动死锁检测:主动回滚其中一个事务,让其他事务执行(innordb_deadlock_detect设置为on,开启逻辑),但是要耗费大量cpu资源,所以要控制访问相同资源的并发量
如何解决热点行更新导致的问题
- 临时把死锁检测关闭(但是要保证不会一定不会发生死锁)
- 并发控制度:在中间件或mysql源码中做并发量的控制,使其并发量维持在一定的量,
- 把一行做成逻辑上的多行:比如一个账户的金额分成十条数据来维持,但是要updata的时候就随机选一条来更新,对同一个用户的金额改变就可能在不同的记录里面执行了