龙空技术网

MySQL数据库精讲:一文讲解MySQL事务隔离

Java架构师丨苏先生 200

前言:

现在我们对“mysql事务隔离”大概比较关怀,小伙伴们都想要了解一些“mysql事务隔离”的相关资讯。那么小编同时在网络上汇集了一些关于“mysql事务隔离””的相关内容,希望咱们能喜欢,朋友们一起来学习一下吧!


事务就是一组数据库操作要么全部成功,要么全部失败。

事务的四大特性:ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性)

MySQL中事务支持是在引擎层实现的,而MySQL的原生MyISAM引擎就不支持事务,所以被InnoDB取代。

隔离性与隔离级别

数据库中多个事务同时执行时,可能出现以下问题:

脏读:读取到其他事务未提交的数据;不可重复读:读取到其他事物已提交的数据,即本次事务多次读取的数据不一致;幻读:本次事务修改后又被其它事务改回去,误以为本次修改未生效。

为了解决这些问题,SQL标准规定了以下四个事务隔离级别;隔离得越严实,效率就会越低。。

读未提交:一个事务还未提交时,它做的变更就能被别的事务看到;隔离级别最低,会导致脏读、幻读以及不可重复读。读提交:一个事务提交之后,它做的变更才会被其他事务看到;避免了脏读,但仍会导致幻读和不可重复读。可重复读:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的;能够避免脏读和不可重复读,但仍会导致幻读。串行化:对于同一行记录读写都会加锁,当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;能够避免以上三个问题,但执行效率最低。

下面通过举例事务A/B说明这四种事务隔离级别:


如果隔离级别是读未提交:那么V1、V2、V3的值为2;虽然事务B还未提交,但结果已被事务A看到了。如果隔离级别是读提交:那么V1的值为1,V2、V3的值为2;只有在事务B提交后,V2才能读取到变更的值2。如果隔离级别是可重复读:那么V1、V2的值为1,V3的值为2;即无论事务B是否提交,事务A在执行期间看到的数据前后必须是一致的。如果隔离级别是串行化:那么事务A在查询到值后便会加读锁,直到事务A提交(释放读锁)后,事务B才能查询到结果并修改(增加读写锁);所以V1、V2都是1,V3是2。InnoDB的事务隔离实现

MySQL的默认隔离级别为可重复读,并且还解决了幻读问题;下面我们来讨论可重复读。

MVCC多版本并发控制

在InnoDB中给每行增加两个字段来实现MVCC,分别是创建的事务版本号和删除的版本号,每开启一个事务,事务的版本号就会递增。

SELECT:创建版本号<=当前版本号 AND (删除版本号 IS NULL OR 删除版本号 > 当前版本号)INSERT:将当前事务版本号保存至新行的创建版本号UPDATE:新插入一行,并且将当前事务版本号作为新行的创建版本号;将原纪录行的删除版本号设置为当前事务版本号DELETE:将当前事务版本号保存至该行的删除版本号

快照读/当前读、一致性非锁定读/锁定读

快照读:读取的是快照版本,也就是历史版本。当前读:读取的是最新版本。一致性非锁定读:不会给它所访问的表加任何形式的锁,其它事务可以同时并发的修改它们。锁定读:SELECT ... LOCK IN SHARE MODE 给记录添加共享锁,其它事务只能读取不能修改;SELECT ... FOR UPDATE给索引记录加锁,加锁情况桶UPDATE。

在MySQL默认的可重复读中,普通的SELECT是一致性非锁定的快照读,读取的是事务创建时的快照;而UPDATE、DELETE、INSERT、SELECT ... LOCK IN SHARE MODE、SELECT ... FOR UPDATE是锁定的当前读。假设当前事务执行了锁定的当前读,那么其它事务将不能进行修改直到当前事务提交。

长事务

事务在提交之前会保留回滚记录,导致大量占用存储空间,并且还会占用锁资源,所以尽量避免使用长事务;如果无法避免,应保证逻辑日志空间足够用,并且支持动态日志空间增长。监控Innodb_trx表,发现长事务报警。

Java程序员福利:我把2019近一年经历过的Java岗位面试,和一些刷过的面试题都做成了PDF,PDF都是可以免费分享给大家的,关注私信我:【101】,免费领取!

标签: #mysql事务隔离