简介
通过此文你可以了解到的内容有:
- 什么是乐观锁和悲观锁
首先要了解什么是锁:mysql为了解决资源共享,所造成并发问题的处理机制。
悲观锁
在操作之前给数据添加锁,锁定后再对数据进行操作。在锁未释放之前,其他人无法对数据进行读写。
特点:
- 可以保证数据的完全独占性和正确性
- 开销大,性能不高
添加锁的方式
/*读锁*/
lock table userinfo read;
/*写锁*/
lock table userinfo write;
/*解锁*/
unlock table;
/*行读锁,条件必须为索引列,否则会自动转换为表锁*/
select * from table where id =1;
/*提交解锁*/
commit;
/*回滚解锁*/
rollback;
实操
预备数据
drop database if exists deom;
create database demo;
drop table if exists lock_demo1;
create table lock_demo1 (
id bigint(11) primary key,
number int(2) default 0
)engin=innodb default charset=utf8;
insert into lock_demo1 values(1,1);
未添加悲观锁
会话一
set autocommit = 0;
/*①添加读锁*/
select * from lock_demo1 where id = 1;
+--------+
| number |
+--------+
| 1 |
+--------+
/*③更新数量*/
update lock_demo1 set number = number-1 where id = 1;
会话二
/*②查询数量*/
select * from lock_demo1 where id = 1;
+--------+
| number |
+--------+
| 1 |
+--------+
/*④更新数量*/
update lock_demo1 set number = number-1 where id = 1;
操作顺序:1—>2—>3—>4
以前情况经常出现在秒杀系统中,2个或者2个以上的用户在争夺最后一件商品,如果没有加锁则会出现第二个会话更新后,number 将等于 -1,造成业务错误。
添加悲观锁
会话一
/*①添加读锁*/
select * from lock_demo1 where id = 1 for update;
+--------+
| number |
+--------+
| 1 |
+--------+
/*③更新数量*/
update lock_demo1 set number = number-1 where id = 1;
会话二
/*②查询数量*/
select * from lock_demo1 where id = 1 for update;
+--------+
| number |
+--------+
| 1 |
+--------+
/*④更新数量*/
update lock_demo1 set number = number-1 where id = 1;
操作顺序:1—>2—>3—>4
当会话一添加了锁之后,会话二添加锁的操作将处于等待,直到会话一进行解锁。从而避免了资源争夺造成的并发问题。
乐观锁
在操作数据的时候,不会对数据进行锁定。只有在提交数据的时候,会采用一种机制来验证数据是否冲突。
特点:
- 并发度高
- 开销小
实操
预备数据
set aotocommit=1;
alter table lock_demo1 add column version int(2) default 0;
会话一
/*1*/
select version , number from lock_demo1 where id =1;
+----+--------+---------+
| id | number | version |
+----+--------+---------+
| 1 | 3 | 0 |
+----+--------+---------+
/*3*/
update lock_demo1 set number = number -1,version=version+1 where id = 1 and version = 0;
会话二
/*2*/
select version , number from lock_demo1 where id =1;
+----+--------+---------+
| id | number | version |
+----+--------+---------+
| 1 | 3 | 0 |
+----+--------+---------+
/*4*/
update lock_demo1 set number = number -1,version=version+1 where id = 1 and version = 0;
执行顺序:1–>2–>3–>4,此时会话2的更新会失败。
由于在提交修改的时候,添加了version字段进行验证,从而保证数据的有效性和正确性,将错误的处理情况让用户进行处理,mysql不添加锁,从而减少了资源消耗,提高了并发。