MySQL锁有哪些??
1.MySQL锁有哪些? 什么是间隙锁?
从锁的粒度来区分:
1.行锁
加锁粒度比较小,但是资源开销比较大。InnoDB支持。
优点是锁定颗粒度很小,所以发生锁定资源争用的概率也最小,因此在在并发处理能力上面有较大的优势。
缺点是由于锁定资源的颗粒度很小,所以每次获取锁和释放锁需要做的事情也更多,带来的消耗自然也就更大了,比页级锁和表级锁消耗更多的内存。此外,行级锁定也最容易发生死锁。
-
共享锁(读锁):多个事务可以对同!a一个数据共享同一把锁。持有锁的事务可以访问数据,但是只能读不能修改。
select xxx lock in share mode
比较简单;
-
排他锁(写锁):只有一个事务可以获得排他锁,其他事务都不能获取该行的锁。Innodb会对update 、delete、insert自动添加排他锁。
使用begin开启事务,不关闭事务,因为提交事务或回滚事务就会释放锁。
select xxx for update
注:排他锁的启用,除了for update 外还有insert,update, delete
打开另一个查询窗口,对同一数据分别使用排他查和共享锁查询两种方式查询;
第一个窗口:
begin; select * from t1 where a=1 for update; -- 排他锁
第二个窗口:
select * from t1 where a=1 for update; select * from t1 where a=1 lock in share mode;
第一个窗口运行之后,第二个加锁会进行阻塞。然后一直在等待。
但是普通查询是成功的。
因为排他锁指的是一个事务在一行数据加上排他锁后,其他事务不能再在其上加其他的锁 ,但是普通查询可以,因为普通查询默认不加任何锁。
但查到的数据是修改数据之前的老数据
ps总结:一个线程进行了加排他锁,其他线程不能进行加共享或排他锁。但是普通查询可以进行读取修改前的数据。
1.select语句默认不会加任何锁类型
2.排他锁指的是一个事务在一行数据加上排他锁后,其他事务不能再在其上加其他的锁,但可以直接通过select ...from...查询数据,因为普通查询没有任何锁机制。
- 自增锁:通常针对Mysql中的自增字段,保证自增字段不会冲突。如果有事务回滚的情况,数据会回滚,但是自增序列不会回滚。
2.表锁(可以同时读,写不行)
加锁粒度大,加锁资源开销比较小。MyIsam和Innodb都支持。
- 表共享读锁:
用法: LOCK TABLE table_name [ AS alias_name ] READ
指定数据表,LOCK类型为READ即可,AS别名是可选参数,如果指定别名,使用时也要指定别名才可
而且一旦加锁,无法进行插入数据和修改数据。
CREATE table t1( a INTEGER not null, b INTEGER not null ); UNLOCK tables; lock table t1 as tone read; insert into t1 VALUES(1,3); -- > 1100 - Table 't1' was not locked with LOCK TABLES select * from t1; -- > 1100 - Table 't1' was not locked with LOCK TABLES select * from t1 as tone; -- 得到结果 update t1 set a=0 where a=1 -- > 1100 - Table 't1' was not locked with LOCK TABLES update t1 as tone set a=0 where a=1 -- > 1099 - Table 'tone' was locked with a READ lock and can't be updated UNLOCK tables; lock table t1 read; select * from t1;
综上所述,设定读锁之后就不能再进行插入和修改操作。
如果在加锁的时候使用了别名,那么select读数据的时候也需要别名才能读出数据。
如果没加别名进行的上锁操作,那么都可以直接读。
- 表排他写锁:对MyISAM表的写操作,则会阻塞其他用户对同一表的读写操作。
用法: LOCK TABLE table_name [AS alias_name] [ LOW_PRIORITY ] WRITE
别名用法与读锁一样,写锁增加了指定优先级的功能,加入LOW_PRIORITY可以指定写锁为低优先级。
CREATE table t2( a INTEGER not null, b INTEGER not null ); UNLOCK tables; lock table t2 as ttwo write; select * from t2 as ttwo; TRUE; select * from t2; FALSE; update t2 as ttwo set a=0 where a=1 TRUE; update t2 set a=0 where a=1 FALSE;
在上锁的情况下,使用别名和不使用别名的区别并不在于是否有别名,而在于锁的作用范围和查询的上下文。
当你对表 t2
使用别名 ttwo
进行锁定时,所有对 t2
的操作都必须使用这个别名 ttwo
。如果你在锁定表时使用了别名,那么在后续的查询和更新操作中也必须使用相同的别名,否则会导致操作失败。
因此:
锁分配的优先级: LOW_PRIORITY WRITE < READ < WRITE
申请锁时使用别名,使用锁定表时必须加上别名
原因:
1.有可能不能操作(查询或更新)没有被锁定的表。
例如当只申请table1的读锁,SQL语句中包含申请的表的话,那么对table2的操作是非法的。例如:
lock table t1 read; SELECT * from t2 false; reason:错误的上锁。
2.能在一个SQL中使用两次表(除非使用别名)
当SQL语句中多次使用一张表时,系统会报错。例如:
select * from t1 where a in(select a from t1) 多次使用一个表的话,需要声明多个别ming。 unlock tables; lock table t1 as tone read,t1 as ttwo read; select * from t1 as tone where a in (select a from t1 as ttwo);
- 意向锁:Innodb自动添加的一种锁,不需要用户干预。
3.页级锁 pagelevel
页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。因此,采取了折衷的页级锁,一次锁定相邻的一组记录。
页级锁定和行级锁定一样,会发生死锁。
4.全局锁
flush tables with read lock 加锁之后整个数据库都处于只读状态,所有数据变更操作都会被挂起。一般用于全局备份的时候。
参考文章: https://blog.csdn.net/weixin_38316697/article/details/106546202
常见的锁算法
user :userid(1.4.9) update user set xxx where userid=5;
1.记录锁: 锁一条具体的数据。
2.间隙锁:RR隔离级别下,会加间隙锁。锁一定的范围,不锁具体的记录。
3.Next-key:间隙锁+右记录锁。
锁的机制非常复杂,可以深入了解的地方。
本文来自博客园,作者:七七喜欢你,转载请注明原文链接:https://www.cnblogs.com/EternalX/p/18366411
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 从 Windows Forms 到微服务的经验教训
· 李飞飞的50美金比肩DeepSeek把CEO忽悠瘸了,倒霉的却是程序员
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee