锁机制--事务锁、乐观锁、悲观锁

版权声明:版权所有,转载备注 https://blog.csdn.net/alviss_kdd/article/details/85003108

查看mysql隔离级别:

select @@tx_isolation;
show variables like '%tx_isolation%';

事务的四种隔离级别

set session transaction isolation level 隔离级别

1. read uncommitted : 读取尚未提交的数据:哪个问题都不能解决
2. read committed:读取已经提交的数据 :可以解决脏读 ---- oracle默认 会出现不可重复读,幻读
3. repeatable read:重读读取:可以解决脏读和不可重复读 ---mysql默认的,无法解决幻读
4. serializable:串行化:可以解决脏读、不可重复读和幻读---相当于锁表

serializable隔离级别下,所有select语句都会被隐式的转化为select …lock in share mode.这可能导致,如果有未提交的事务正在修改某些行,所有读取这些行的select都会被阻塞住。

show variables like '%iso%'版本控制很强,在设置set global transaction isolation level read committed;时无法更改当前会话,可以在修改全局变量后修改会话set session transaction isolation level read committed;类似重新加载变量

验证隔离级别操作步骤

开始验证之前,需要知道,MySQL默认开启autocommit,默认隔离级别为repeatable read,MySQL事务的流程为begin ...end
在事务执行过程中,采用MVCC解决不可重复读问题。事务在默认隔离级别下,多版本控制数据库DML操作。

在模拟实验时需设置autocommit=off,方便模拟

顺序 事务1 事务2
1 begin;
2 begin;
3 select * from sakila2.actor1 where actor_id=2;
4 select * from sakila2.actor1 where actor_id=2;
5 update sakila2.actor1 set first_name=‘kdd1’ where actor_id=2;
6 commit;
7 select * from sakila2.actor1 where actor_id=2;
8 select * from sakila2.actor1 where actor_id=2;
9 update sakila2.actor1 set first_name=‘kdd1’ where actor_id=2;
10 commit;
11 select * from sakila2.actor1 where actor_id=2;
12 select * from sakila2.actor1 where actor_id=2;
13 end;
14 end;

乐观锁和悲观锁

当我们说乐观锁和悲观锁时,它们的概念和事务锁(共享锁、排它锁)是完全不同的。
乐观锁和悲观锁是针对应用和数据库之间的一种取数和锁定策略。而事务锁是数据库为了解决数据库一致性问题出现的解决方案。这一点很重要。
所谓乐观锁,就是利用版本号比较机制,只是在读数据的时候,将读到的数据的版本号一起读出来,当对数据的操作结束后,准备写数据的时候,再进行一次数据版本号的比较,若版本号没有变化,即认为数据是一致的,没有更改,可以直接写入,若版本号有变化,则认为数据被更新,不能写入,防止脏写。版本号一般通过加字段的方式来实现,可以是自增标识,也可以是时间戳。

抢购执行过程

说明:以上为操作执行过程简要描述

多用户抢购冲突

说明:如上图所示,如果更新操作顺序执行,则数据的版本(version)依次递增,不会产生冲突。但是如果发生有不同的业务操作对同一版本的数据进行修改,那么,先提交的操作(图中B)会把数据version更新为2,当A在B之后提交更新时发现数据的version已经被修改了,那么A的更新操作会失败。

悲观锁是以悲观的态度面对高并发,此时高并发如果采用乐观锁会经常导致修改出现等待的情况。
在应用设计和存储过程开发时,应以最小代价方式选择乐观锁和悲观锁。一般b/s环境下,推荐使用乐观锁 。

高并发多修改,为什么使用悲观锁?

从下例中可以看出假设只是进行一次修改。
乐观锁的操作除了case1其余均返回错误。此时开销为5次查询,1次加锁,1次修改。悲观锁只有case1可以执行,其余均处于等待状态。此时开销为,1次查询,1次加锁,1次更新。所以使用悲观锁开销更小。

乐观锁

case 1 case 2 case 3 case 4 case 5
update table set update table set update table set update table set update table set
success failure failure failure failure
返回信息 下一步操作 下一步操作 下一步操作 下一步操作

悲观锁

case 1 case 2 case 3 case 4 case 5
update table set 等待操作 等待操作 等待操作 等待操作
success failure failure failure failure
返回信息 获取锁 获取锁 获取锁 获取锁

猜你喜欢

转载自blog.csdn.net/alviss_kdd/article/details/85003108
今日推荐