MySql 事务(2)

隔离级别
读未提交【Read Uncommitted: 在该隔离级别,所有的事务都可以看到其他事务没有提交的
执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多
并发问题,如脏读,幻读,不可重复读等,我们上面为了做实验方便,用的就是这个隔离性。
读提交【Read Committed:该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL
认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离
级别会引起不可重复读,即一个事务执行时,如果多次 select, 可能得到不同的结果。
可重复读【Repeatable Read: 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行
中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。
串行化【Serializable: 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,
从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,。但是可能会导致超时和锁竞争
(这种隔离级别太极端,实际生产基本不使用)
隔离级别如何实现:隔离,基本都是通过锁实现的,不同的隔离级别,锁的使用是不同的。常见有,表
锁,行锁,读锁,写锁,间隙锁(GAP),Next-Key(GAP+行锁)等。不过,我们目前现有这个认识就行,
先关注上层使用。

1.查看与设置隔离性

1. 查看全局事务隔离级别 使用以下 SQL 语句,可查询整个 MySQL 服务实例的默认事务隔离级别(新创建的数据库连接会继承该全局设置):

select @@global.transaction_isolation;

2. 查看当前会话事务隔离级别(完整写法) 若要查询 ** 当前数据库连接(会话)** 的事务隔离级别(仅对当前连接内的事务生效),可使用:

select @@session.transaction_isolation;

3. 查看当前会话事务隔离级别(简写形式) @@transaction_isolation 是 @@session.transaction_isolation 的简写,效果相同,也用于查询当前会话的事务隔离级别:

select @@transaction_isolation;

session.transaction优先级>global.transaction优先级

更改隔离级别

比如我们这个地方可以通过代码将会话隔离级别和全局隔离级别修改成读提交

2.读未提交【Read Uncommitted

我们发现当左边终端操未持久化保存时右边的终端可以读取到这就是读未提交

我可以读到其他终端未提交修改的结果

这个地方我用的是update演示 delete等等也是一样的

--几乎没有加锁,虽然效率高,但是问题太多,严重不建议采用
--一个事务在执行中,读到另一个执行中事务的更新(或其他操作)但是未commit的数据,这种现象叫做脏读
(dirty read)

当然如果你那个数据在事务结束后也没有commit 那么后续你是读不到的

3.读提交【Read Committed

读提交就是我可以读到其他终端事务运行时的commit的值

未commit的值我是读不到的

4.可重复读【Repeatable Read

--可以看到,在终端左边中,事务无论什么时候进行查找,不管终端b事务发生啥看到的结果都是一致的,这叫做可重复读!

可重复读意味着不管别的终端怎么改动 每次事务读到的多次内容都是一致的

在 可重复读(Repeatable Read,RR) 隔离级别下,能读到另一个事务内容的时间点主要分两种情况:

情况 1:其他事务在「当前事务启动前」已提交 可重复读的核心机制是:事务启动时会生成一个 “数据快照”(基于 MVCC 多版本并发控制),快照会记录 “事务启动瞬间所有已提交的其他事务的结果”。

如果另一个事务在 当前事务启动之前 就已经提交了数据修改,那么当前事务从 “启动时的快照” 里,能读到这些已提交的内容。

情况 2:当前事务结束后,「新事务启动」时 当前事务执行过程中,即使其他事务提交了新的修改,当前事务因为依赖 “启动时的快照”,读不到这些后续提交的内容(这是为了保证 “同一事务内多次读结果一致”)。

但如果当前事务执行完毕(提交或回滚),之后 新启动一个事务,这个 “新事务” 的快照会基于 “新事务启动瞬间” 生成,此时就能读到 “之前其他事务提交的新内容” 了。

这里如果左边终端事务insert也符合重复读的性质 但是一般的数据库未必满足

一般的数据库在可重复读情况的时候,无法屏蔽其
他事务insert的数据(为什么?因为隔离性实现是对数据加锁完成的,而insert待插入的数据因为并不存
在,那么一般加锁无法屏蔽这类问题),会造成虽然大部分内容是可重复读的,但是insert的数据在可重复读
情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉。这种现象,叫做幻读
(phantom read)。很明显,MySQLRR级别的时候,是解决了幻读问题的(解决的方式是用Next-Key
(GAP+行锁)解决的。

5.串行化【serializable

--对所有操作全部加锁,进行串行化,不会有问题,但是只要串行化,效率很低,几乎完全不会被采用

1.查看不受串行化的影响

2.当一个事务执行完 才能执行另一个事务的内容

总结

其中隔离级别越严格,安全性越高,但数据库的并发性能也就越低,往往需要在两者之间找一个平
衡点。

不可重复读的重点是修改和删除:同样的条件, 你读取过的数据,再次读取出来发现值不一样了
幻读的重点在于新增:同样的条件, 1次和第2次读出来的记录数不一样
说明: mysql 默认的隔离级别是可重复读,一般情况下不要修改
上面的例子可以看出,事务也有长短事务这样的概念。事务间互相影响,指的是事务在并行执行的
时候,即都没有commit的时候,影响会比较大
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值