00:00
大家好,我是上硅谷Java英语学科的韩延冰,接下来和大家分享一道面试题。这道面试提示请简单介绍spring支持的常用数据库,事物传播属性和事物隔离级别。那么首先呢,我们先了解一下什么是事物的传播属性。哎,我们来看一下啊,这个事物的传播属性呢,呃,就是我们说的这个事物的传播行为,我们来看一下这个介绍简介事物的传播行为,当事物方法被另一个事物方法调用时,必须指定事物应该如何传播那个,那么这个嗯,就是事物的一个传播行为,我们用一句话来概括的话就是这样,诶来看我写的这个注释,事物的传播行为是什么呢?一个方法运行在了一个开启了事物的这个方法中时。当前这个方法是用原来的事物还是开启一个新的事物,那么这个呢,就属于一个事物的传播行为,也就是说我这个方法是,呃,用原来那个事物给我传过来,传播过来还是自己开启一个新的事物,我们来看一下这个情景。
01:04
来看我写这个代码。我们这块呢,有两个接口,一个是booksh service的一个接口里边有一个方法叫purchase买东西。还有一个开里边有一个拆out的方法,这个拆out呢,它要调用我们这个。Purchase方法来实现功能,我们来看一下,看一下我们这个CA的一个实现,在checkout的这个checkout的方法上面加了一个at trans注解,也就是说用我们这个spring的一个声明式事物,哎,来给这个checkout添加了事物,那这个checkout里边调用的是我这个purchase方法来实现功能,来我们打开这个purchase的实现。Process上面呢,也加了这个at trans这个注点,也就是说我这个process呢,也加了spring的生命是事物。这个开设里边这个checkout也加了事物,但是这个checkout呢,是调用了我这个purchase方法,那么现在呢,就属于这种情况,一个开启了一个事物的一个方法,这个purchase方法它添加了事物。
02:04
那么它外层的这个checkout的呢,也添加了事物,那么这个事物呢,在运行的事物,这个port到底是用自己的事物呢,还是使用拆靠的事物,那么这个呢,就属于一个事物的传播行为。那么这个事物的传播行为用什么来设置呢?来看一下我写的这个注释。找到我这个实线,哎,我把这个接口呢,就给关闭掉了。我们的这个事物的传播行为呢,用ADD transactional里边的一个属性叫propagation来进行设置,Propagation的默认值呢是required。哎,那我们先看一下吧,看一下这个事物的传播行为呢,都可以用哪几个值来进行设置来看一下。定义了七种。七种这个类型的传播行为,第一种呢是required,如果有事物在运行,哎,当前的方法就在这个事物内运行,否则就启用一个新的事物,并在自己的事物内运行,这是默认值,一会儿呢,给大家通过代码的方式给大家演示一下。第二个呢是require new,就当前的方法必须启用一个新的事物,哎,也就是说不用原来的事物了,并在自己的这个事物内运行,如果有事物正在运行呢,将它挂起。第三个是support。
03:20
Support,如果有事物在运行,当前的方法就在这个事物内运行,否则呢,它可以不运行在事物中。第四个呢是not supported,就是不not supported啊,当前的方法不应该运行在事物中,也就不支持嘛,Not supported就是不支持的意思就是不应该运行在事物中,如果有事物运行的事物呢,将它挂起,也就是说如果你这个值设置为not support,也就它。不在事物里边运行了啊,就是相当于不开解事物了啊。来下一个叫呃,Mandatory mandatory,当前的方法必须运行在事物内部,如果没有正在运行的事物,就抛出异常。嗯,第六个是never,当前的方法不应该运行在事物中,如果有运行的事物,那就抛出异常。第七个是nated,如果有事物在运行,当前的方法就应该在这个事物的嵌到事务内运行,否则就启动一个新的事物,并在它自己的事物内运行。不过我们常用的呢,其实就是默认这个required和require new,那下面啊,我就通过这个代码的方式呢,给大家这个测试一下。
04:23
它默认值啊,默认值是require的,如果有事物在运行,当前的方法就在这个事物内运行,否则呢,就启动一个新的事物,也就是说如果你的值是默认值是属于块的话,哎,它就在当前的一个方法的一个事物内运行,那我们来看一下我们这个代码,现在呢,我们这个port这个方法,这个开启了事物加了at trans的这个注解。开里边的checkout也加了十物,现在port运行到了这个开启了事物的checkout里边,那如果是默认值的话,Port就应该使用这个checkout的事物,那么我们来看一下在checkout里边,诶有一个for循环,有一个for循环,那我们来看一下我们这个测试,来打开我们这个test test。
05:09
找到我们这个TX test,诶我把它打开来,我们现在呢,呃,调用这个测试这个cash,因为我这个cash里边呢,传的这一个参数,一个是用户的ID,一个是list,诶一个是list,那在这里边呢,我遍历这个list,也就是说如果这个list里边诶有几个IDISBN,这是呃国际标准书号的一个缩写啊,如果有这个执行多次,那就相当于我要调用多次这个port。也调用这个多次的这个ports,那我们来看一下啊,由于这个checkout呢,它添加添加的事物,也就是说我每调一次这个port,诶那这个诶用的都是这个checkout的事物,也就说我要有多个操作的话,那应该用的都是这个checkout的一个事物,也就是说这多多个操作,要么都完成,要么都不完成,这根据我们事物的这个。
06:01
呃,原子性啊,要么都完成,要么都不完成,好,那下面啊,我们来看一下我们这个测试里边的代码,我自己创建了一个a list里边呢,添加了两个ID,一个是1001,一个是1002,那我们我们这个测试啊,操作的是我数据库里边这张表,我们来看一下数据库里边呢,有三张表,一个是account,也就是我里有一个用户,现在呢,我的用户里边的余额是100块钱。下面呢有两张表,一个是book表,哎,里边呢有两本书。第一本书的idbn,哎就是国际标准书号,哎,就是ISBN啊,它的这个国际标准书号是1001,它的价格呢是60,第二本书呢是1002,它的价格是50。还有一个表叫bookto,就是图出的库存1001和1002,它现现在的库存呢,都是100,好,那现在我们来看一下啊,我现在呢,我这个账户是100块钱。
07:00
我的图书呢,是60和50加起来一共是110,也就是说我现在100块钱是不足以买这两本图书的,诶,不足以买这两本图书啊,那现在我们测试一下,看到底是一本也买不成功,还是能买成功一本,那现在呢,大家分析一下,哎,根据我们这个事物的传播行为来看一下啊,如果是默认值的话,大家再来看,如果有事物呢,当前的方法就在这个事物的运行,否则呢,就开启一个新的事物,也就是说现在我买1001和买1002在同一个事物里边。那要在同一个事物里边,根据我们这个事物的这个原子性,要么都完成,要么都不完成,那现在我们这种情况,我的余额是100可以买成功1001,但是呢不能买成功1002,因为你买成功1001之后呢,你的账户余额100减60变成40了,40不足以买50这本图书,所以呢,第一本能买成功,第二本就买失败了,那么到底最终的结果是能买成功一本,还是一本都买不成功呢?我们来测试一下。
08:07
来我在这右键注意啊,我这一块呢,有一个例子里边我要买两本书,现在是1001和1002,我们再看一下这个拆out的实现嘛,来看这块要便利这个例子,那遍利这个例子呢,要调book source里边这个purchase方法啊。调这个方法,诶,扣我这个账户的一个余额,哎,扣账户的余额啊,根据这个图书的一个价格,这里边把这个isb传进来了,也就是说我第一次买要买这个1001,第二次呢要买1002,因为list里边有两本图书嘛,哎,两个图书的一个国际标准书号,好,下面我们来测试一下,来右键。哎,来测试一下,看能不能买成功。是能买成功一本还是两本都不成功这块这个错是因为什么啊,超出我这个余额的一个范围了,因为我这个数据库里边呢,这个余额我给他设定的这个啊,来我们的右键改变这个表来看一下,我这个余额呢,是按三就是无符号的,也就是说不能是负数。
09:07
那我现在的这个账户余额呢,是100,如果减一百一就变成负数了,所以呢,报了这样的一个异常,好,那这个不是我们关心的,我们来最终看一下我这个账户余额有没有变,刷新一下,诶发现呢并没有买成功,来看我的图书的库存也没有更新,哎,也没有更新,也就是说一本也没有买成功,那为什么是这样的呢?我们来分析一下。如果是默认值的话,事物的传播行为如果是默认值的话,也就是说它会使用原来的事物来看我这个port方法。我们虽然开启了事物。来打开它的实现。添加了事物,但是由于我们的事物的传播行为使用的是默认值,它会使用checkout的这个事物,那如果要使用checkout的事物,哎,我们刚刚发现在我的这一个。例子里边呢,有两本图书,哎,一个是1001,一个是1002,一个是1002,这样啊,我来开启一下呢,我们用一下这个画笔。
10:05
给大家标注一下。好,现在这个list里边呢,嗯,我要这个买两次图书,第一次呢,我这个,呃,List里边我第一次呢要买1001,哎,第二次呢,我要买1002,哎第一我的账户余额是100,这个1001,它的价格呢是60,那按说第一次呢可以买成功,第二次由于你这个100减60等于40买第二本书,第二本书的价格呢是50,所以呢第二次要失败。但是这个买1001和买1002掉的都是porter方法,这两个操作呢,是在同一个事物里边,因为它默认用的是checkout的事物,诶,但是呢,买1002失败了,所以呢,这个时候呢啊,根据这个事物的原子性,要么都成功要么都失败,不能一个成功一个失败,所以呢,他要回滚。
11:01
那要回滚的话,也就相当于我买101也买失败了,所以呢,最终啊,我的这个账户余额没有变,是100,诶,也就相当于我一本图书都没有买成功,那么我们能不能让他买成功一本呢?可以,也就是说我们可以把这个值改成require new。也就把事物的传播行为这个值呢,改成request new,当前的方法必须启用新的事物,并在自己的事物内运行,那如果要改成request new的话,也就是说我port再调port,我要用自己的一个开启一个新的事物,不再用checkout的事物。好,我们现在来改一下,通过proagation这个属性来设置事物的传播行为,诶,默认值是require的默认值啊,使用原来的事物,也就是也就是使用我们拆开的事物,那现在我们把把它改成request new,就将原来的事物挂起,开启一个新的事物来。括号,我们来用这个propagation,哎,用这个属性来设置等于等于什么呢?哎,Out,斜杠我们来看一下,我们来改这个requires new。
12:03
好,现在呢,我让这个port每次掉port的时候都开启一个新的事物,我们这个时候呢,再来测试一次,看能不能买成功一本来右键。走。好诶同样报错,那报错是因为你买第二次的时候超范围了啊,这个我们就不看了,哎来现在啊,我来刷新一下我的账户余额,刷新一下,然后变成40了,哎来看我这个第一本图书呢是60,所以呢,100减60等于40没问题,来看图书的库存。A变成99了,也就是说我如果把事的传播行为改成request new的话,诶确实呢,可以买成功一本,那这个这个时候是什么情况呢?我们再来看一下啊,打开我们的开始这个实现。由于现在我的P的数。传播这个。属性啊,设置为了request new,也就是说我要开启一个新的事物,当买101。
13:04
和买1002用的就不再是同一个事物了,虽然你checkoutd也加了事物,但是呢,我不使用你的,每次调用port的时候,我会开启一个新的事物,也就说买1001是一个事物,买1002也是一个事物,根据事物的隔离性,也就互相之间没有影响,那么你买1001跟买1002之间是没有影响的,虽然你1001成功了,1002这是失败的啊,1002失败了,但是呢,哎,不会影响1001这次行为,所以呢,最终的结果是1001买成功,买成功了,一本1002,哎,没有买成功,好,那这个情况呢,啊,我们下边有一个图,我们来看一下这个图,结合这个图呢,我们再分析一下这块,就是我们这个接口啊,我已经写过了,我们来看。说明一下。如果是默认require require,现在啊,这个book service,这个purchase方法被另一个事物方法checkout的调用,哎,我们现在呢,就属于这种情况。
14:02
Checkout呢?呃,Port被checkout调用啊,调用就是这种情况啊,它默认会在现有的事物内运行,也就是说这个port会使用checkout的事物啊,这个默认的传播。行为呢,就是required required,这是默认值啊,认值,因此呢,在check的方法开始和终止边界的只有一个事物,也就是说用的都是这个checkout的事物,这个事物只有在checkout的方法结束时,哎,被提交结果呢,用户一本书都买不了,我们刚刚已经测试过了,确实如果使用默认值REQUIRED1本图书都买不成功,好,我们再来分析一下。再来分析一下啊checkout呢,假设现在有个事物是T,诶,由于呢这个port。这个使用的这个事物传播行为,哎,还是这个块的,所以啊,他用的诶用的就是我这个T1,哎,这是这块啊,这个叫T1啊check考的是T1,那呃,我们测试的时候,哎,T一开始当我买1001的时候,由于你的process用的是默认值required,所以我用的还是这个T1,这个事物买1001我们买成功了,哎,当我买1002掉第二次破的时候,由于用的还是T1啊这块呢,由于你的余额不足,余额不足这块买失败了。
15:15
但是呢,1001和1002现在处在同一个事物里边,T1里边根据事物的原子性,要么都成功,要么都失败,由于1002失败了,所以呢最终要回滚,所以呢,导致的结果是一本图书都没有买成功。那么当我们改成requests new的时候来看,表示该方法必须启用一个新的事物,也就是说在port。这个方法上,如果哎,我改成了这个requires new,现在改成了它这个事物的传播属性不是默认值了,破呢,每次掉发的时候都会开启一个新的事物。来看下面这个图。这种情况是这个样子的,还是我们在执行checkout的时候呢,T一开始,当我买1001的时候,由于port的这个事物传播属性呢,变成了requests new,我就将T1挂起,也就是说我不用你这个事物,我自己开启一个新的事物,那T2开始。
16:12
当第一本图书1001买成功之后,也就是第一个成功了,那T2就结束,我T1呢继续。继续执行,但是呢,呃,我们这个由于啊,我拆out里边没有调其他的方法,调的都是port方法,就是调了两次port,所以呢,相当于这个题没有用啊,哎,没有这个根本就没有使用这个T1这个事物,当我买1002的时候,由于呢,还是掉破方法,我的事物传播属性呢,还是request,所以呢,我还会把T1挂起,我又开启了一个新的事物,买1001是T2,买100,买1002的时候呢,买101用的是T2啊,买1002的时候,我又开启了一个新的事物,比是T3,那1002,哎买失败了,那买失败了,T3结束了,但是呢,T3跟T2呢,他两个之间是没有影响的,给你事物的这个隔离性啊,隔离性这个失败了,那不再影响我的1001,所以当我的这个书的,诶,这个属性啊是request new的时候,能买成功一本,这也是我们这的这个测试的结果啊,1001买成功了,1002没有买成功,因为他现在用的不是同一个事物了,是分别开启了一个新的事物。
17:15
诶来再看一下我们这个数据库,这呢结果呢,1001减了一本,我的这个账户余额呢,减了60,因为11001的突出的价格是60,是四,呃60,所以我减了60啊这是这块啊,就是这个。事物的一个,呃,传播行为给大家呢,通过代码的方式啊,给大家演示了这两种,当然啊,第一种呢,肯定是块呢,是默认值啊,我也可以给你测试一下,如果你设置为这个铝块的也是两本都不买,都买不成功的,哎来来测试一下啊奥这斜杠。用这个required。块的,这是默认值,我们来保存一下,再来测一下,那我把这个账户呢,我再改一下啊,改成100。100好。诶,来我保存一下。
18:00
我们把这个图出的库存呢,再改成100。好。哎,如果你这个值是required,就是默认值,一本也买不成功,因为他用的是这个CA里边这个checkout的事物,用的是它买1001和1002用的是同一个事物,要么都成功,要么都失败,来测试一下右键走。好,哎,来看一下结果。刷新诶库存没有变,来看账户余额刷新诶也没有变,哎,这是我们这个呃事物的一个传播行为,诶给大家通过代码的方式就给大家演示这两个属性了啊其他的呢,哎,大家可以自己来测试一下,好下面啊我们来说这个。隔离级别。事物的隔离级别,那在说事物的隔离级别之前啊,我们先说一下这个在并发时候呢所导致的问题,我们来往下看啊,隔离级别数据库,嗯,数据库事物并发的问题有哪些呢?有这三个问题,一个是脏毒,一个是不可重复读,一个是换读,那什么是脏毒呢?嗯,也就是说T1将某条记录的这个,比如edge值从20修改为30,修改为30。
19:15
T2呢,读取了T1更新后的这个值,哎,30,但是注意啊T1,诶这个时候呢,T1回滚,那A值呢,又恢复到了20,那这个时候啊,T2读到这个30呢,就是一个无效的值,这种情况呢,就属于脏毒,用一句简单的话来概括就是什么呢。And。这个当前这个事物。哎,读到了其他事物。提这个更新,但是还没有提交的这个值就属于一个脏毒,因为如果啊其他事物把它给回滚的话,你读的那个值就是无效的,你可以认为是脏的,所以啊称为脏毒,哎,这是这一块这个脏读的问题啊,也就是说你读到了其他人。更新,但是还没有提交的值,这个时候呢就属于脏读,那第二种情况是不可重复读,比如T1,哎,这个TRACTION01我就简称为T1了啊,T1读取了这个A级的值,比如数据库里面某一个字段A的值是20,然后T2呢,将它修改为了30,哎,但是这种情况肯定是提交过的啊,提交过的有只有藏读这种方式,你读到了别人没有提交的这个值,属于属于藏读的范畴。
20:21
这个不可重复读,包括下边的换读,都是别人,就是其他的事物已经提交过的啊,已经提交过的好来看,T2呢,将这个A级值修改为了30,也就是T1啊,有可能这次事物里边,哎,你有多次这个获取,多次获取,但是呢,在你第二次读取之前,可能其他事物把它给修改了,T1读到这个值为20 T2呢,将它更新为了30,当然了,已经提交过了啊,T1呢,再次读取这个值之后,就变成30了,和第一次读取的不一致,也就是没有重复,不可重复嘛,就是不可以重复嘛,所以这个时候啊,就引起了这个不可重复读这种情况,比如你在读的期间。第一次读是20,在第二次跟第一次之间,其他的事物把它给修改为30,并且提交了,这时候你再读的话就变成30了,跟第一次的值没有重复,不可重复,所以呢,这是不可重复读,不可重复读,那么什么是换读呢?T读取了,嗯,比如这个表中的一部分数据。
21:15
在这个他第二次读的时候呢,T2另一个时候呢,向里边插入了新的行,就本来你读的,呃,读这个数据的时候,假设就有两行,就有两条记录,哎,但是你在下一次读的时候呢,哎,发现多了一些新的行,因为这个另一个事物插入了一新的数据嘛,哎插入了一个新行,所以啊就感觉出现幻觉似的,第一次呢,明明是两行,哎我再读的话变成了比如四行或者五行,就插入了好多行,哎感觉好像出现了幻觉,所以啊,这个是幻读,这是幻读,这是这一块啊事物这个呃,数据库事物并发之后引起的问题,第一个是脏毒,哎简单来说就是你读到了别人更新但是没有提交的数据。哎,第二第三就是都是别人已经提交过的,哎,不可重复什么呢?你第一次读的值和第第二次读的值呢,是不一致,也就是不可重复,这属于不可重复的重复读的情况,换读是什么呢?
22:08
你读完这个,第一次读完这个数据,第二次再读时候发现读了好多行,好像出现幻觉似的,哎,这个是幻读,好,那这个事物的隔离级别都有哪些呢?我们来看一下啊,第一个呢是读未提交,就是能读到啊别人没有提交的这个值,哎,这个隔离级别是越来越高的啊,第一种情况是读未提交,当然了,你如果这个隔离级别是读未提交的话,上面这三种问题呢,都难避免,都不可以避免啊,因为你读可以读到别人没有提交的这个数据,所以呢,藏毒肯定避免不了。第二种呢是读已提交,就只能读到别人提交的这个值,那这个呢,脏读就可以避免了,第三个是可重复读,那这个呢,脏读跟不可重复读都可以避免,第四个是串行化,也叫序列化,这个呢脏读、不可重复读和换毒都可以避免。哎,这个级别最高啊,但是呢,并不是说什么隔离级别越高越好啊,嗯,因为你这个。
23:03
隔离级别越高的话,这个性能就就差了啊,就差了,我们这个在在开发的时候呢,哎,这个用的基本上就用这个读已提交,因为。其他事物已经提交过了,这个数据就是真实有效的,哎,这个是我们这个常用的一个值叫读未提交,好,下面我们也有一个表来看一下,嗯,读未提交的话,脏读问题有,不可重复读也有,换读也有,呃,读已提交的话。哎,单独就避免了,不可重复读,有换读也有,嗯,可重复读,就是可以重复,嗯,这个时候就相当于你在读的时候给他上了这个数据,上了一把锁,其他的数据呢。更新不了啊,更新不了这个时候呢,这个脏读不可重复读可以避免,但是换读哎,避免不了,因为呢,其他人虽然不能更新这个数据,但是我可以插入一些新的行,哎。那这个最后的序列化脏毒可以避免,不可重复读可以避免,换读也可以避免,这时候呢,相当于你把这个你你可以认为啊,把这个表呢,给上了一把锁,其他人不能插入一些新的内容了,哎,就是这块隔离级别啊。
24:04
那这个关于对隔离级别的一个,呃,支持程度,我们来看一下下面啊这个这是说了两种数据库,Oracle呢,呃,它只支持两种隔离级别,一个是读一提交,一个是可重复读,嗯可呃一个这个不是啊,Oracle呢只支持两种,一个是读一读一提交,一个是序列化啊,它只支持两种,像这一个读未提交啊,包括可重复读呢,它不支持,而且Oracle默认的这个隔离级别呢,是这个已提交,就是默认的隔离级别,MYSQ呢,四种都支持。嗯,读未提交啊,嗯,读未提交啊,还有可重复读啊,包括序列化呀,MYSQL都支持,MYSQL默认的是。可重复读,这是他默问的隔离级别,那下面啊,我就给大家演示一下,因为我现在连的数据库呢,就是MYSQL,看一下这个默认值呢,是不是啊。是不是可重复读来给大家演示一下,这块呢,也说了啊,在这个事物里边怎么来设置事物的隔离级别,呃,隔离级别怎么来设置,用个isol这个属性来进行设置啊,设置事物的隔离级别,嗯,可重复读就是my circle默认的隔离级别,读一提交是Oracle默认的隔离级别,那现在呢,我连的是这个my circle,哎,所以呢,我来逗号,我来加一下这个isolation这个属性等于out斜杠,我们来看一下这里边有一个default default呢就是默认值,我们来看一下my circle的默认值,说了啊,默认的是可重复读。
25:26
哎,MYSQL默认的是可重复读,嗯,可重复读,我们来看一下是不是可重复读,那现在呢,我需要把这个post,我只测这个post就行了,我把这个呢注释掉啊注释掉。我要干啥呢?我要在这里边呢,读两次,读两次,把这些都除掉。哎,我再来获取一下这个图书的一个价格。P Du。点儿。Get一个by press,好,哎,进去哎。CTRL1。
26:00
好,诶,我们又得到了一个book book,诶,好,就默认值吧,来,再打印一下。好,这打印一下,当然了,我们这上面呢也打印一下。哎,现在我这个port里边呢,嗯,仅仅就是查询了一下这个图书的价格,图纸价格好,那现在啊,我们把这一块呢,打个断点,在port这一块打一个断点,好在这打个断点,然后我们来到这个测试。在这块我们要测这个方法。所以呢,我们就用这个testbook service里边这个调这个purchase方法这块,这样我们就来测它了啊,那这呢,我来右键来第八个运行一下。Debug as。让他停在这儿。填到debug透视图,好,来到了debug透视图,现在呢,我要调这个book service,呃,Book service实现的一个破方法,我们来走一步,快捷键是F6啊,我们来走。
27:05
走好,现在呢,查出来了这个价格,注意啊,答案的价格是60,好,那下面呢,我们通过这种方式啊,模拟第二个事物,另一个事物呢,把这个值给它修改掉,把图出的价格本来是60,我给它改成600。好,600之后呢,我来保存一下,好现在我把这个值给改掉了,呃,由于这个my circle默认的隔离别是可重复读,也就意味着我第二次读的话,它还应应该还是60,因为可以重复嘛,可重复读,但是现在数据库里边已经变成600了啊,我们来看一下是不是60。走。再来打印一下,哎,没问题,确实是60,哎,因为这个my circle它默认的这个隔离级别是可重复读,因为在这一个事物里边呢,读到这个值是可可以重复的啊,是一样的一样的,哎,那。我现在呢,把它改成读已提交,因为这个呢是我们开发出常用的啊,常用的这个隔离级别好来把这个改掉。
28:06
斜杠。这里边也有啊,Repeatable就是可重复读哎,可重复读,你如果选它的话,就是我们的一个MYS的一个默认值啊,默认值现在呢,我来点一个read committed读已提交保存好,现在呢,我要把它修改之后呢,我们再来测试一下。来,右键再d bug as。好,现在呢,我们再来。查询图书的价格,打印图书的价格600,好,那在第二次查询之前,同样我把图书的价格再改回来,改成60。好,哎,已经保存过了,下面呢,注意啊,我现在的隔离级别是独已提交另一个事物已经把它给提交过了,已经变成60了,来现在我们再来查询走。诶看一下这个图书的价格是多少,诶60诶没问题,没问题,现在呢啊就是读已提交,诶读已提交就是只要是别人提交过的数据,哎,我就可以得到啊,就可以读到,那这种呢啊显然是这个合法的,因为别人已经提交过了啊,已经交过了,把数据库里边的值已经更新过了,所以这也是我们这个开发的时候呢,常用的一个隔离级别都一提交,因为这个不是隔离级别越高越好,嗯越高呢,这个性能就差了啊,所以呢,我们这个,嗯。
29:30
选择的是这个读已提交好啊,这是我们这个给大家分享的这个面试题诶。Spring支持的一个常用常用数据库,事物传播属性以及这个事物的隔离级别,哎,这个传播属性呢,有七个,给大家演示了两个,事物的隔离级别呢,有四个,也是通过代码的方式啊,给大家演示了两个,好。
我来说两句