数据库事务(一)------脏读,虚读,不可重复读

         今天梳理下数据库事务,东一点西一点的容易忘。

        说到事务,首先要了解下事务,事务主要有四个特性,原子性,一致性,隔离性,持久性。我们具体来看下。

事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在计算机术语中,事务通常就是指数据库事务。

原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。

          为什么需要事务呢?最典型的就是转账问题,假设A,B各有1000元,A转账给B100元,那么首先是A减去100,然后B加上100。这个肯定是要么一起成功,要么一起失败,如果A减了100,系统问题或者断电问题,程序运行不了了,结果B没收到钱,那A就要哭了,哈哈,这个大家都懂,不多说了哈。

         以上都是一些基础的概念性问题,如果哪位小伙伴不太明白,可以找点资料翻看下哈,下面我们接着说。

        我们知道对数据库的操作有增、删、改、查,如果在事务中一般都会有多个操作,或者查改,或者查增,等等,如果只是一个数据库操作,那其实不需要标明事务,数据库一般有内置的事务服务,直接进行操作的。

        我们想象一下,如果事务一修改A的金额为900,还没有提交,事务二想去查询A的金额或者想对A的金额加100,这个时候如果认为数据库的钱是900的话,明显是不行的,因为事务一还没有commit,如果事务一rollback,那就又出乐子了,哈哈。

       当然,最简单的方式就是每个事务必须独立运行,这个事务不结束,其他事务不允许操作数据库表,当然这种绝对是安全的,不过这样的话,对性能就不太友好了,比如:事务三对学生表修改张三的成绩为120,事务四修改李四的成绩为130,这两个事务有关联么?有!修改的是同一张表,但是他们的数据并没有任何关系,并不会相互影响,这个时候如果不允许事务四操作,明显是不合理的,等于在浪费资源。

       为了处理数据库中事务的操作,数据库中有一套整体的模式,包括事务的处理,锁的处理其中还牵涉到索引等,我们来慢慢看。

       先了解几个基本的概念脏读,虚读,不可重复读。

       一、脏读:即为事务1第二次读取时,读到了事务2未提交的数据。若事务2回滚,则事务1第二次读取时,读到了脏数据。

       举例:学生表中张三的成绩是59,事务一修改了学生表张三的成绩69,但是事务还没有提交,这个时候事务二来读取张三的成绩,读到了69,但是事务一出问题回滚了,数据库学生表中张三还是59,明显事务二读的数据不对,“脏读”了。

      二、不可重复读:事务一第二次查询某条数据时,读到了事务二提交的修改的该数据

       举例:事务一第一次读取张三的成绩是59(事务没结束),这个时候,事务二改了张三的成绩为69并且commit,这时候事务一又去读取张三的成绩,哎?变成69了,就是重复读数据不一致,不可重复读。

      三、虚读(也说幻读):事务2在事务1第二次读取时,提交了数据。导致事务1前后两次读取的数据量不一致

      举例:事务一读取学生表总共有45人(事务没结束),这个时候事务二突然插入一条学生数据,事务一再次读取总数,发现变成了46条数据,就是两次读取的数据数量不一致。

虚读和不可重复读的区别:不可重复读针对的是修改某一条数据,前后数据不一致,虚读针对的是批量的数据,针对的是数据量,是一个数字

         也许你会问,就脏读、虚读、不可重复读就能搞定事务?事务之间的冲突不止这几种吧?

         在我个人看来,脏读、虚读、不可重复读是对数据库事务的宏观控制,只是对底层一些锁机制和一些事务处理的表现,想要更深入的了解事务,还有进一步深入数据库的另一项知识----数据库锁。

         这个留到后面说,先把脏读、虚读、不可重复读说完。

        既然有了脏读、虚读、不可重复读这三种情况,肯定有相关的配置,看你可以容忍哪种,其实就是在数据安全性和性能之间做一个权衡,当然我们是尽量在保证数据安全的情况下,尽可能的提高效率和资源的利用率。

说道这里就要说一下事务的隔离级别了,分别是Read uncommitted(未提交就读了,就是脏读呗),Read committed(提交后再读,事务二提交,事务一又读了呗,幻读和不可重复读都可能会出现),Repeatable read(重新读,不可重复读不会发生,幻读可能会),Serializable(直接同步,这个事务不完成,别的事务一边去,绝对安全,杠杠的,就是太耗资源了)。

        这里再说下Repeatable read,重复读,后面会提到,数据库有读锁和写锁,一般来说加了读锁之后,是不会把这条数据锁死,也就是允许修改的,所以虚读(幻读)还是有可能发生,不过这种不算数据错误,如果有问题也可以进行事务回滚,所以这种错误一般是可以接受的。

          下面秀张图,

√:可能会出现       ×:不会出现
  脏读 不可重复读 幻读
Read uncommitted
Read committed ×
Repeatable read × ×
Seralizable × × ×

mysql 默认的事务隔离级别是Repeatable read,Oracle默认的事务隔离级别是Read committed,当然也可以进行设置。Spring中也有一套配套的事务隔离级别,一般是默认使用数据库的,这个后面有空再说吧,今天先说到这边,下次就聊下数据库的锁吧,内容有点多,翻下资料先,O(∩_∩)O哈哈~

感觉还行的话,点个赞呗~

No sacrifice ,no victory~

猜你喜欢

转载自blog.csdn.net/zsah2011/article/details/108999289
今日推荐