MySQL中乐观锁和悲观锁

乐观锁:
乐观的认为操作不会导致冲突,在操作数据时,并不进行任何其他特殊处理(也就是不加锁), 而是在进行更新时,再去判断是否有冲突MySQL数据库不支持乐观锁,需要开发者自己实现
乐观者开发者通常实现方案:
给表添加一个版本号或者时间戳(基于version、基于timestamp字段),每次操作后,将记录的版本号加1。实际的做法为,先查询出来那条记录,获取version字段,如果要对那条记录进行更新操作,则先判断此时version的值是否与刚才查出来的version的值相等,如果相等,则说明这段期间,没有其他程序对其进行操作,则可以进行更新操作,并将version字段的值加1;如果更新时发现此刻version值与刚才取出来的version的值不相等,则说明这段期间已经有其他程序对其进行更新操作,则不进行更新操作。
举例如下
1、查询出商品信息
select (status, version) from tbl_goods where id=#{id};
2、根据商品信息生成订单
3、修改商品信息
update tbl_goods set status=2, version=version+1 where id=#{id} and version=#{version};
4、判断update影响的行数,如果为0则本次更新失败,如果为1,则更新成功。
5、更新失败时,需要重试

悲观锁:
悲观锁在操作数据时,认为此操作会出现数据冲突,所以在每次操作时都要通过获取锁来对数据进行操作。悲观锁是由数据库自己实现的。
select for update或者lock in share mode,必须包裹 在事务中才生效
即语句如下:
begin ; // 开启事务
select status from tbl_goods where id=1 for update; // 悲观锁 (id字段未普通索引,只锁定该行,不是索引就会锁全表)
update tbl_goods set status=2;
commit; // 提交事务

3、MySQL中高并发,更新计数
对于update、delete和insert语句,InnoDB会自动给涉及数据添加排他锁。对于普通select语句,innodb不会加任何锁。
如上update的更新操作会加自动加排他锁,因此,不需要而外再去处理其他操作,直接使用如下语句:
update tbl_goods set count=count+1 where id=1; // 利用mysql计数器实现计数操作
错误的用法:
select count from tbl_goods where id=1;
count = count+1; // 其他操作
update tbl_goods set count=#{count} where id=1;
上述的操作会有并发的问题,导致计数不正确。
一种改进的操作是添加for update悲观锁:
being; // 开启事务
select count from tbl_goods where id=1 for update;
count = count +1; // 其他操作
update tbl_goods set count = #{count} where id=1;
commit;

猜你喜欢

转载自blog.csdn.net/timchen525/article/details/80753813