MySQL中的“锁事”之全局锁、表级锁和行锁

27 篇文章 0 订阅
4 篇文章 0 订阅

直入正题,数据库中根据加锁的范围大致可以分为全局锁表级锁行锁三大类。

全局锁
全局锁,从名字就能知道其含义,就是对整个数据库实例进行加锁,mysql中可以通过Flush tables with read lock(FTWRL)来对数据库加锁,使得数据库处于只读状态。

应用场景:做全库逻辑备份应用。

引发的问题:1、主库上备份,导致数据库在备份期间都只能做只读操作,不能做更新之类的其他操作,会使业务进入停摆。
2、从库备份:备份期间从库不能执行从主库同步过来的binlog,导致主从延迟

mysqldump:官方自带的逻辑备份工具,在使用参数-single-transaction的时候,更新的时候会启动一个事务,拿到一致性视图。由于MVCC的支持。所以在这个过程中,进行例如更新等操作是没有问题的。

但是既然有这个功能,那FTWRL的存在是因为什么呢?
那是因为并不是所有存储引擎都支持事务的,比如MyISAM就是不支持事务。

set global readonly = true
众所周知,这种方式也可以让全库进入只读状态。那么这种方式和FTWRL之间该如何做取舍呢?
这个时候,我们来看readonly可能引发的问题

  1. 对数据库异常,readonly和FTWRL的处理方式是有差异的。FTWRL下如果客户端异常断开,Mysql会自动释放这个全局锁。readonly则不会,如果数据库发生异常,就会一直保持readonly状态,这样会导致整个库长期不可写。
  2. 在某些系统,readonly的值被作为其他逻辑,比如判断一个库是主库还是从库。修改global变量的方式影响面比较大,所以要小心使用。

表级锁
表级锁的分类:

  • 表锁
    语法:lock tables … read/write,可通过unlock tables主动释放锁,客户端断开的时候也会自动释放锁。lock tables 不仅会限制其他线程操作,也会限制自身操作。比如:线程1执行 Lock tables T1 read,T2 write,语句,这个时候其他线程不能写T1,读写T2都会被阻塞。而线程1本身就只能读T1,读写T2。

  • 元数据锁(MDL)(防止DDL和DML冲突)
    这个锁不需要显示使用,访问表的时候会自动被加上。这个锁的作用是保证读写的正确性。在两种情况下会加这个锁:1、对一个表进行增删改查操作的时候,会加MDL读锁。2、对表的结构进行更改的时候,会加MDL写锁
    MDL读锁之间是不互斥的,所以可以有多个线程对同一个表进行增删改查。
    MDL写锁与读锁之间、写锁与写锁之间是互斥的,当一个线程对一个表的结构进行修改,这个时候其他线程必须要等到这个线程对这个表修改完成。
    关于如何给一个小表加字段的考虑:首先解决长事务,事务不提交的话,会一直占用MDL锁,假设占用的是MDL读锁,这个时候再申请MDL写锁,MDL写锁就会被阻塞掉。MDL写锁被阻塞掉的话问题就大了,后来再申请的写锁和读锁都会被阻塞,表就会变得完全不能读写。其次可以在DDL语句中设定等待时间。如果在指定时间内没有获取MDL写锁,就主动放弃,防止阻塞其他锁。

InnoDB的行锁

两阶段锁:在InnoDB中,行锁是在需要的时候才加上的,但是并不是不要了就立即释放,而是要等待事务结束才释放,这就是两阶段协议。所以在这里要考虑一个问题,在事务A中如果要锁住多个行,把最可能影响并发度的锁放在较后,这个可以减少锁等待时间,提高并发度。

死锁和死锁检测:首先先来看看引发死锁的情况,如下图:

在这里插入图片描述

事务A等待事务B持有的id为2的行锁,事务B等待事务A持有的id为1的行锁,互相等待对方资源释放,就会进入死锁状态。

解决死锁的两种策略:

  1. 设置innodb_lock_wait_timeout超时参数
  2. 发起死锁检测,发现死锁后,主动回滚死锁链中的一个事务,使得其他事务能够继续执行。可以通过将参数innodb_deadlock_timeout设置为on来开启这个逻辑。

这两种方式的利与弊

  1. 第一种设置超时参数,这个参数设大还是小都是比较难搞的,设大了,锁等待时间会很长,设小了,正常的锁等待如何处理呢?
  2. 普遍来说死锁检测用的比较多,本身来说死锁检测就是默认为on的,这种方式可以避免上述所说的超时参数的不足。但是死锁检测需要占用较多的cpu资源,如果并发很大的情况下,将会耗费大量的cpu资源。

可以看到这两种方式都有其不足之处,对于死锁检测的问题,有两种算是没有办法中的办法。第一种在自己明确不会出现死锁的情况下,关掉死锁检测。第二种,控制并发度(主要方向)。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值