暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Mysql - 锁

小D学Java 2019-08-18
110


加锁范围分类

  • 全局锁

  • 表锁

    • 表锁 -- innodb下一般不会直接使用表锁(lock table)

    • 元数据锁(MDL)

  • 行锁

全局锁

全局锁就是对整个数据库实例加锁。MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL)。当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。

全局锁的典型使用场景是,做全库逻辑备份。当然若是innodb引擎的话,可直接使用可重复读的事务隔离级别就可避免使用全局锁,而如果使用的是myisam引擎的话则只能使用全局锁来保证数据一致性.

MDL(metadata lock)

MDL的作用是保证读写的正确性.MDL 不需要显式使用,在访问一个表的时候会被自动加上。当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。

MDL的释放时机是事务提交的时候.

Online DDL

online ddl主要包括3个阶段,prepare阶段,ddl执行阶段,commit阶段.

Online DDL的过程是这样的:

  1. 拿MDL写锁

  2. 降级成MDL读锁

  3. 真正做DDL

  4. 升级成MDL写锁

  5. 释放MDL锁


行锁

行锁释放锁的时机是在事务提交的时候,所以我们需要将一个事务中最容易造成锁冲突,并发度小的的sql语句放在最后执行.

间隙锁

间隙锁(GAP LOCK),锁的就是两个值之间的空隙。间隙锁跟间隙锁之间不存在冲突,跟间隙锁存在冲突的是往这个间隙中插入记录.

next-key Lock

间隙锁和行锁合称 next-key lock,每个 next-key lock 是前开后闭区间。

死锁

当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁。

死锁的解决策略 :

  • 等待超时(默认50s)

  • 检查回滚(默认开启)

一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数 innodb_lock_wait_timeout
来设置。另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数innodb_deadlock_detect
设置为 on,表示开启这个逻辑。

主动检查死锁时,每当一个事务被锁的时候,就要看看它所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待,也就是死锁。每个新来的被堵住的线程,都要判断会不会由于自己的加入导致了死锁,这是一个时间复杂度是 O(n) 的操作。假设有 1000 个并发线程要同时更新同一行,那么死锁检测操作就是 100 万这个量级的。虽然最终检测的结果是没有死锁,但是这期间要消耗大量的 CPU 资源。因此,你就会看到 CPU 利用率很高,但是每秒却执行不了几个事务。

文章转载自小D学Java,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论