事务的隔离级别和引发的问题

以mysql为例:

查询当前事务的隔离级别用

select @@tx_isolation;

设置隔离级别用 set session transaction isolation level [隔离级别];

例如: set session transaction isolation level read uncommitted;

如果是设置全局的事务隔离级别用set global transaction isolation level [隔离级别];

例如:set global transaction isolation level read uncommitted;

mysql的默认隔离级别为 Repeatable Read可重复读

oracle的默认隔离级别为Read Committed;读已提交

四种隔离级别:

Read Uncommitted:未提交读   

Read Committed :已提交读(oracle默认)

Repeatable Read:可重复读(mysql默认)

Serializable:序列化

Read Uncommitted  

我们将左边的隔离级别设置为未提交读

可以看到,左右都开启了事务,但是右边更新数据之后还没有提交,左边就可以读取到右边为提交的数据

这就会引发脏读的问题

Read Committed  

我们将左边的隔离级别设置为提交读

可以看到,左右都开启了事务,但是右边更新的数据之后还没有提交,左边就不可以读取到右边未提交的数据

只有等右边的数据提交了,左边才能读取到

但是这样又有一个问题,就是左边还未提交,就能读取到另一个事务提交的数据

这就会引发不可重复读的问题

Repeatable Read

左边数据太长了,只能截取一部分

我们将左边的隔离级别设置为可重复读

可以看到,左右都开启了事务,右边事务提交后的数据,只有左边的事务也提交之后才可以读取到

Serializable:序列化

我们将左边的隔离级别设置为序列化

我们这里先在左边开启事务,我们可以看到第一张图,左边事务先开启,右边的插入数据就无法执行

只有等左边的事务提交了,右边才能进行插入事务,如图二

假如我们将右边事务先开启,那么只有等右边的事务提交了,左边的操作才能进行

引发读的安全问题 

脏读:一个事务读取到了另一个事务为提交的内容,例如隔离级别为未提交读

不可重复读:一个事务读取到了另一个事务提交的数据,导致前后两次查询结果不一致,例如隔离级别为提交读

幻读:一个事务读取到另一个事务插入的数据,导致多次查询的结果不一致。也就是说第一次查询有n条记录,第二次查询有n+1条数据,看起来就像产生幻觉(mysql数据库没办法演示幻读)

效率

未提交读>提交读>可重复读>序列化

引发写的安全问题(隔离级别不是序列化的级别)

一般引发写的问题就是丢失更新的数据

事务a,b开启事务后同时查询

然后事务a先对事务进行更新,事务b对事务后更新引发的问题

解决的方法一般两个:悲观锁和乐观锁

悲观锁

一般认为丢失更新一定会发生

在查询的时候加上字段 for update 

a事务的查询加上for update后,b事务的界面就会卡主,拿不了数据,只能等a数据提交后才能拿数据

这样就保证了数据a提交的数据不会丢失

乐观锁

认为不会发生丢失更新,一般有程序员手动增加任意字段,一般加上version

例如程序员手动加上了version字段,初始字段为version(0)

那么a事务和b事务一开始的version(0)

然后a事务修改了数据并提交,version(0)就会变成version(1),

b事务进行操作的时候发现version的值改变了,便会从数据库中重新查询数据

这样也能保证数据不会更新丢失。

数据库的行锁和表锁

行锁就是将我们要操作的行锁住,其他事务无法去进行增删改的操作

表锁就是我们将整个表锁住,使得其他事务无法对我们的表进行操作

行锁和表锁都涉及到了排他锁,for update ,在开启事务后如果对行进行上锁,就是行锁,对表进行操作就是表锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值