全局锁

  整个库加个锁
命令:Flush tables with read lock (FTWRL),该命令可以禁止后续的DDL和DML语句
mysqldump备份使用参数-single-transaction,在导数据的时候就启动一个事务,确保拿到一致性视图,一致性读的前提是引擎为innodb引擎;不会对整库加锁,避免 了备份时无法更新数据的问题

表级锁

表锁和元数据锁

表锁

  加锁:lock tables ... read/write -> 加锁的时候相应的线程只能进行相应的读写操作不能进行锁规定之外的其他操作
  解锁:unlock tables

元数据锁(MDL)

  加锁:不需要显式的使用,在访问一个表的时候会被自动加上,当对一个表做增删查改的时候,加MDL读锁,表结构变更时,加MDL写锁。
  释放:事务提交
  特点:读锁之间不互斥,读写锁和写锁之间互斥。

行锁

  在Innodb事务中,行锁是在需要的时候加上的,等事务结束(提交/回滚)的时候才释放。
  当并发系统出现循环资源竞争的时候,会出现死锁,
  解决方案:1.通过innodb_lock_wait_timeout设置超时等待时间,过了等待时间就释放锁
2.通过innodb_deadlock_detect参数设为on开启死锁检测
死锁检测导致的问题:
  当有大量请求进来同时更新同一行的时候,会进行循环死锁检测,这样就模拟出了"死锁情况",会出现事务处理不大,但大量消耗cpu资源。
解决死锁检测导致的问题:
  业务层面控制不会出现死锁,控制并发度,对操作同一行的事务进行排队

隔离级别下的加锁分析


Q1:能解释下online ddl是怎么执行的吗?

A1:1. 拿MDL写锁 2. 降级成MDL读锁 3. 真正做DDL 4. 升级成MDL写锁 5. 释放MDL锁

Q2:对热点表执行DDL语句的时候,怎么保证其他事务不被阻塞?

A1:执行DDL的时候会拿到MDL写锁,写锁之后的操作都会被阻塞,且如果DDL事务没有提交的话,会一直阻塞下去,当请求线程打满的时候容易造成数据库奔溃 解决方案:监控information_schema的innodb_trx表,检查到长事务就停掉;执行alter语句的时候使用nowait/wait n语法,在一定时间内获取不到DDL写 锁的时候直接释放掉。

Q3:一个事务中需要锁多个行,怎么提高执行效率?

A3:将最可能造成冲突和最能影响并发度的锁申请时机尽量往后放。