多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
**问题:** 两个用户(或以上)对同一个数据对象操作引起的数据丢失。 **解决方案:** 1.悲观锁:假设丢失更新一定存在;sql后面加上**for update;**这是数据库的一种机制。 2.乐观锁:假设丢失更新不一定发生。update时候存在版本,更新时候按版本号进行更新。 # 一、乐观锁 乐观锁,简单地说,就是从应用系统层面上做并发控制,去加锁。 实现乐观锁常见的方式:版本号version **实现方式:** 在数据表中增加版本号字段,每次对一条数据做更新之前,先查出该条数据的版本号,每次更新数据都会对版本号进行更新。在更新时,把之前查出的版本号跟库中数据的版本号进行比对,如果相同,则说明该条数据没有被修改过,执行更新。如果比对的结果是不一致的,则说明该条数据已经被其他人修改过了,则不更新,客户端进行相应的操作提醒。 ![](https://img.kancloud.cn/96/93/96933d3f1ab234751162749176e38bf0_741x499.png) **代码:** ![](https://img.kancloud.cn/c8/17/c817ad4868a4024b4df96a8faefd4133_684x147.png) 既然可以用version,那还可以使用时间戳字段,该方法同样是在表中增加一个时间戳字段,和上面的version类似,也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比,如果一致则OK,否则就是版本冲突。 **注意:** 把select语句放在事务中,查询的就是master主库了! # 二、悲观锁 悲观锁,简单地说,就是从数据库层面上做并发控制,去加锁。 在MySQL中使用悲观锁,必须关闭MySQL的自动提交,set autocommit=0,MySQL默认使用自动提交 autocommit模式,也即你执行一个更新操作,MySQL会自动将结果提交。 ![](https://img.kancloud.cn/ee/43/ee43dcf02c717db471e75dc6e4f3c93e_672x53.png) 当我们在查询出items信息后就把当前的数据锁定,直到我们修改完毕后再解锁。那么在这个过程中,因为数据被锁定了,就不会出现有第三者来对其进行修改了。而这样做的前提是需要将要执行的SQL语句放在同一个事物中,否则达不到锁定数据行的目的。 ![](https://img.kancloud.cn/ca/75/ca75404dfc372e0a02a86986f876d4fe_673x143.png) 悲观锁并不是适用于任何场景,它也存在一些不足,因为悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。如果加锁的时间过长,其他用户长时间无法访问,影响了程序的并发访问性,同时这样对数据库性能开销影响也很大,特别是对长事务而言,这样的开销往往无法承受,这时就需要乐观锁。 **注意:** 在MySQL中用悲观锁务必须确定走了索引,而不是全表扫描,否则将会将整个数据表锁住**。