锁是计算机协调多个线程访问同一共享资源的机制,主要用于解决多线程访问同一共享资源的并发安全问题。
(1)从性能分为:乐观锁和悲观锁
MySQL中采用版本号控制,JVM中使用CAS
(2)从数据库操作类型分为:读锁(共享锁)、写锁(排他锁) 【读锁和写锁都属于悲观锁】
(3)从颗粒度划分为,表锁和行锁
注意:
(1)读锁、写锁都属于行级锁,即事务1 对商品A 获取写锁,和事务2对商品B 获取写锁互相不会阻塞的。
(2)如果sql语句使用了行锁,当SQL未使用索引而使用全表扫描的时候,行级锁会变成表锁。
(3)锁只有在执行commit或者rollback的时候才会释放,并且所有的锁都是在同一时刻被释放。
(4)Innodb引擎执行普通的修改、删除sql语句时,会给修改和删除的行加行锁。
事务A使用共享锁获取了某条(或某些)记录时,事务B可以读取这些记录,可以继续添加共享锁,但是不能修改这些记录(当事务C对这些数据修改或删除时,会进入阻塞状态,直至锁等待超时或者事务A提交)
# 加锁
SELECT ... LOCK IN SHARE MODE
# 释放锁
commit;
rollback;
作用
SELECT … LOCK IN SHARE MODE在读取的若干行记录加共享锁(share lock),其他事务只能对这些行查询而不能修改这些记录。多个事务可以对相同的行记录加共享锁,因此获取了共享锁的事务不一定能修改行数据
使用场景: 读取结果集的最新版本,同时防止其他事务产生更新该结果集
例如:并发下对商品库存的操作
select … for update在对读取的行记录加排他锁,只允许获取到该排他锁的事务修改该行记录,防止其他事务对该行进行修改,就像普通的update语句执行时会加行锁一样。
# 加排他锁
select ... for update //排他锁
# 释放锁
commit;
rollback;
(1)一旦某个事务获取了排他锁,其他事务就无法再获取排他锁。
多个事务可以对相同行数据加共享锁。
(2)给指定行加了共享锁的事务,不一定能修改该行数据,因为其他事务也可能对该行加了共享锁或排他锁; 给指定行加了排他锁的事务,则可以修改加了排他锁的该行数据
使用表级锁定的主要是MyISAM,MEMORY,CSV等一些非事务性存储引擎。
表锁一般在数据迁移时使用。
某行加共享锁的前提是:该行数据所在表会先获取到意向共享锁。
某行加排他锁的前提是:该行数据所在表会先获取到意向排他锁。
注意:意向共享锁和意向排他锁均是表锁,无法手动创建。
意向锁是为了告知mysql该表已经存在数据被加锁,而不需要逐行扫描是否加锁,提搞加锁的效率。
lock tables saas.goods read,saas.account write; // 给saas库中的goods表加读锁,account表加写锁
unlock tables; //解锁
FLUSH TABLES WITH READ LOCK; // 所有库所有表都被锁定只读
unlock tables; //解锁
注意: 在客户端和数据库断开连接时,都会隐式的执行unlock tables。如果要让表锁定生效就必须一直保持连接。
上图中where条件中,虽然template_name建立普通索引,但使用or关键字,导致template_name的索引失效,从而进行了全表扫描,锁定了整张表。
窗口1中删除某一行,但没有提交。窗口2中更新该行会一直处于阻塞中。
间隙锁的目的是为了防止幻读,其主要通过两个方面实现这个目的:
(1)防止止间隙内有新数据被插入
(2)防止范围内已存在的数据被更新
(1)数据隔离级别必须为可重复读
(2)检索条件必须使用索引(没有使用索引的话,mysql会全表扫描,那样会锁定整张表所有的记录,包括不存在的记录,此时其他事务不能修改不能删除不能添加)
根据检索条件向左寻找最靠近检索条件的记录值A,作为左区间,向右寻找最靠近检索条件的记录值B作为右区间,即锁定的间隙为(A,B)。下图中,where number=5的话,那么间隙锁的区间范围为[4,11];
session 1:
start transaction ;
触发间隙锁的方式1:
select * from news where number=4 for update ;
触发间隙锁的方式2:
update news set number=3 where number=4;
session 2:
start transaction ;
insert into news value(2,4);#(阻塞)
insert into news value(2,2);#(阻塞)
insert into news value(4,4);#(阻塞)
insert into news value(4,5);#(阻塞)
insert into news value(7,5);#(执行成功)
insert into news value(9,5);#(执行成功)
insert into news value(11,5);#(执行成功)
next-key锁其实包含了记录锁和间隙锁,即锁定一个范围,并且锁定记录本身。InnoDB默认加锁方式是next-key 锁。
select * from news where number=4 for update ;
next-key锁锁定的范围为间隙锁+记录锁,即区间(2,4),(4,5)加间隙锁,同时number=4的记录加记录锁,即next-key锁的锁定的范围为(2,4],(4,5]。
update news set number=0 where id>15
sql默认加的是next-key锁。根据上图,next-key锁的区间为(-∞,1],(1,5],(5,9],(9,11],(11,+∞),上面id>15,实际上next-key锁是加在[11,+∞)这个范围内,而不是(15,+∞)这个范围内。注意:需要使用锁的字段必须加索引,因为锁是加在索引上的,没有索引则加的表锁。
非ES6代码实现继承的主流方式主要可以分为: 构造继承、原型链继承、构造继承+原...
问题 如果打算为项目选择一款免费、开源的 数据库 ,那么你可能会在 MySQL 与Pos...
伪静态:即网站本身是动态网页如.php、.asp、.aspx等格式,而这类网页还带“”加...
分享背景 由于一直在虚拟机的状态下开发PHP,尝试一下mac本地搭建环境.mac本身是...
注入获取 注入获取通过IConfiguration直接获取的方法官方文档里就有,可以直接看...
1.如果你连追求自己喜欢的事物与人的勇气都没有,你注定是个失败者。 2.不要因...
前言 最近在阅读某开源框架源码的时候,发现作者在其中运用了很多 Action委托 和...
了解类似的获取字符位置的方法: charAt() 获取字符串指定位置的字符 用法:strO...
分析可能是: asp的一些保留字段导致,具体的大家可以参考这篇文章: ASP常见的...
HTML常用meta 文章目录 HTML常用meta Meta(元数据) 提示以下是本篇文章正文内容...