【博客园cnblogs笔者m-yb原创(部分引用, 在文末有注明),转载请加本文博客链接,笔者github: https://github.com/mayangbo666,公众号aandb7,QQ群927113708】
https://www.cnblogs.com/m-yb/p/9974979.html
最近写代码时, 发现自己对事务和数据库的锁的使用有点不明白, 而这些是面试易考点, 查了些资料, 对这些进行重新梳理表述如下:
所谓事务是用户定义的一个数据库操作系列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。例如在关系数据库中,一个事务可以是一条sql语句、一组sql语句或整个程序。
【事务】:对加了事务的一系列操作, 会在执行的时候 -> 同时成功, 同时失败. spring中使用事务, 可在方法头上加这样一行注解代码:
@Transactional(rollbackFor = Exception.class)
为什么有了事务这东西,还需要乐观锁悲观锁?事务是粗粒度的概念、乐观锁悲观锁可以更细粒度的控制;
比如抢票,假设余票只有1张;隔离级别可以保证事务A和事务B不能读到对方的数据,也不能更新对方正在更新的数据,但是事务A和事务B都认为还有1张余票,于是出票,并更新为0;
但是事务B读取的是过时数据,依据过时数据做了业务处理;
所以需要乐观锁或者悲观锁,来记录一个信息:当前已经读取的数据,是不是已经过时了!
事务有这么几种实现方式:锁协议、MVCC、时间戳排序协议、有效性检查协议,锁协议是事务的一种实现方式,事务 = 用锁封装的一个函数,可以重用而已,但是这几个事务的函数覆盖面太粗粒度了,所以有时候我们还得借助于锁来进行细粒度控制;
事务不能保证每个操作结果正确,售票时超卖还是会发生。
事务保证整个操作的成一个组,要么全做要么全不做, 但是不能保证多个事务同时读取同一个数据
数据对象被加上排它锁时,其他的事务不能对它读取和修改;加了共享锁的数据对象可以被其他事务读取,但不能修改
事务可以用锁实现,可以保证一致性和隔离性,但是锁用来保证并发性;
隔离性和并发性有点类似,但是隔离性只是保证不会出现相互读取中间数据,却无法解决并发的问题.
当业务要求执行这组操作的成功率时, 使用悲观锁;
当业务要求迅速返回状态的速度时, 使用乐观锁;
悲观锁(排他锁)、乐观锁(共享锁)在数据库的使用:
悲观锁在sql语句的最后加上 for update【典型应用场景 如 转账时,锁住两边加减余额的操作】
乐观锁可通过版本控制, 在sql语句的更新操作语句中加入 version = #{oldVersion}条件
注本文部分转载自:
作者:chinoukin
来源:CSDN
原文:https://blog.csdn.net/chinoukin/article/details/79005596