暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL锁介绍

数据库笔记 2019-12-04
1024


MySQL根据加锁的范围,mysql锁大致可分为全局锁,表锁,行锁


全局锁

全局锁就是对整个数据库实例加锁,可以通过flush table with read lock(ftwrl)实现加全局锁。加锁后,其他线程的ddl,dml操作将被阻塞。

全局锁最典型的使用场景是全库逻辑备份。

设置全局锁风险:

  1. 如果在主库上设置,则加锁期间所有dml,ddl操作均不能执行,业务处于停滞状态

  2. 如果在从库上设置,则加锁期间同步过来的binlog均不能apply,复制延迟不断增大

官方的逻辑备份工具是mysqldump,在全库备份时会为了保证一致的逻辑备份时间点,会设置全局锁。后续可以通过--single-transaction参数避免设置全局锁。会在数据导出之前开启一个事务来保证一致性视图,并通过mvcc的支持,保证期间数据可以正常更新。当然该参数仅对支持事务的引擎有效。


那么ftwrl与set global read_only=true的区别是?

  1. 在某些系统中,read_only会被作为判断主库或从库的依据之一,因此修改global参数的影响面更大。

  2. 在异常处理机制上有差异。执行ftwrl命令的客户端如果异常断开,mysql会自动释放全局锁,数据库会回到可以正常更新的状态。而设置read_only=true,即使客户端异常断开,数据库仍然处于只读模式,会导致整个库长期处于不可写状态。


表级锁

mysql表级锁分为两种,表锁和元数据锁(MDL meta data lock)


表锁

表锁的语法是lock tables read/write。与ftwrl类似。可以用unlock tables解锁也可以在客户端断开时自动释放锁。需要注意的是lock tables语法除了限制别的线程读写外,也限制了本线程接下来的操作。


元数据锁

MDL锁不需要显式的使用,在访问一个表的时候会自动加上。MDL锁的作用是防止DDL和DML并发的冲突,保证读写的正确性。防止正在读写某张表时,表结构被另一个线程变更。

当对表进行增删改查操作时,加MDL读锁。当对表进行表结构变更操作时,加MDL写锁。

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

  • 读写锁之间,写锁之间互斥,用来保证变更表结构操作的安全性。


意向锁

为了支持行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。(可以简单理解为支持并发DDL和DML互不冲突)


意向共享锁(IS)

事务打算给数据行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。

意向排他锁(IX)

事务打算给数据行加排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。



行锁

行锁应用于innodb存储引擎,行锁主要分为共享锁(S)和排他锁(X)。


共享锁

当一个事务对某行或某些行加了共享锁,在该事务结束期间,其他事务对其只能进行读操作,不能进行写操作。

用法:SELECT `id` FROM  table WHERE id in(1,2) LOCK IN SHARE MODE


排他锁

当一个事务对某行或某些行加了排他锁,在该事务结束期间,其他事务不能对其加任何锁。

用法:SELECT `id` FROM mk_user WHERE id=1 FOR UPDATE



PS:


文章转载自数据库笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论