数据库的锁
按范围划分,mysql里面的锁大致分为全局锁,表级锁和行级锁
全局锁
Flush tables with read lock;
使用命令FTWRL后,整个库处于只读状态.
全局锁的典型使用场景是,做全库逻辑备份.
当 mysqldump 使用参数–single-transaction的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。而由于 MVCC 的支持,这个过程中数据是可以正常更新的.如果直接使用mysqldump的话,会导致加上全局锁,业务基本不可用.
开启事务(可重复读)即可得到一致性视图.但是需要引擎支持
当引擎不支持的情况下,FTWRL就很有必要了.
表级锁
表锁一般是在数据库引擎不支持行锁的时候才会被用到的。
表锁
lock tables … read/write
unlock tables
元数据锁
meta data lock,MDL
MDL 不需要显式使用,在访问一个表的时候会被自动加上。MDL 的作用是防止DDL和DML并发引发冲突.
事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。
如何安全地给小表加字段?
资源首先我们要解决长事务,事务不提交,就会一直占着 MDL 锁。在 MySQL 的information_schema 库的 innodb_trx 表中,你可以查到当前执行中的事务。如果你要
做 DDL 变更的表刚好有长事务在执行,要考虑先暂停 DDL,或者 kill 掉这个长事务。
行级锁
mysql的行锁是在引擎层由各个引擎自己实现的.行级锁即InnoDB的行锁.
锁的释放
在事务当中,行锁在需要时加上,因为两阶段提交的缘故,在事务结束时释放.所以在事务当中,最可能造成锁冲突,最可能影响并发度的锁尽量往后放.
死锁和死锁检测
事务互相等待资源释放并持有资源时,会出现死锁.
死锁解决方案:
- 设置等待超时,这个超时时间可以通过参数innodb_lock_wait_timeout 来设置。
- 发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑
热点行更新解决方案:
控制访问相同资源的并发事务量。
- 关闭死锁检测,但要保证业务一定不会出现死锁(有风险)
- 控制并发度,对于相同行的更新,在进入引擎之前排队.实现在数据库服务端/中间件上.
- 逻辑行拆分,一行拆为多行,然后进行上层逻辑随机命中物理行.