最后
针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。
上述的面试题答案都整理成文档笔记。 也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
3.1 查看事务隔离级别
SHOW VARIABLES LIKE 'tx_isolation';
查看全局的事务隔离级别
SHOW GLOBAL VARIABLES LIKE 'tx_isolation';
使用系统变量查询
SELECT @@global.tx_isolation;
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
3.2 设置MysQL的事务隔离级别
语法
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{
REPEATABLE READ
| READ COMMITTED
| READ UNCOMMITTED
| SERIALIZABLE
}
GLOBAL
:设置全局的事务隔离级别
SESSION
:设置当前session的事务隔离级别,如果语句没有指定GLOBAL或SESSION,默认值为SESSION
使用系统变量设置事务隔离级别
SET GLOBAL tx_isolation='REPEATABLE-READ';
SET SESSION tx_isolation='SERIALIZABLE';
下面实际操作中使用到的一些并发控制语句,可看上面的操作介绍
作为演示:product表
| productId | productName | productPrice | productCount |
| — | — | — | — |
| 1 | xiaomi | 1999 | 100 |
带着上面的我们来看一下,事务在没有隔离性的情况下,会引发哪些问题?
同时打开两个窗口模拟2个用户并发访问数据库
4.1 事务隔离级别设置为read uncommitted
查询事务隔离级别
SELECT @@tx_isolation;
设置隔离级别为未提交读:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
注意:需要同时修改两个窗口的事务隔离级别
以下我们以两位用户抢小米手机为例
| 时间轴 | 事务A | 事务B |
| — | — | — |
| T1 | start transaction; | |
| T2 | select p.productName,p.productCount from product p where p.productId=1;(productCount =100) | |
| T3 | | start transaction; |
| T4 | | select p.productName,p.productCount from product p where p.productId=1;(productCount =100) |
| T5 | | update product set productCount = 99 where productId = 1; |
| T6 | select p.productName,p.productCount from product p where p.productId=1;(productCount =99) | |
| T7 | | ROLLBACK; |
| T8 | select p.productName,p.productCount from product p where p.productId=1;(productCount =100) | |
T1—— A用户开启事务,start transaction;
T2—— A用户查询当前小米手机剩余数量,select p.productName,p.productCount from product p where p.productId=1;此时数量显示为100。
T3——B用户开启事务,start transaction;
T4——B用户查询当前小米手机剩余数量,select p.productName,p.productCount from product p where p.productId=1;此时数量显示为100。
T5—— B用户购买了一台小米手机,update product set productCount = 99 where productId = 1; 此时只修改数据并未提交事务。
T6—— A用户刷新页面,select p.productName,p.productCount from product p where p.productId=1;此时数量显示为99。
T7—— B用户购买失败,回滚事务。
T8—— A用户查询当前小米手机剩余数量,select p.productName,p.productCount from product p where p.productId=1;此时数量显示为100。
小结:
事务A读取了未提交的数据,事务B的回滚,导致了事务A的数据不一致,导致了事务A的脏读
!
4.2 事务隔离级别设置为Read Committed
查询事务隔离级别
SELECT @@tx_isolation;
更改数据库隔离级别,设置隔离级别为提交读:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
注意:需要同时修改两个窗口的事务隔离级别
| 时间轴 | 事务A | 事务B |
| — | — | — |
| T1 | start transaction; | |
| T2 | select p.productName,p.productCount from product p where p.productId=1;(productCount =100) | |
| T3 | | start transaction; |
| T4 | | select p.productName,p.productCount from product p where p.productId=1;(productCount =100) |
| T5 | | update product set productCount = 99 where productId = 1; |
| T7 | select p.productName,p.productCount from product p where p.productId=1;(productCount =100) | |
| T6 | | commit; |
| T8 | select p.productName,p.productCount from product p where p.productId=1;(productCount =99) | |
这里就不再对流程做过多赘述。
小结:
可以看到避免了脏读
现象,但是却出现了,一个事务还没有结束,就发生了不可重复读问题,即事务A来说 productCount从 100->100->99。但这个过程中事务并未提交结束。
4.3 事务隔离级别设置为Repeatable Read(mysql默认级别)
查询事务隔离级别
SELECT @@tx_isolation;
更改数据库隔离级别,设置隔离级别为可重复读:
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
注意:需要同时修改两个窗口的事务隔离级别
| 时间轴 | 事务A | 事务B |
| — | — | — |
| T1 | start transaction; | |
| T2 | select p.productName,p.productCount from product p where p.productId=1;(productCount =100) | |
| T3 | | start transaction; |
| T4 | | select p.productName,p.productCount from product p where p.productId=1;(productCount =100) |
| T5 | | update product set productCount = 99 where productId = 1; |
| T7 | select p.productName,p.productCount from product p where p.productId=1;(productCount =100) | |
| T6 | | commit; |
| T8 | select p.productName,p.productCount from product p where p.productId=1;(productCount =100) | |
这里就不再对流程做过多赘述。
小结:
可以看到可重复读
隔离级别避免了脏读
,不可重复读
的问题,但是出现了幻读
现象。事务A查询到的小米数量等于100,但是事务B修改了数量为99,但是事务A读取到的值还是100。当事务A去减1等于99时,是错误的,此时应该是99-1=98才对。接下来我们再提高一个事务隔离级别。
4.4 事务隔离级别设置为Serializable
查询事务隔离级别
SELECT @@tx_isolation;
更改数据库隔离级别,设置隔离级别为串行化:
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
| 时间轴 | 事务A | 事务B |
| — | — | — |
| — | — | — |
| T1 | start transaction; | |
| T2 | | start transaction; |
| T2 | select p.productName,p.productCount from product p where p.productId=1;(productCount =100); | |
| T4 | | update product set productCount = 99 where productId = 1;(等待中…) |
这里就不再对流程做过多赘述。
小结:
在我们Serializable隔离级别中,我们可以看到事务B去做修改动作时卡主了,不能向下执行。这是因为:给事务A的select操作上了锁,所以事务B去修改值的话,就会被卡主。只有当事务A操作执行完毕,才会执行事务B的操作。这样就避免了上述三个问题了。
-
回到问题的本身,其实我们并不需要将事务提到这么高。
-
问题的本身就是,当我们读完了的时候,就要在上面加锁。我们不希望别人能够去读它。因为别人读到了count,就会修改count的值,并写进去。所以我们在select 操作的时候,加上for update。这时候就会把这行操作给锁掉了。那么另外一个人也进行相同的操作,也表示select 出来的count需要进行update,需要锁住。
select p.productName,p.productCount from product p where p.productId=1 for update;
结尾
这不止是一份面试清单,更是一种”被期望的责任“,因为有无数个待面试者,希望从这篇文章中,找出通往期望公司的”钥匙“,所以上面每道选题都是结合我自身的经验于千万个面试题中经过艰辛的两周,一个题一个题筛选出来再次对好答案和格式做出来的,面试的答案也是再三斟酌,深怕误人子弟是小,影响他人仕途才是大过,也希望您能把这篇文章分享给更多的朋友,让他帮助更多的人,帮助他人,快乐自己,最后,感谢您的阅读。
由于细节内容实在太多啦,在这里我花了两周的时间把这些答案整理成一份文档了,在这里只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
5796124131)]
这不止是一份面试清单,更是一种”被期望的责任“,因为有无数个待面试者,希望从这篇文章中,找出通往期望公司的”钥匙“,所以上面每道选题都是结合我自身的经验于千万个面试题中经过艰辛的两周,一个题一个题筛选出来再次对好答案和格式做出来的,面试的答案也是再三斟酌,深怕误人子弟是小,影响他人仕途才是大过,也希望您能把这篇文章分享给更多的朋友,让他帮助更多的人,帮助他人,快乐自己,最后,感谢您的阅读。
由于细节内容实在太多啦,在这里我花了两周的时间把这些答案整理成一份文档了,在这里只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!