文章目录
数据库锁
文章目录
为什么需要数据库锁呢?其实就是为了解决并发的一些问题;锁保证了并发下数据访问的规则性和合理性!
根据加锁的范围,MySQL里面的锁大致可以分为全局锁、表级锁、行锁;
1. 全局锁
加全局锁命令:flush table with read lock;(FTWRL)
mysql> flush table with read lock;
Query OK, 0 rows affected (0.05 sec)
释放全局锁命令:unlock tables;
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
1. 全局锁的特点
-
全局锁让整个数据库(所有表)处于只读状态,使用这个命令后,数据库表的增删改(DML)、表结构的更改(DDL)、更新类事物的提交都会被阻塞;
例如下面,前面我已经给该数据库加上了全局锁,此时对其中一个表进行查询和插入操作:
mysql> select * from test; +----+------+-----------+ | id | name | adress | +----+------+-----------+ | 1 | yy | ChongQing | | 2 | lch | XiAn | +----+------+-----------+ 2 rows in set (0.00 sec) mysql> insert into test values('yyg','zhongxian'); ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock
可以看到,查询是允许的,而插入是禁止的;
2. 全局锁的作用(全库逻辑备份)
上面看到了全局锁会让数据库只处于可读的状态,这种状态会使数据库处于一个多么低效率的状态,那么为什么还需要它呢?
低效率的原因:
- 如果你在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆;
- 如果你在从库上备份,那么备份期间从库不能执行主库同步过来的binlog,会导致主从延迟;
因为在以前,全局锁的主要作用就是:做全库逻辑备份;
即在备份的时候,加上全局锁,让表只处于可读状态,处于这种
那么为什么这么做呢?即为什么需要在备份的时候加全局锁呢,这里用反证法来证明:
案例: 假如一个商城里有两张表,一张用户所购商品表,一张是用户余额表,假如在备份商品表刚完成还没开始备份用户余额表的时候,一位用户购买了某个产品,此时它的余额扣除成功,然后备份了用户余额表,这时造成的现象就是:备份的商品表没有用户买的那个商品,但备份的余额表却扣除了钱;
假如是备份完余额表,用户下单,再备份商品表的话,结果就是:用户的余额没扣,却多了商品;
上面的案例说明了,在做全库逻辑备份的时候,如果不加锁,会造成备份得到的库里面的表不是一个逻辑时间点 ,这个视图是逻辑不一致的;那么提到这,对于视图一致性,事物的可重复读这个隔离性不就能够实现吗;所以官方自带逻辑备份工具是mysqldump。当mysqldump使用参数-single-transaction的时候,导数据之前就会启动一个事物,来确保拿到一致性视图。而由于MVCC的支持,这个过程中数据是可以正常更新的;
那么,有了mysqldump这个功能,为什么还需要FTWRL?(⭐)
因为mysqldump是基于事物的,而有些引擎不支持事物,比如MyISAM,这种引擎在做全库逻辑备份的时候就只能使用全局锁了;
对于全库只读,还有一种方式可以实现:
set global readonly = true
那么到底使用set的方式还是使用FTWRL的方式来进行全库逻辑备份呢?这里有两个原因推荐使用FTWRL:
- 1.在有些系统里,readonly的值会被用来做其他逻辑,比如用来判断一个库是主库还是备库,因此修改global变量的影响比较大,不建议使用;
- 2.两者在异常处理机制上有差异:
- 执行FTWRL命令之后由于客户端的发生异常断开,那么MySQL会自动释放这个全局锁,整个库可以回到正常更新的状态;
- 执行set global这个方式的话,如果客户端发生异常,则数据库还是一直会保持只读状态,这样会导致整个库长时间处于不可写状态,风险较高;
2. 表级锁
MySQL里面表级别的锁分两种:
- 表锁
- 元数据锁(mete data lock,MDL)
1. 表锁
加锁命令: lock table 表名 read/write
mysql> lock table test read;
Query OK, 0 rows affected (0.00 sec)
释放锁的命令:unlock tables;
1. 特点
-
当还没有出现更细粒度的锁时,表锁是常用的处理并发问题的方式,而对于InnoDB这种支持