一、全局锁:对整个数据库实例加锁,命令是 Flush tables with read lock (FTWRL)
全局锁的典型使用场景是,做全库逻辑备份,必须保证全库是只读的状态
整库只读缺点:
- 如果你在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆;
- 如果你在从库上备份,那么备份期间从库不能执行主库同步过来的 binlog,会导致主从延迟。
全库只读的方式:
- 官方自带的逻辑备份工具是 mysqldump,使用参数–single-transaction 的时候,导数据之前就会启动一个事务,要求执行引擎必须是支持事务的
- 不支持事务的执行引擎只能使用 FTWRL (Flush tables with read lock)
- set global readonly=true的方式
set global readonly=true的方式 缺点:
-
一是,在有些系统中,readonly 的值会被用来做其他逻辑,比如用来判断一个库是主库还是备库。因此,修改 global 变量的方式影响面更大,我不建议你使用。
-
二是,在异常处理机制上有差异。如果执行 FTWRL 命令之后由于客户端发生异常断开,那么 MySQL 会自动释放这个全局锁,整个库回到可以正常更新的状态。而将整个库设置为 readonly 之后,如果客户端发生异常,则数据库就会一直保持 readonly 状态,这样会导致整个库长时间处于不可写状态,风险较高。
二、表级锁
MySQL 里面表级别的锁有两种:一种是表锁,一种是元数据锁(meta data lock,MDL)。
表锁的语法是 lock tables … read/write,innodb支持行级锁,一般不会采用此方式,
另一类表级的锁是 MDL(metadata lock)。MDL 不需要显式使用,在访问一个表的时候会被自动加上,因此,在 MySQL 5.5 版本中引入了 MDL,当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。
- 读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。
- 读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。
MDL潜在危险:给一个小表加个字段,导致整个库挂了。
案例:一个sessionA 对T表进行读取,添加mdl读锁,接下来sessionB进行读是可以正常读取的,sessionC 需要mdl 一个写锁,因A 没释放所以被阻塞,但是接下来sessionD 只是需要获取读锁的话也会被阻塞,导致之后的所有操作都会完全不可读写,如果这个表示需要频繁操作的表,整个库的线程会很快爆满。简单说就是违背上面的 读锁之前不互斥的原则。
还有一点就是 事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。
如何安全地给小表加字段?
- information_schema 库的 innodb_trx 表中查看是否有长事务,如果有要不暂停DDL,要不kill掉长事务
- 如果该表的请求很频繁,在alter table 后面加上等待时间,nowait/wait n ,拿不到不会阻塞,
ALTER TABLE tbl_name NOWAIT add column ...
ALTER TABLE tbl_name WAIT N add column ...
三、行锁
MyISAM 引擎就不支持行锁,
两阶段锁协议:在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放。
所以在使用事务中,如果你的事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。最大程度地减少了事务之间的锁等待,提升了并发度。
死锁和死锁检测
死锁:当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态。
优化死锁的策略
- 一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数 innodb_lock_wait_timeout 来设置。默认50s,一般不会采用,
缺点:(1)超时时间过长导致无法接受(2)超时时间过短导致很多误伤
- 另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为 on,表示开启这个逻辑。
缺点:每个新来的被堵住的线程,都要判断会不会由于自己的加入导致了死锁,检测的代 价是比较昂贵的,并发线程高的情况下要消耗大量的 CPU 资源。
针对缺点处理思路:控制并发度,建议在中间件或者服务器端控制,或者是采用扽断汇总 的方式,先逻辑计算在更新到数据库,