MySql五:锁

锁设计的初衷:解决Mysql并发访问的问题,当出现并发访问问题时,数据库就要合理地控制资源的访问规则。
锁的分类:全局锁、表锁和行锁。
全局锁
顾名思义,全局锁的作用范围是整个数据库,全局锁的命令为Flush tables with read lock (FTWRL),使用该命令后,整个数据库将只处于只读状态,即DML和DDL操作不能进行。
全局锁的典型使用场景:用于数据库全库逻辑的备份,但是让全库都处于 只读状态这样是危险的
1.如果在主库上备份,那么备份期间就不能进行任何更新,整个业务都处于停止状态
2.如果在从库上备份,那么在主库上的binlog日志就不会被同步更新到从库上,导致主从延迟
根据上述描述来看,全局锁似乎并没有必要,但是从另一种角度来看全局锁又是必要的。如果不加全局锁的话在备份过程中对数据库进行操作,备份系统备份的得到的库不是一个逻辑时间点,这个视图是逻辑不一致的。那么该如何拿到一致性的视图,可以在“可重复读”隔离级别中拿到一致性的视图,该隔离级别中事务启动时是静态的,不受其他事务更新的影响。
官方自带的逻辑备份工具是 mysqldump。当 mysqldump 使用参数–single-transaction 的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。而由于 MVCC 的支持,这个过程中数据是可以正常更新的。对于引擎全是InnoDB引擎的库,可以适用这个备份工具。
那么我们是否还需要全局锁?答案是肯定的,事务隔离级别是由引擎支持的,如果引擎不支持这个隔离级别,在备份过程中发生了更新的话,总是读取到最新的数据, 这样就破坏了一致性。
既然我们只需要全库只读,那么能不能用set global readonly=true 的方式呢,二者相比FTWRL有以下两个优势
一是,在有些系统中,readonly 的值会被用来做其他逻辑,比如用来判断一个库是主库还是备库。因此,修改 global 变量的方式影响面更大,我不建议你使用。
二是,在异常处理机制上有差异。如果执行 FTWRL 命令之后由于客户端发生异常断开,那么 MySQL 会自动释放这个全局锁,整个库回到可以正常更新的状态。而将整个库设置为 readonly 之后,如果客户端发生异常,则数据库就会一直保持 readonly 状态,这样会导致整个库长时间处于不可写状态,风险较高。
表级锁
MySQL 里面表级别的锁有两种:一种是表锁,一种是元数据锁(meta data lock,MDL)。
表锁的语法是 lock tables … read/write。与 FTWRL 类似,可以用 unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。需要注意,lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。
lock table t1 read t2 write,限制表t1只读,t2读写。意味着其它线程不能对t1进行写操作,也不能对t2进行读写操作,同样地,在释放锁之前,该线程也不能对t1进行读写操作,自然也不能访问其它的表。
事务中的 MDL 锁,在语句执行开始时申请,但是语句结束后并不会马上释放,而会等到整个事务提交后再释放。
另一类表级的锁是 MDL(metadata lock)。MDL 不需要显式使用,在访问一个表的时候会被自动加上。MDL 的作用是,保证读写的正确性。
读锁之间不互斥,意味着多个线程可以对表实行增删改查的操作。读锁和写锁,写锁和写锁之间是互斥的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值