网站建设教学视频百度云盘,wap什么意思网络语言,海门市城乡建设局网站,免费推广软件有哪些使用场景举例#xff1a;以MySQL InnoDB为例商品t_goods表中有一个字段status#xff0c;status为1代表商品未被下单#xff0c;status为2代表商品已经被下单#xff0c;那么我们对某个商品下单时必须确保该商品status为1。假设商品的id为1。 一、如果不采用锁#xff0c;…使用场景举例以MySQL InnoDB为例商品t_goods表中有一个字段statusstatus为1代表商品未被下单status为2代表商品已经被下单那么我们对某个商品下单时必须确保该商品status为1。假设商品的id为1。 一、如果不采用锁那么操作方法如下//1.查询出商品信息select status from t_goods where id1;//2.根据商品信息生成订单insert into t_orders (id,goods_id) values (null,1);//3.修改商品status为2update t_goods set status2 where id1; 上面这种场景在高并发访问的情况下很可能会出现问题。前面已经提到只有当goods status为1时才能对该商品下单上面第一步操作中查询出来的商品status为1。但是当我们执行第三步Update操作的时候有可能出现其他人先一步对商品下单把goods status修改为2了但是我们并不知道数据已经被修改了这样就可能造成同一个商品被下单2次使得数据不一致。所以说这种方式是不安全的。 二、使用悲观锁来实现在上面的场景中商品信息从查询出来到修改中间有一个处理订单的过程使用悲观锁的原理就是当我们在查询出goods信息后就把当前的数据锁定直到我们修改完毕后再解锁。那么在这个过程中因为goods被锁定了就不会出现有第三者来对其进行修改了。 注要使用悲观锁我们必须关闭mysql数据库的自动提交属性因为MySQL默认使用autocommit模式也就是说当你执行一个更新操作后MySQL会立刻将结果进行提交。 我们可以使用命令设置MySQL为非autocommit模式set autocommit0;设置完autocommit后我们就可以执行我们的正常业务了。具体如下//0.开始事务begin;/begin work;/start transaction; (三者选一就可以)//1.查询出商品信息select status from t_goods where id1 for update;//2.根据商品信息生成订单insert into t_orders (id,goods_id) values (null,1);//3.修改商品status为2update t_goods set status2 where id1;//4.提交事务commit;/commit work; 注上面的begin/commit为事务的开始和结束因为在前一步我们关闭了mysql的autocommit所以需要手动控制事务的提交在这里就不细表了。 上面的第一步我们执行了一次查询操作select status from t_goods where id1 for update;与普通查询不一样的是我们使用了select…for update的方式这样就通过数据库实现了悲观锁。此时在t_goods表中id为1的那条数据就被我们锁定了其它的事务必须等本次事务提交之后才能执行。这样我们可以保证当前的数据不会被其它事务修改。 注需要注意的是在事务中只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 同一笔数据时会等待其它事务结束后才执行一般SELECT ... 则不受此影响。拿上面的实例来说当我执行select status from t_goods where id1 for update;后。我在另外的事务中如果再次执行select status from t_goods where id1 for update;则第二个事务会一直等待第一个事务的提交此时第二个查询处于阻塞的状态但是如果我是在第二个事务中执行select status from t_goods where id1;则能正常查询出数据不会受第一个事务的影响。 补充MySQL select…for update的Row Lock与Table Lock上面我们提到使用select…for update会把数据给锁住不过我们需要注意一些锁的级别MySQL InnoDB默认Row-Level Lock所以只有「明确」地指定主键MySQL 才会执行Row lock (只锁住被选取的数据) 否则MySQL 将会执行Table Lock (将整个数据表单给锁住)。