MySql系列:我们简单聊聊事务和锁的概念~~

一、事务的四个隔离级别

1.1 事务并发导致的几类问题
问题描述
脏读一个事务去更新或者查询了另外一个还没提交的事务更新过的数据;例如: 事务A读取一条记录的值,然后基于这个值做业务逻辑,在事务A提交之前,事务B回滚了该记录,导致事务A读到的这条记录是一个脏数据
不可重复读同一个事务里边,2次读取统一记录,但是数据不一样。因为另外一个事务在对此记录进行update
幻读同一事务里,同样的select语句,执行了两次,返回记录条数不一样。因为另一个事务在进行insert/delete
丢失更新两个事务同时修改同一记录,事务A的修改被事务B覆盖了。例如:x=5,A和B同时把它读出来,减一,再写回去,得到x=4,实际x的正确值应该是x=3
1.2 InnoDB的事务隔离级别
名称解决问题
RU(Read Uncommited)四个问题 都没有解决
RC(Read Commited)只解决了脏读
RR(Repeatable Read)几觉了脏读、不可重复读、幻读;默认级别
Serialization串行化。完全上面四个问题

在RR级别下,如何解决最后一个问题。

二、锁

2.1 悲观锁和乐观锁

假设有张用户余额表T :

user_idbanlance
130
280

有2个事务,一个充钱,一个扣钱
事务A

start transaction
int a = select  banlance from T where user_id =1
b = b + 50
update T set balance  = b where user_id =1
commit

事务B

start transaction
int b = select banlance from T where user_id =1
b = b -50
update T set balance  = b where user_id =1
commit

事务A和事务B并行执行,执行结果可能是30(结果正确),也可能是80(事务A给事务B覆盖了),也可能是-20(事务B把事务A的结果覆盖了)。
解决当前问题,有下面几种方法:
方法1:利用单条语句的原子性
事务A

update T set balance  = b + 50 where user_id =1

事务B

update T set balance  = b - 50 where user_id =1

方法2:悲观锁
事务A

start transaction
int a = select  banlance from T where user_id =1 for update
b = b + 50
update T set balance  = b where user_id =1
commit

事务B

start transaction
int b = select banlance from T where user_id =1 for update
b = b -50
update T set balance  = b where user_id =1
commit

问题:一个事务拿到锁的时候,其他访问该记录的事务都会阻塞,在高并发情况下会造成用户端大量请求阻塞。

方法3:乐观锁(数据库的CAS)

user_idbanlanceversion
130
280

事务A

while(!result) {
	start transaction
	int a, v1 = select  banlance,version from T where user_id =1 ;
	b = b + 50
	result = update T set balance  = b, version=version+1 where user_id =1 and version
	commit
}

事务B

while(!result) {
	start transaction
	int a, v1 = select  banlance,version from T where user_id =1 ;
	b = b -50
	result = update T set balance  = b, version=version+1 where user_id =1 and version
	commit
}

方法4:分布式锁

start_transaction
	select xxx from T1
	select xxx from T2
	根据T1,T2查询结果进行逻辑计算
	update T3
commit
2.2 死锁检测

1、2个事务为例
在这里插入图片描述
2、多个事务发生死锁的情况
在这里插入图片描述
死锁的检测就是发现这种图中是否是有环存在的。检测到死锁后,数据库可以强制让其中某个事务回滚,释放掉锁,把环断开,死锁就解除了
场景1
事务A和事务B,顺序刚好反过来,可能发生死锁

事务A事务B
delete from T1 where id=1
update T2 set xxx where id = 5
delete from T1 where id=5
delete from T2 where id = 1

场景2
同一张表,在RR隔离级别下,insert操作会增加Gap锁,可能会导致2个事务死锁。

事务A事务B
delete from T1 where id =1
update T1 set xxx where id =5
insert into T1 values(…)
insert into T1 values(…)
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值