一不小心走光了,和浩宸聊一聊数据库的锁。

一不小心走光了,和浩宸聊一聊数据库的锁。

引入背景

周六,浩宸在卫生间洗澡,然后我没注意,一下推门进去了,浩宸这样走光了,场面顿时尴尬。原来是锁坏了。这时候就提现了锁的重要性。

为什么要引入锁

在日常生活中,我们会共享卫生间,关门上锁可以保护我们的隐私。在数据库中锁同样是为并发所设计的。使用锁可以保证线程的安全性。

锁的分类

锁按粒度可以分为
! 全局锁
!! 表锁 , 元数据锁(meta data lock)
!!! 行锁

全局锁

全局锁从字面上看 就是锁库的锁。加上这把锁之后所有写的操作都将不能执行(增删改的操作,创建表和修改表结构的操作,提交事务的操作)

语法:flush table with read lock 

使用场景:整库备份逻辑备份 。就是把整库的每个表都select出来存成文本。

在这里插入图片描述
让整库只读,岂不是很危险。
这里具体来描述一下
如果在主库上备份,那么在备份期间不能进行写的操作,整个业务将会停摆。
如果在从库上备份,那么在备份期间从库不能执行主库同步过来的binlog 会导致主从延迟。
在这里插入图片描述
为什么备份要加锁呢?
那是因为如果不加锁 备份系统备份的库不是一个逻辑时间点,视图不一致。
如何进行备份?
官方自带的逻辑备份工具mysqldump 当mysql使用参数single-transaction到数据之前会启动一个事务,来确保拿到一致性视图,由于mvcc的支持,备份的过程中,数据是可以正常更新的。
有了这个功能为什要引入ftwrl呢?
这就和数据库的存储引擎有关系了。对于MyISAM这种不支持事务的引擎,如果备份过程中有更新,总是 只能取到最新的数据,那么就破坏了备份的一致性。这时,我们就需要使用FTWRL命令了。所以,single-trasaction方法适用于所有表使用事务引擎的库。如果有的表使用了不 支持事务的引擎,那么备份就只能通过FTWRL方法。

说到这里浩宸就提出疑问了,既然是全局可读。为什么不用set globle readonly=true.
1)在有些系统中,readonly的值会被用来做其他逻辑,比如用来判断一个库是主库还是备 库。因此,修改global变量的方式影响面更大,不建议使用
2)在异常处理机制上有差异。如果执行FTWRL命令之后由于客户端发生异常断开,那么 MySQL会自动释放这个全局锁,整个库回到可以正常更新的状态。而将整个库设置为 readonly之后,如果客户端发生异常,则数据库就会一直保持readonly状态,这样会导致整个 库长时间处于不可写状态,风险较高。

表锁,元数据锁(meta data lock)

表锁的语法:lock tables …read/write
lock tables语法除了会限制别的线程的读写 外,也限定了本线程接下来的操作对象。
MDL不需要显式使用,在访问一个表的时候会被 自动加上。MDL的作用是,保证读写的正确性。
在MySQL 5.5版本中引入了MDL,当对一个表做增删改查操作的时候,加MDL读锁;当 要对表做结构变更操作的时候,加MDL写锁。
! 读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。
!! 读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线 程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。

猜你喜欢

转载自blog.csdn.net/OnlyoneFrist/article/details/107636793