mysql锁


mysql并发事务访问相同记录

2.1 读读情况

读-读 情况,即并发事务相继 读取相同的记录 。读取操作本身不会对记录有任何影响,并不会引起什么问题,所以允许这种情况的发生。

2.2 写写情况

写-写 情况,即并发事务相继对相同的记录做出改动。

脏写:

A,B同时操作某一条记录,A对改记录修改,原来值为1改为2了,但是B这是也对改记录进行修改 改为3但是B将事务回滚了,这是就发生了脏写

在这种情况下会发生 脏写 的问题,任何一种隔离级别都不允许这种问题的发生。所以在多个未提交事务相继对一条记录做改动时,需要让它们 排队执行 ,这个排队的过程其实是通过 锁 来实现的。这个所谓的锁其实是一个 内存中的结构 ,在事务执行前本来是没有锁的,也就是说一开始是没有 锁结构 和记录进行关联的,如图所示:

当一个事务想对这条记录做改动时,首先会看看内存中有没有与这条记录关联的 锁结构 ,当没有的时候就会在内存中生成一个 锁结构 与之关联。比如,事务 T1 要对这条记录做改动,就需要生成一个 锁结构与之关联:

一个事务对应一个锁结构,当前事务没结束是,另一个事务又来这是会再次生成一个锁结构


2.3 读写

读-写 或 写-读 即一个事务进行读取操作,另一个进行改动操作。这种情况下可能发生脏读 ,不可重复读 幻读的问题。

各个数据库厂商对SQL标准 的支持都可能不一样。比如MySQL在REPEATABLE READ 隔离级别上就已经解决了幻读问题。

2.4解决方案


从数据操作的类型划分:读锁 写锁


锁定读

select ... from 表名  lock in share mode  //为读取到的数据添加共享锁
select ... from  表名  for update  //加排它锁
#事务1
begin
SELECT * FROM  student  LOCK IN  SHARE MODE


#事务二
begin 
SELECT * FROM  student  LOCK IN  SHARE MODE
#成功  此时commit事务二
commit

begin
SELECT * FROM  student for update #失败  因为事务1  对该数据加了共享锁

#X锁  加X锁  也会被阻塞

#X锁  加S锁  也会被阻塞

写操作必须加排它锁

从数据操作的粒度划分

表锁

表级别的S和X锁

意向锁


在我们对行数据加锁是会自动在其外层空间结构加一个意向锁 IX
这样可以方便告知这个数据页有数据加过锁了

如果对表中一条数据加过X锁,那么另一个会话对表加锁是阻塞,因为意向锁(自动对表级别加IX)

意向锁不会与行级的共享 / 排他锁互斥!正因为如此,意向锁并不会影响到多个事务对不同数据行加排
他锁时的并发性。(不然我们直接用普通的表锁就行了)


比如对一个id=5数据加行锁,自动会对整个表加一个意向锁IX,这是另一个事务对id=6加锁是不受影响的

自增锁

元数据锁(MDL)锁


MDL的读锁之间是可以同时增删查改的 ,但是如果有一个MDL写锁这是就会阻塞

比如我们遇到一种情况 一个事务正在读一个表的内容这时会加MDL的读锁,这时另一个事务要更改表结构这时要加MDL的写锁,这个事务被阻塞了。这时又来一个事务要读,这时就会阻塞

行锁

InnoDB与MyISAM最大区别:①支持索引 ②采用行级锁

#事务1
begin
update student set name='测试' where id=1  #这是mysql会自动给改行加上X锁

#事务2
begin
select *  from  student where id=1   #可以读到
select *  from  student where id=1  lock in share mode #阻塞

 #直到事务1  commit才能读取到

间隙锁


可以多次去加

临键锁


文章作者: 蛰伏
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 蛰伏 !
  目录