事务操作可能会出现的数据问题
1、脏读(dirty read):B事务更改数据还未提交,A事务已经看到并且用了 。B事务如果回滚,则A事务做错了
2、 不可重复读(non-repeatable read):不可重复读的重点是修改: 同样的条件, 你读取过的数据, 再次读取出来发现值不一样了,只需要锁住满足条件的记录
3、 幻读(phantom read):事务A先修改了某个表的所有纪录的状态字段为已处理,未提交;事务B也在此时新增了一条未处理的记录,并提交了;事务A随后查询记录,却发现有一条记录是未处理的造成幻读现象,幻读仅专指新插入的行 。幻读会造成语义上的问题跟数据一致性问题 。
4、 在可重复读RR隔离级别下,普通查询是快照读,是不会看到别的事务插入的数据的 。因此,幻读在当前读下才会出现 。要用间隙锁解决此问题 。
在说隔离级别之前,你首先要知道,你隔离得越严实,效率就会越低 。因此很多时候,我们都要在二者之间寻找一个平衡点 。SQL标准的事务隔离级别由低到高如下: 上图从上到下的模式会导致系统的并行性能依次降低,安全性依次提高 。
读未提交:别人改数据的事务尚未提交,我在我的事务中也能读到 。
读已提交(Oracle默认):别人改数据的事务已经提交 , 我在我的事务中才能读到 。
可重复读(MySQL默认):别人改数据的事务已经提交 , 我在我的事务中也不去读,以此保证重复读一致性 。
串行:我的事务尚未提交,别人就别想改数据 。
标准跟实现:上面都是关于事务的标准,但是每一种数据库都有不同的实现,比如MySQL InnDB 默认为RR级别,但是不会出现幻读 。因为当事务A更新了所有记录的某个字段,此时事务A会获得对这个表的表锁,因为事务A还没有提交 , 所以事务A获得的锁没有释放,此时事务B在该表插入新记录,会因为无法获得该表的锁,则导致插入操作被阻塞 。只有事务A提交了事务后,释放了锁,事务B才能进行接下去的操作 。所以可以说 MySQL的RR级别的隔离是已经实现解决了脏读 , 不可重复读和幻读的 。
5、MySQL中的锁
无论是Java的并发编程还是数据库的并发操作都会涉及到锁 , 研发人员引入了悲观锁跟乐观锁这样一种锁的设计思想 。
悲观锁:
优点:适合在写多读少的并发环境中使用 , 虽然无法维持非常高的性能,但是在乐观锁无法提更好的性能前提下,可以做到数据的安全性
缺点:加锁会增加系统开销,虽然能保证数据的安全,但数据处理吞吐量低,不适合在读书写少的场合下使用
乐观锁:
优点:在读多写少的并发场景下,可以避免数据库加锁的开销,提高DAO层的响应性能,很多情况下ORM工具都有带有乐观锁的实现,所以这些方法不一定需要我们人为的去实现 。
缺点:在写多读少的并发场景下,即在写操作竞争激烈的情况下,会导致CAS多次重试,冲突频率过高,导致开销比悲观锁更高 。
实现:数据库层面的乐观锁其实跟CAS思想类似, 通数据版本号或者时间戳也可以实现 。
数据库并发场景主要有三种:
读-读:不存在任何问题,也不需要并发控制
读-写:有隔离性问题,可能遇到脏读,幻读 , 不可重复读
写-写:可能存更新丢失问题,比如第一类更新丢失,第二类更新丢失
两类更新丢失问题:
第一类更新丢失:事务A的事务回滚覆盖了事务B已提交的结果 第二类更新丢失:事务A的提交覆盖了事务B已提交的结果
为了合理贯彻落实锁的思想,MySQL中引入了杂七杂八的各种锁:
推荐阅读
- 如何将pdf转word,如何把pdf转为word
- 微信直播花钱推广效果如何,微信直播卖货推流机制
- 模拟经营游戏开发,模拟经营游戏开发成本
- oracle查看表所在表空间,oracle查看表空间下的表
- pca函数python PCA函数R语言
- 下载flutter_windows,下载手游
- java爬虫隐藏表单提交,javaweb爬虫
- go语言成长十年 go语言现状
- wordpress二级目录安装,wordpress 二级域名