0
点赞
收藏
分享

微信扫一扫

06-全局锁和表锁

eelq 2022-01-06 阅读 83

全局锁:就是对整个数据库实例加锁

全局读锁命令:flush tables with read lock 

数据库全局读锁情况下,其他操作都不可以

使用场景:全库逻辑备份

若全库逻辑备份中不加全局锁,可能导致数据不正常

Mysql自带逻辑备份工具mysqldump,使用single-transaction参数,导数据之前会开启一个事务,保证拿到一致性视图,又因为mvcc的支持,整个过程可以进行数据更新。

一致性读这么好,为什么还要全局读锁?

一致性视图要求支持事务和特定的隔离级别,对于不支持事务的库,还是要使用全局读锁

全库只读,set global readonly =true也可以,为什么不用?

1.某些系统,readonly 的值会被用作其他逻辑,比如主从区分

2.异常处理,全局读锁,客户端发生异常,会释放锁,恢复库状态; 设置全局只读则库的不可写时间更长,风险更大

表锁:

两种:1.表锁 2.元数据锁(meta data lock, MDL)

表锁的语法:lock tables ...read/write,与全库锁一样,可以自动释放锁。lock tables除了会限制别的线程读写外,也会限制当前线程的操作对象,

元数据锁:不需要显式使用,访问一个表之前会被自动加上,MDL可以保证读写的正确性

Mysql5.5引入MDL,对一个表增删改查时加MDL读锁,对一个表结构更改时加MDL写锁

读锁之间不互斥,写锁之间互斥

给小表加字段,导致数据库挂了?

给一个表加字段,或者修改字段,或者加索引,需要扫描全表的数据,每次执行sql之前都会先加MDL读锁,若中间有修改表结构则要加MDL写锁,两者冲突,导致阻塞,后面的增删改查语句也无法获取到MDL读锁,进入阻塞;因为事务中的MDL锁,在事务提交才会释放

如何安全的给小表加字段?

1.解决长事务,事务不提交会一直占有MDL锁,可以在 information_schema 库的 innodb_trx 表中查看事务,选择暂停修改表结构,或者杀死长事务

2.若变更的表查询很频繁,可以在 alter table语句设置等待时间,规定时间内拿到MDL写锁就执行,否则放弃,防止阻塞后续操作

小结:

全局锁:若引擎都是innodb,那么最好用一致性读解决逻辑备份

表锁:一般不支持行锁才会被用到

应用程序中包含lock tables语句可能的原因:

1.使用不支持事务的引擎

2.引擎升级了,代码未更改,可以把 lock  tables 和 unlock tables 改成 begin 和 commit,问题就解决了

举报

相关推荐

0 条评论