网站的设计流程有哪些步骤,网站建设与管理 教材,那些网站可以给产品做推广,中国建设教育协会的网站转载自 并发控制--悲观锁和乐观锁详解背景考虑下面两个并发带来的问题#xff1a;1、丢失更新#xff1a;一个事务的更新结果覆盖了其它事务的更新结果#xff0c;即所谓的更新丢失。2、脏读#xff1a;当一个事务读取其它完成一半事务的记录时#xff0c;就会发生脏读取。…转载自 并发控制--悲观锁和乐观锁详解背景考虑下面两个并发带来的问题1、丢失更新一个事务的更新结果覆盖了其它事务的更新结果即所谓的更新丢失。2、脏读当一个事务读取其它完成一半事务的记录时就会发生脏读取。例如
两个用户同时修改商品库存表A、B同时进入看到的库存都是100A购买一件把库存修改为99(100-1)。此时B购买两件把库存修改为98(100-2)因为A、B同时读到的库存都是100B并不能看到A做的库存更新所以造成B脏读造成A丢失更新。所以为了解决这些并发带来的问题。 我们需要引入并发控制机制--锁。锁分类悲观锁
悲观锁就是用户修改数据时看起来很悲观保守态度担心别的用户会同时修改这条数据所以每次修改时会提前把这条数据锁定起来只有自己可修改但别的用户可以读等自己修改完了再释放锁。乐观锁
乐观锁就是用户修改数据时心态很乐观不管别人修改不修改数据我都不上锁我修改的时候判断下数据有没有发生变化没发生变化我就会更新成功发生变化了就不会更新成功我再去重试之前的动作直到更新成功。锁应用悲观锁
使用悲观锁的时候我们首先必须关闭mysql数据库的自动提交属性因为MySQL默认使用autocommit模式也就是说当你执行一个更新操作后MySQL会立刻将结果进行提交。
关闭命令为set autocommit0;悲观锁一般使用select…for update实现在执行的时候会锁定数据虽然会锁定数据但是不影响其他事务的普通查询使用。
在我们使用悲观锁的时候事务中的语句例如//开始事务
begin;/begin work;/start transaction; (三选一)
//查询信息
select * from order where id1 for update;
//修改信息
update order set namenames;
//提交事务
commit;/commit work;(二选一)此处的查询语句for update关键字在事务中只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 同一条数据时会等待其它事务结束后才执行一般的SELECT查询则不受影响。注意事项
执行事务时关键字select…for update会锁定数据防止其他事务更改数据。但是锁定数据也是有规则的。查询条件与锁定范围
1、具体的主键值为查询条件
比如查询条件为主键ID1等等如果此条数据存在则锁定当前行数据如果不存在则不锁定。2、不具体的主键值为查询条件
比如查询条件为主键ID1等等此时会锁定整张数据表。3、查询条件中无主键
会锁定整张数据表。4、如果查询条件中使用了索引为查询条件
明确指定索引并且查到则锁定整条数据。如果找不到指定索引数据则不加锁。乐观锁
1、使用自增长的整数表示数据版本号更新时检查版本号是否一致比如数据库中数据版本为666更新提交时version6661,使用该version值(667)与数据库version1(667)作比较如果相等则可以更新如果不等则有可能其他程序已更新该记录所以返回错误或者发起重试动作。例如表
student(id,name,version)
1 a 1
当事务一进行更新操作update student set nametxt where id #{id} and version #{version};
此时操作完后数据会变为id 1,name txt,version 2当另外一个事务二同样执行更新操作的时候却发现version ! 1此时事务二就会操作失败从而保证了数据的正确性。2、使用时间戳来实现原理同上。3、使用其他数据库字段如金额更新时添加条件判断金额是否变化原理同上。乐观锁图示结论两种锁各有优缺点不能单纯的定义哪个好于哪个。乐观锁比较适合数据修改比较少读取比较频繁的场景即使出现了少量的冲突这样也省去了大量的锁的开销故而提高了系统的吞吐量。但是如果经常发生冲突写数据比较多的情况下上层应用不不断的retry这样反而降低了性能对于这种情况使用悲观锁就更合适。