全局锁和表锁 :给表加个字段怎么有这么多阻碍?

1)数据库为什么要设计锁?

  • 处理并发问题,因为数据库是共享资源

2)根据加锁的范围,mysql里面的锁有哪几种?

  • 全局锁

  • 表锁

  • 行锁

3)全局锁

what?

  • 对整个数据库实例加锁

why?

  • 优点:防止在备份期间有业务修改数据库的数据,导致问题的出现。

how?

  • 让整个库只读的命令:Flush tables with read lock

  • 释放锁:unlock tables

应用场景?

  • 做全库逻辑备份 ,把整库每个表都 select 出来存成文本。

3.1)全局读锁存在哪些问题?

  • 如果你在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆;

  • 如果你在从库上备份,那么备份期间从库不能执行主库同步过来的 binlog,会导致主从延迟。

3.2)既然我们全局读锁备份时业务停摆,那有没有什么解决方案,让业务不停摆又能让备份的逻辑一致?

  • mysql官方逻辑备份工具mysqldump。使用的时候加上参数–single-transaction。导数据之前就会启动一个事务,来确保拿到一致性视图。而由于 MVCC(多版本并发控制) 的支持,这个过程中数据是可以正常更新的。

3.3)既然mysqldump做备份这么好用,那干嘛还要FTWRL命令?

  • mysqldump是需要引擎有事务支持的,而mysql自带的引擎MYISAM是不支持事务的。

3.4)既然备份过程中要全库只读,那为什么不可以用set global readonly=true命令呢?

  • 有些系统中,readonly 的值会被用来做其他逻辑,比如用来判断一个库是主库还是备库。

  • 在异常处理机制上有差异

    • FTWRL 命令执行后客户端异常断开,MySQL 会自动释放这个全局锁,业务可正常运行。

    • readonly执行后客户端发生异常则数据库会呆呆的保持只读状态

     

4)表级锁

what?

  • 锁的范围是表,有两种

    • 表锁

    • 元数据锁(meta data lock,MDL)。

why?

  • 没有出现更细粒度的锁的时候,表锁是最常用的处理并发的方式

how?

  • 表锁的语法:lock tables … read/write

  • 释放表锁:unlock tables/客户端断开自动释放

  • 元数据锁是自动挡,在访问一个表的时候被自动加上。mysql5.5版本之中引入的。

    • 对表内容增删改查时:加MDL读锁

    • 对表结构变更时:加MDL写锁

4.1)为什么对表内容增删改查加读锁而对表结构变更时加MDL写锁?

  • 读锁之间不互斥,因此可以有多个线程同时对一张表增删改查

  • 读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。

4.2)InnoDB引擎为什么不用表锁Lock tables来控制并发?

  • InnoDB引擎有粒度更细的行锁,当然用行锁。

4.3)因为MDL锁机制我们修改一个小表而导致整个库挂了的教训?

全局锁和表锁 :给表加个字段怎么有这么多阻碍?

 

 

 

AB是更新表内容,所以会自动加上MDL读锁,他们可以并发执行的。而我们的C是改变表结构,需要加上MDL写锁,但是此时MDL正在忙AB的事,没空理C,C就阻塞了,然后D是读表内容,申请MDL读锁,但是要在C基础上。也跟着遭罪被阻塞,后面一直遭罪堵着,就是因为C。

也就是说我们现在t这张小表因为C这个害群之马不能读了,假如我几万个用户要来读这张表,这个库的线程很快就爆满挂掉。

4.4)事务中的MDL锁有什么特点?

  • 语句执行开始时申请,但是语句结束后并不会马上释放,而是要等到事务结束。

4.5)如何安全地给小表加字段?

  • 首先我们要解决长事务,事务不提交,MDL锁不释放。先去information_schema 库的innodb_trx 表中看看有没有长事务正在执行,要么让它先执行完,或者干掉kill它。那我就可以正常给小表加字段。

4.6)假如一个小表频繁被用户用着,那我怎么加一个必须加的字段?

  • 这个时候kill也没用,因为下一个请求马上就来,杀不完的。

  • 在 alter table 语句里面设定等待时间,在这个时间内如果能见缝插针拿到MDL锁最好,拿不到就放弃,业务优先。之后再通过重试命令重复这个过程。

4.7)在mysql中4.6的操作是怎样实现的?

  • MariaDB 已经合并了 AliSQL 的这个功能,所以这两个开源分支目前都支持 DDL NOWAIT/WAIT n 这个语法。

     ​
     ALTER TABLE tbl_name NOWAIT add column ...
     ALTER TABLE tbl_name WAIT N add column ...

4.8)假如你发现你的应用程序里有 lock tables 这样的语句,有哪些可能的情况?

  • 你的系统现在还在用 MyISAM 这类不支持事务的引擎,那要安排升级换引擎

  • 你的引擎升级了,但是代码还没升级。最后业务开发就是把 lock tables 和 unlock tables 改成 begin 和 commit,问题就解决了。

4.8.1)为什么把lock tables 和 unlock tables 改成 begin 和 commit问题就解决了?

  • 原本需要用到表锁的场景都可以直接用事务替代,因为事务自动添加 MDL 锁,MDL 锁能够区别对待表结构的修改和普通增删改查,粒度更细。

上一篇:Laya页面嵌套和Scene.destory导致的Bug


下一篇:BUUCTF WEB HCTF 2018 WarmUp