mysql四个隔离级别的介绍

mysql四个隔离级别的介绍 为了解决“隔离”与“并发”的矛盾,ISO/ANSI SQL92定义了4个事务隔离级别,每个级别的隔离程度不同,允许出现的副作用也不同,应用可以根据自己的业务逻辑要求,通过选择不同的隔离级别来平衡 “隔离”与“并发”的矛盾。
隔离级别(由高到低)
Serializable>Repeatable read>Read committed>Read uncommitted
四个隔离接的详细介绍

  1. Read uncommitted(读未提交)
    从字面意思来理解就是能读取到未提交的数据,不过当然是另一线程的未提交数据,这样到导致所谓的脏读问题。
    脏读:大抵便是两个线程同时运行,第一个线程在操作数据,另一个线程也修改了相关的数据,都没有进行提交,第一个线程就已经读取到了。数据便读到了线程2的相关修改,破坏了事务的隔离性。
    下面这段是所谓的专业术语写的。
    一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫做**“脏读”**。
  2. 【mysql四个隔离级别的介绍】Read committed(读取已提交)
    从字面意思来理解就是能读取到已经提交的数据,不过当然是另一线程的提交数据。第一个线程中可以读取到第二个线程中已经提交的数据。不过还是会有所谓的缺点,那就是**“不可重复读”。
    "不可重复读":大抵便是第一个线程中一个事务在读取某些数据后,隔段时间再次用同样的条件查询数据,却发现其读出的数据已经发生了改变,出现了第一次事务中未有的数据。这种现象就叫做“不可重复读”。即一个事务中两次读取数据,会出现数据不一致的问题。
    下面这段是所谓的专业术语写的。
    一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不可重复读”**。
  3. Repeatable read(可重复读取)
    从字面意思来理解就是一个事务中,多次读取,查询的数据是一致的。innodb已经通过mvcc,来保证这个特性。保证当前读的情况下,当前事务只能看到,事务之前和自己的修改,别的均不可见,"不可重复读"和"幻读"都已经解决。不过依旧有缺点,那就是不能读取到并发情况下,其他线程事务提交的最新数据。
  4. Serializable(可序列化)
    最安全级别,默认读的时候,也加上共享读锁,阻止其他事物,修改相关数据。不过,性能么,就差太多太多了!!
隔离级别杂谈 在上面讲到的并发事务处理带来的问题中,
“脏读”、“不可重复读”和“幻读”,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。数据库实现事务隔离的方式,基本上可分为以下两种。
  • 一种是在读取数据前,对其加锁,阻止其他事务对数据进行修改。
  • 另一种是不用加任何锁,通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本,因此,这种技术叫做数据多版本并发控制(MultiVersion Concurrency Control,简称MVCC或MCC),也经常称为多版本数据库。
mvcc带来的当前读和快照读
  • 快照读
    相当于读取的是查询数据的最新快照版本,而并非最新的实时数据。
    不显式加锁的普通查询,都是快照读。诸如 select xx from table where field = value
  • 当前读
    始终读取最新数据,相当于Serializable级别的读操作。
    显式加锁的查询就是当前读。如 select xx from table where field = value lock in share mode(加共享读锁),select xx from table where field = value for update (加排它锁)
共享锁和排它锁的介绍mysql四个隔离级别的介绍
文章图片

代码操作 数据库版本信息,我的mysql版本8.0.19,innodb引擎。5.6前后,好像还是有点差距的,在此先说下。
命令相关
# 查看mysql版本 select version(); # 查看隔离级别 select @@transaction_isolation; # 设置隔离级别(其他几个前面有) set session transaction isolation levelserializable; # 显式加共享锁 select xx from table where field = value lock in share mode; # 显式加排它锁 select xx from table where field = value for update;

验证当前读和快照读
mysql四个隔离级别的介绍
文章图片

mysql四个隔离级别的介绍
文章图片

从操作中,我们已经得知,快照读的缺点。不能获取到实时数据,不过,快照读,它不加锁,性能好啊。
验证共享锁和排它锁
mysql四个隔离级别的介绍
文章图片

mysql四个隔离级别的介绍
文章图片

验证不可重复读
自己动手试试吧。
先改下默认的隔离级别,然后在一个事务中查询,另一个事务中修改,未提交读,读取已提交,还有可序列化,自己模拟一下场景,试试你就明白上面说的什么意思了~~
自己动手,丰衣足食。
结语 数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上 “串行化”进行,这显然与“并发”是矛盾的。同时,不同的应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用对“不可重复读”和“幻读”并不敏感,可能更关心数据并发访问的能力。
大家只需要知道,鱼与熊掌不可兼得,既想马儿吃得少,又想马儿跑的快,是不可能的。性能和数据一致性,你只能选择一个,选择最适合你的业务的隔离级别就好了,当然默认RR,已经能满足大部分需求了~

    推荐阅读