mysql有乐观锁和悲观锁吗_MySQL中的乐观锁和悲观锁

当我们购买一件商品时,一般会有以下几个操作:

查询商品信息

将商品信息和用户信息插入订单表

更新商品信息,比如状态更新为已被购买

当单条线程执行这些操作的时候肯定不会出现问题,但是当高并发的时候,会出现商品会重复购买的情况.这时候我们就要加锁了.

goods

CREATE TABLE `goods` (

`id` int(11) NOT NULL COMMENT '主键id',

`name` varchar(32) DEFAULT NULL COMMENT '商品名称',

`status` tinyint(3) DEFAULT NULL COMMENT '商品状态 0:未被购买 1: 已被购买',

`version` int(11) DEFAULT NULL COMMENT '版本号,每次更新版本号 + 1',

`create_time` bigint(20) DEFAULT NULL COMMENT '创建时间(精确到毫秒)',

`update_time` bigint(20) DEFAULT NULL COMMENT '更新时间(时间戳,精确到毫秒)',

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';

orders

CREATE TABLE `orders` (

`id` int(11) NOT NULL COMMENT '注解id',

`goods_id` int(11) DEFAULT NULL COMMENT '商品id',

`user_id` int(11) DEFAULT NULL COMMENT '用户id',

`status` tinyint(4) DEFAULT NULL COMMENT '订单状态 0:刚创建 1:下单完成 -1:下单失败',

`create_time` bigint(20) DEFAULT NULL COMMENT '创建时间',

`update_time` bigint(20) DEFAULT NULL COMMENT '更新时间',

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单表';

加锁可分为乐观锁和悲观锁

乐观锁

乐观锁,顾名思义,它的想法比较乐观,认为每次查询都不会涉及到更新,所以只有到更新的时候再判断查询到的记录是否发生变化,如果没有发生变化就执行更新操作,如果已经发生了变化就不执行更新操作.

怎么判断数据是否发生变化

给表添加一个updateTime字段,每次更新的时候先判断updateTime是否与查询到updateTime一致,如果一致就更新数据,并且更新updateTime,否则不更新

//查询id = #id 商品 goods

SELECT id, name, status, create_time, update_time, version FROM GOODS WHERE id = '#id';

//插入订单表

INSERT INTO ORDERS VALUES(id, goods_id, user_id,...);

//更新goods状态,这里的update_time是上面查到的goods的update_time

UPDATE GOODS SET status = 1, update_time = now() WHERE id = '#id' AND update_time = '#update_time';

给表添加一个version字段,每次更新的时候仙判断version是否和查询到的version一致,如果一致就更新数据,并且更新version = version + 1,否则不更新(操作和update_time更新相似,只是update_time改成version)

悲观锁

悲观锁,顾名思义,就是想法比较悲观,它认为每次查询都可能涉及到更新,所以在查询的时候就给记录加上锁,其它线程就不会执行更新操作了,只有等释放锁了才能执行更新操作.

怎么给记录加锁

共享锁(读锁,S锁)

SET AUTOCOMMIT = 0;

BEGIN;

SELECT id, name, status, create_time, update_time, version FROM GOODS WHERE id = '#id' LOCK IN SHARE MODE;

COMMIT;

在mysql事务中查询语句后面加上 lock in share mode,即可得到记录的共享锁;什么叫做共享呢?就是当共享锁还没释放的时候,其他查询用lock in share mode也可以得到记录的共享锁.那共享锁有什么用呢?共享锁被占用的记录不能被更新或者不能被select ... for update 得到排它锁,否则会被阻塞.

排它锁

SET AUTOCOMMIT = 0;

BEGIN;

SELECT id, name, status, create_time, update_time, version FROM GOODS WHERE id = '#id' FOR UPDATE;

COMMIT;

在mysql事务中查询语句后面加上 for update 或者 更新记录的时候,即可得到记录的排它锁;什么叫做排他锁呢?排它锁被占用的记录,不允许其他线程获得他的排它锁,甚至共享锁,就是说记录不能被更新或者 其他线程的for update 到,否则会阻塞.直到排它锁释放了才能继续执行.

注意,不管是共享锁还是排它锁,当我们用不加锁的select 查询记录的时候也是可以查询到的.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值