相信大部分小伙伴在面试过程当中,只会针对面试官提出的表面问题来进行回答。其实否则,面试官问的每个问题都是通过深思熟虑的,面试的时间相对来讲也是短暂的,面试官不可能在很短的时间内就对你很是了解,他想经过几个问题来考察你所掌握的知识的深度和广度,若是你只是回答面试官表面问你的问题,向挤牙膏同样,问一点,答一点,结果不用说,确定是凉凉了。面试
说说什么是事务?并发事务会带来哪些问题呢?sql
表面上看,面试官是问了两个问题。一个是:什么是事务,也就是让你说说事务的基本概念;另外一个是:并发事务会带来哪些问题。数据库
实则否则,听到面试官这样问,你不要随意回答。要用极短的时间思考一下,面试官究竟想要获得什么答案。设计模式
对于第一个问题:说说什么是事务?就只是让你简单的说说事务的基本概念吗?基本概念相信是个学过数据库的小学生都会,面试官为何会问你这个问题呢?此时,你须要揣测面试官的心理。此时的面试官其实想问你的不久是事务的基本概念,并且他也想让你说出事务的特性,也就是四大属性。这才是这个问题的核心所在!微信
对于第二个问题:并发事务会带来哪些问题呢?就只是想问一下会带来哪些问题吗?知道问题,不知道如何解决问题,这样的面试者面试官能要吗?究其本质,面试官是想问你并发事务会带来哪些问题,有哪些解决方案可以解决这些问题!这才是面试官想要的答案!数据结构
综上,面试官本质上问的问题是:什么是事务?事务的四大特性是什么?并发事务会带来哪些问题?有哪些解决方案?你只有深入理解了面试官提问的本质,才能更好的回答面试官所提出的问题。否则,你应付面试官,面试官也会应付你。并发
事务的概念理解起来还比较简单的:事务是指做为单个逻辑工做单元执行的一系列操做,要么彻底地执行,要么彻底地不执行。 事务处理能够确保除非事务性单元内的全部操做都成功完成,不然不会永久更新面向数据的资源。经过将一组相关操做组合为一个要么所有成功要么所有失败的单元,能够简化错误恢复并使应用程序更加可靠。一个逻辑工做单元要成为事务,必须知足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工做单位,由DBMS中的事务管理子系统负责事务的处理。分布式
事务必须是原子工做单元;对于其数据修改,要么全都执行,要么全都不执行。好比转帐,要么转帐成功,帐户余额增长(减小);要么转帐失败,帐户余额不变。微服务
事务在完成时,必须使全部的数据都保持一致状态。在相关数据库中,全部规则都必须应用于事务的修改,以保持全部数据的完整性。事务结束时,全部的内部数据结构(如 B 树索引或双向链表)都必须是正确的。某些维护一致性的责任由应用程序开发人员承担,他们必须确保应用程序已强制全部已知的完整性约束。例如,当开发用于转账的应用程序时,应避免在转账过程当中任意移动小数点。高并发
由并发事务所做的修改必须与任何其它并发事务所做的修改隔离。事务查看数据时数据所处的状态,要么是另外一并发事务修改它以前的状态,要么是另外一事务修改它以后的状态,事务不会查看中间状态的数据。这称为隔离性,由于它可以从新装载起始数据,而且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。当事务可序列化时将得到最高的隔离级别。在此级别上,从一组可并行执行的事务得到的结果与经过连续运行每一个事务所得到的结果相同。因为高度隔离会限制可并行执行的事务数,因此一些应用程序下降隔离级别以换取更大的吞吐量。
事务完成以后,它对于系统的影响是永久性的。该修改即便出现致命的系统故障也将一直保持。
例如咱们在使用JDBC操做数据库时,在提交事务方法后,提示用户事务操做完成,当咱们程序执行完成直到看到提示后,就能够认定事务以及正确提交,即便这时候数据库出现了问题,也必需要将咱们的事务彻底执行完成,不然就会形成咱们看到提示事务处理完毕,可是数据库由于故障而没有执行事务的重大错误。
当两个或多个事务选择同一行,而后基于最初选定的值更新该行时,会发生丢失更新问题。每一个事务都不知道其它事务的存在。最后的更新将重写由其它事务所作的更新,这将致使数据丢失。
例如,T1和T2同时修改一条数据,T2的修改覆盖了T1的修改;若是在T1以后T2才能进行更改,则能够避免该问题。
咱们来看一个经典的转帐问题,开始小明和小刚都有1000元钱,在事务T1中,小明为小刚转帐100元,在事务T2中,小刚为小明转帐200元。则正常状况下,结果为:小明有1100元,小刚为900元。若是发生了脏写的问题,则结果可能为:小明1200元,小刚800元。以下图所示。
一个事务正在对一条记录作修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另外一个事务也来读取同一条记录,若是不加控制,第二个事务读取了这些“脏”数据,并据此作进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫作”脏读”。
例如:在事务T1中,小明为小刚转帐100元,在转帐的过程当中,事务未提交或者未回滚时,此时事务T2读取到了事务T1未提交的内容,也就是说在事务T2中读取到了小明900元,小刚1100元的记录。能够用下图表示。
一个事务在读取某些数据后的某个时间,再次读取之前读过的数据,却发现其读出的数据已经发生了改变!这种现象就叫作“不可重复读”。
指事务T2读取数据后,事务T1执行更新操做,使T2没法读取前一次结果。
例如,在事务T1中执行小明为小刚转帐100元的操做,在事务未提交以前,在事务T2中读取的数据仍是小明为1000元,小刚为1000元。待事务T1提交后,事务T2中读取的数据为小明900元,小刚1100元。以下图所示。
一个事务按相同的查询条件从新读取之前检索过的数据,却发现其余事务插入了知足其查询条件的新数据,这种现象就称为“幻读”。
事务t2读取到了事务t1体提交的新增、删除数据,不符合隔离性。
幻读和不可重复读都是读取了另外一条已经提交的事务(这点就脏读不一样),所不一样的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据总体(好比数据的个数)。
例如,在事务T1中插入两条分别为小明和小刚的数据,在事务提交以前,事务T2中读取的数据记录为10,随后事务T1提交,则在事务T2中读取的记录为12,以下所示。
为了不上面出现的几种状况,在标准SQL规范中,定义了4个事务隔离级别,不一样的隔离级别对事务的处理不一样。如下四种不一样的隔离级别限制由低到高,性能从高到底。
读未提交(Read Uncommitted):容许脏读取,但不容许更新丢失。若是一个事务已经开始写数据,则另一个事务则不容许同时进行写操做,但容许其余事务读此行数据。该隔离级别能够经过“排他写锁”实现。
不可避免 脏读、不可重复读、虚读。
读已提交(Read Committed):容许不可重复读取,但不容许脏读取。这能够经过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务容许其余事务继续访问该行数据,可是未提交的写事务将会禁止其余事务访问该行。
可避免 脏读,不可避免 不可重复读、虚读。Oracle采用读已提交。
可重复读取(Repeatable Read):禁止不可重复读取和脏读取,可是有时可能出现幻读数据。这能够经过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但容许读事务),写事务则禁止任何其余事务。
可避免 脏读、不可重复读, 不可避免 虚读。MySQL采用可重复读。
序列化(Serializable):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。仅仅经过“行级锁”是没法实现事务序列化的,必须经过其余机制保证新插入的数据不会被刚执行查询操做的事务访问到。
可避免 脏读、不可重复读、幻读状况的发生。
事务的四种隔离级别总结起来以下图所示。
常看当前数据库的事务隔离级别: show variables like 'tx_isolation';
设置事务隔离级别:set tx_isolation='REPEATABLE-READ';
Mysql默认的事务隔离级别是可重复读,用Spring开发程序时,若是不设置隔离级别默认用Mysql设置的隔离级别,若是Spring设置了就用已经设置的隔离级别
关注「 冰河技术 」微信公众号,后台回复 “设计模式” 关键字领取《深刻浅出Java 23种设计模式》PDF文档。回复“Java8”关键字领取《Java8新特性教程》PDF文档。回复“限流”关键字获取《亿级流量下的分布式限流解决方案》PDF文档,三本PDF均是由冰河原创并整理的超硬核教程,面试必备!!
好了,今天就聊到这儿吧!别忘了点个赞,给个在看和转发,让更多的人看到,一块儿学习,一块儿进步!!
若是你以为冰河写的还不错,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习高并发、分布式、微服务、大数据、互联网和云原生技术,「 冰河技术 」微信公众号更新了大量技术专题,每一篇技术文章干货满满!很多读者已经经过阅读「 冰河技术 」微信公众号文章,吊打面试官,成功跳槽到大厂;也有很多读者实现了技术上的飞跃,成为公司的技术骨干!若是你也想像他们同样提高本身的能力,实现技术能力的飞跃,进大厂,升职加薪,那就关注「 冰河技术 」微信公众号吧,天天更新超硬核技术干货,让你对如何提高技术能力再也不迷茫!