悲观锁和乐观锁使用场景
乐观锁是在应用层加锁,而悲观锁是在数据库层加锁(for update)
乐观锁顾名思义就是在操作时很乐观,这数据只有我在用,我先尽管用,最后发现不行时就回滚。
悲观锁在操作时很悲观,生怕数据被其他人更新掉,我就先将其先锁住,让别人用不了,我操作完成后再释放掉。
悲观锁需要数据库级别上的的实现,程序中是做不到的,如果在长事务环境中,数据会一直被锁住,导致并发性能大大地降低。
一般来说如果并发量很高的话,建议使用悲观锁,否则的话就使用乐观锁。
如果并发量很高时使用乐观锁的话,会导致很多的并发事务回滚、操作失败。
总之,冲突几率大用悲观,小就用乐观。
悲观锁一般是用于并发不是很高,并且不允许脏读等情况。但是对数据库资源消耗较大
悲观锁
当一个事务锁定了一些数据之后,只有当当前锁提交了事务,释放了锁,其他事务才能获得锁并执行操作
使用方式如下:
首先要关闭MySQL的自动提交:set autocommit = 0;
这里使用select for update的方式利用数据库开启了悲观锁,锁定了id=1的这条数据(注意:这里除非是使用了索引会启用行级锁,不然是会使用表锁,将整张表都锁住。)。
之后使用commit提交事务并释放锁,这样下一个线程过来拿到的就是正确的数据。
悲观锁一般是用于并发不是很高,并且不允许脏读等情况。但是对数据库资源消耗较大。
我们可以使用命令设置MySQL为非autocommit模式
set autocommit=0;
//0.开始事务
begin;/begin work;/start transaction; (三者选一就可以)
//1.查询出商品信
select status from t_goods where id = #{id} for update;
//2.根据商品信息生成订单
insert into t_orders (id,goods_id) values (null,1);
//3.修改商品status为2
update t_goods set status=2;
//4.提交事务
commit;/commit work;
乐观锁
通常的实现方式增加一个version字段,为每一条数据加上版本。每次更新的时候version+1,并且更新时候带上版本号。实现方式如下:
版本号(version)
UPDATE price_version
SET front = #{front,jdbcType=DECIMAL},
version= version + 1
WHERE id = #{id,jdbcType=INTEGER}
AND version = #{version,jdbcType=INTEGER}