Mysql锁是什么?锁有哪些类别?
锁定义
同⼀时间同⼀资源只能被⼀个线程访问
update test set a=a-1 where id=100 and a> 0;
update test set a=a-1 where id=100 and a> 0;
在数据库中,除传统的计算资源(如
CPU
、
RAM
、
I/O
等)的争⽤以外,数据也是⼀种供许多⽤户
CPU
、
RAM
、
I/O
等)的争⽤以外,数据也是⼀种供许多⽤户
共享的资源。如何保证数据并发访问的⼀致性、有效性是所有数据库必须解决的⼀个问题,锁冲突
也是影响数据库并发访问性能的⼀个重要因素。
锁的分类
从对数据操作的类型分法(读或写)
读锁(共享锁):
针对同⼀份数据,多个读操作可以同时进⾏⽽不会互相影响。
针对同⼀份数据,多个读操作可以同时进⾏⽽不会互相影响。
写锁(排它锁):
当前写操作没有完成前,它会阻断其他写锁和读锁。
当前写操作没有完成前,它会阻断其他写锁和读锁。
从对数据操作的粒度分法
表级锁:
表级锁是
MySQL
中锁定粒度最⼤的⼀种锁,表示对当前操作的整张表加锁
表级锁是
MySQL
中锁定粒度最⼤的⼀种锁,表示对当前操作的整张表加锁
⾏级锁:
⾏级锁是
Mysql
中锁定粒度最细的⼀种锁,表示只针对当前操作的⾏进⾏加锁
⾏级锁是
Mysql
中锁定粒度最细的⼀种锁,表示只针对当前操作的⾏进⾏加锁
⻚级锁:
⻚级锁是
MySQL
中锁定粒度介于⾏级锁和表级锁中间的⼀种锁,⼀次锁定相邻的⼀组记
⻚级锁是
MySQL
中锁定粒度介于⾏级锁和表级锁中间的⼀种锁,⼀次锁定相邻的⼀组记
录
从并发⻆度的分发
—
实际上乐观锁和悲观锁只是⼀种思想
—
实际上乐观锁和悲观锁只是⼀种思想
悲观锁
:对数据被外界(包括本系统当前的其他事务,以及来⾃外部系统的事务处理)修改持保守
:对数据被外界(包括本系统当前的其他事务,以及来⾃外部系统的事务处理)修改持保守
态度(悲观
)
,因此,在整个数据处理过程中,将数据处于锁定状态。
)
,因此,在整个数据处理过程中,将数据处于锁定状态。
乐观锁
:乐观锁假设认为数据⼀般情况下不会造成冲突,所以在数据进⾏提交更新的时候,才会正
:乐观锁假设认为数据⼀般情况下不会造成冲突,所以在数据进⾏提交更新的时候,才会正
式对数据的冲突 与否进⾏检测,如果发现冲突了,则让返回错误信息再进⾏业务重试
其他锁:
间隙锁
:在条件查询中,如:
where id>100
,
InnoDB
会给符合条件的已有数据记录的索引项加
:在条件查询中,如:
where id>100
,
InnoDB
会给符合条件的已有数据记录的索引项加
锁;对于键值在条 件范围内但并不存在的记录,叫做“
间隙(
GAP)”
,间隙的⽬的是为了防⽌
间隙(
GAP)”
,间隙的⽬的是为了防⽌
幻读
意向锁:意向锁分为 intention shared lock (IS)
和 intention exclusive lock (IX),意向锁的⽬的就是
和 intention exclusive lock (IX),意向锁的⽬的就是
表明有事务正在或者将要锁住某个表中的⾏

