文章插图
此时,用户李四的操作就丢失掉了:
- 丢失更新:一个事务的更新覆盖了其它事务的更新结果 。
解决的方法:
- 使用Serializable隔离级别 , 事务是串行执行的!乐观锁悲观锁乐观锁是一种思想 , 具体实现是,表中有一个版本字段,第一次读的时候 , 获取到这个字段 。处理完业务逻辑开始更新的时候,需要再次查看该字段的值是否和第一次的一样 。如果一样更新,反之拒绝 。之所以叫乐观 , 因为这个模式没有从数据库加锁,等到更新的时候再判断是否可以更新 。悲观锁是数据库层面加锁,都会阻塞去等待锁 。
所以,按照上面的例子 。我们使用悲观锁的话其实很简单(手动加行锁就行了):
- select * from xxxx for update
- 也就是说 , 如果张三使用select ... for update,李四就无法对该条记录修改了~
乐观锁不是数据库层面上的锁,是需要自己手动去加的锁 。一般我们添加一个版本字段来实现:
具体过程是这样的:
张三select * from table --->会查询出记录出来 , 同时会有一个version字段
文章插图
李四select * from table --->会查询出记录出来,同时会有一个version字段
文章插图
李四对这条记录做修改:update A set Name=lisi,version=version+1 where ID=#{id} and version=#{version},判断之前查询到的version与现在的数据的version进行比较,同时会更新version字段
此时数据库记录如下:
文章插图
张三也对这条记录修改:update A set Name=lisi,version=version+1 where ID=#{id} and version=#{version},但失败了!因为当前数据库中的版本跟查询出来的版本不一致!
文章插图
参考资料:
- ***/p/31537871---什么是悲观锁和乐观锁***/question/27876575---乐观锁和 MVCC 的区别?
当我们用范围条件检索数据而不是相等条件检索数据,并请求共享或排他锁时 , InnoDB会给符合范围条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)” 。InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁 。
值得注意的是:间隙锁只会在Repeatable read隔离级别下使用~
例子:假如emp表中只有101条记录,其empid的值分别是1,2,...,100,101
Select * from emp where empid > 100 for update;上面是一个范围查询,InnoDB不仅会对符合条件的empid值为101的记录加锁,也会对empid大于101(这些记录并不存在)的“间隙”加锁 。
InnoDB使用间隙锁的目的有两个:
- 为了防止幻读(上面也说了 , Repeatable read隔离级别下再通过GAP锁即可避免了幻读)满足恢复和复制的需要MySQL的恢复机制要求:在一个事务未提交前,其他并发事务不能插入满足其锁定条件的任何记录 , 也就是不允许出现幻读
并发的问题就少不了死锁,在MySQL中同样会存在死锁的问题 。
但一般来说MySQL通过回滚帮我们解决了不少死锁的问题了,但死锁是无法完全避免的,可以通过以下的经验参考,来尽可能少遇到死锁:
- 1)以固定的顺序访问表和行 。比如对两个job批量更新的情形,简单方法是对id列表先排序 , 后执行,这样就避免了交叉等待锁的情形;将两个事务的sql顺序调整为一致,也能避免死锁 。2)大事务拆小 。大事务更倾向于死锁 , 如果业务允许,将大事务拆小 。3)在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率 。4)降低隔离级别 。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁 。5)为表添加合理的索引 。可以看到如果不走索引将会为表的每一行记录添加上锁,死锁的概率大大增大 。
推荐阅读
- 林正英葬礼两大诡异事件,曾留古怪遗言:千万别让人看见我的尸体
- 低温烫伤神器有哪些 保暖神器真的会导致低温烫伤吗
- 这一次父亲节,王健林迎来了“两大喜讯”!
- 《扫黑风暴》徐英子、马帅之死,两大嫌疑人浮出水面,导演用心了
- 00级神器可以继承
- 《超新星运动会》官宣回归,嘉宾阵容曝光,两大顶流助阵成焦点!
- 游泳耳朵不进水小窍门 游泳防耳朵进水的神器
- 两大动作巨星李连杰和吴京会面,疑合作新片《镖人》,期待值拉满
- 目的基因的获取方法3种,获取目的基因的两大途径是什么
- 40集《时光正好》今晚开播,演员阵容强大,两大看点,有爆款潜质