⾏锁与表锁的⽐较
表级锁
是
MySQL
中
锁定粒度最⼤
的⼀种锁,表示对当前操作的整 张表加锁,它实现简单。最常使
是
MySQL
中
锁定粒度最⼤
的⼀种锁,表示对当前操作的整 张表加锁,它实现简单。最常使
⽤的MYISAM与
INNODB
都⽀持表级锁定。
INNODB
都⽀持表级锁定。
特点:
开销⼩,加锁快;不会出现死锁;锁定粒度⼤,发出锁 冲突的概率最⾼,并发度最低。
开销⼩,加锁快;不会出现死锁;锁定粒度⼤,发出锁 冲突的概率最⾼,并发度最低。
⾏级锁
是
Mysql
中
锁定粒度最细
的⼀种锁,表示只针对当前操作的⾏进⾏加锁。⾏级锁能⼤⼤减少
是
Mysql
中
锁定粒度最细
的⼀种锁,表示只针对当前操作的⾏进⾏加锁。⾏级锁能⼤⼤减少
数据库操作的冲突。其加锁粒度最⼩,但加锁的开销也最⼤。
特点:
开销⼤,加锁慢;会出现死锁;锁定粒度最⼩,发⽣锁冲突的概率最低,并发度也最⾼
开销⼤,加锁慢;会出现死锁;锁定粒度最⼩,发⽣锁冲突的概率最低,并发度也最⾼
使⽤:
InnoDB⾏锁是通过给索引上的索引项加锁来实现的,
InnoDB⾏锁是通过给索引上的索引项加锁来实现的,
只有通过索引条件检索数据,InnoDB才使⽤⾏级锁,否则,InnoDB将使⽤表锁
InnoDB死锁概念
定义:当两个或以上的事务相互持有和请求锁,并形成⼀个循环的依赖关系,就会产⽣死锁。多个
事务同时锁定同⼀个资源时,也会产⽣死锁。在⼀个事务系统中,死锁是确切存在并且是不
能完全避免的。
解决:
InnoDB
会⾃动检测事务死锁,⽴即回滚其中某个事务,并且返回⼀个错误。它根据某种机
InnoDB
会⾃动检测事务死锁,⽴即回滚其中某个事务,并且返回⼀个错误。它根据某种机
制来选择那个最简单(代价最⼩)的事务来进⾏回滚
程序开发过程中应该如何注意避免死锁
锁的本质是资源相互竞争,相互等待,往往是两个(或以上)的 Session加锁的顺序不⼀致
如何有效避免:
在程序中,操作多张表时,尽量以相同的顺序来访问(避免形 成等待环路)
批量操作单张表数据的时候,先对数据进⾏排序(避免形成等 待环路) A
线程
id
:
1 ,10 ,20
按顺
线程
id
:
1 ,10 ,20
按顺
序加锁
B
线程
id:20,10,1
如果可以,⼤事务化成⼩事务,甚⾄不开启事务
select for
B
线程
id:20,10,1
如果可以,⼤事务化成⼩事务,甚⾄不开启事务
select for
update==>insert==>update = insert into update on duplicate key
尽量使⽤索引访问数据,避免没有
where
条件的操作,避免锁表 有⾛索引记录锁,没⾛索引表锁
where
条件的操作,避免锁表 有⾛索引记录锁,没⾛索引表锁
使⽤等值查询⽽不是范围查询查询数据,命中记录,避免间隙锁对并发的影响 1
,
10
,
20
等值
,
10
,
20
等值
where id in (1,10,20)
范围查询 id>1 and id<20
范围查询 id>1 and id<20
避免在同⼀时间点运⾏多个对同⼀表进⾏读写的脚本,特别注意加锁且操作数据量⽐较⼤的语句;
我们经常会有⼀些定时脚本,避免它们在同⼀时间点运⾏
Mysql间隙锁
间隙锁的定义:间隙锁是⼀个在索引记录之间的间隙上的锁
间隙锁的作⽤:
RR
隔离级别保证对读取到的记录加锁
(
记录锁
)
,
同时保证对读取的范围加锁,新
RR
隔离级别保证对读取到的记录加锁
(
记录锁
)
,
同时保证对读取的范围加锁,新
的满⾜查询条件的记录不能够插
⼊
(
间隙锁
)
,不存在幻读现象
⼊
(
间隙锁
)
,不存在幻读现象

select id,a,b from test where a=10 for update; 1
条满⾜的记录
条满⾜的记录
update delete…
INSERT INTO
test
(
id
,
a
,
b
) VALUES (18, 10, 10);
test
(
id
,
a
,
b
) VALUES (18, 10, 10);
select id,a,b from test where a=10; 2
条满⾜的记录
条满⾜的记录
验证间隙锁的⽅式,建表
==
》开启两个
session==
》第⼀个 session进⾏锁操作==
》另⼀个
session
==
》开启两个
session==
》第⼀个 session进⾏锁操作==
》另⼀个
session
插⼊数据
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
喜欢就支持一下吧
相关推荐
暂无评论内容