mysql四个隔离级别的介绍

mysql四个隔离级别的介绍

为了解决“隔离”与“并发”的矛盾,ISO/ANSI SQL92定义了4个事务隔离级别,每个级别的隔离程度不同,允许出现的副作用也不同,应用可以根据自己的业务逻辑要求,通过选择不同的隔离级别来平衡 “隔离”与“并发”的矛盾。

隔离级别(由高到低)
Serializable>Repeatable read>Read committed>Read uncommitted

四个隔离接的详细介绍

  1. Read uncommitted(读未提交)
    从字面意思来理解就是能读取到未提交的数据,不过当然是另一线程的未提交数据,这样到导致所谓的脏读问题。
    脏读:大抵便是两个线程同时运行,第一个线程在操作数据,另一个线程也修改了相关的数据,都没有进行提交,第一个线程就已经读取到了。数据便读到了线程2的相关修改,破坏了事务的隔离性。
    下面这段是所谓的专业术语写的。
    一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫做**“脏读”**。

  2. 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四个隔离级别的介绍_第1张图片

代码操作

数据库版本信息,我的mysql版本8.0.19,innodb引擎。5.6前后,好像还是有点差距的,在此先说下。

命令相关

# 查看mysql版本
select version(); 
# 查看隔离级别
select @@transaction_isolation; 
# 设置隔离级别(其他几个前面有)
set session transaction isolation level  serializable; 
# 显式加共享锁
select xx from table where field = value lock in share mode;
# 显式加排它锁
select xx from table where field = value for update;

验证当前读和快照读

mysql四个隔离级别的介绍_第2张图片
mysql四个隔离级别的介绍_第3张图片
从操作中,我们已经得知,快照读的缺点。不能获取到实时数据,不过,快照读,它不加锁,性能好啊。

验证共享锁和排它锁

mysql四个隔离级别的介绍_第4张图片
mysql四个隔离级别的介绍_第5张图片

验证不可重复读

自己动手试试吧。
先改下默认的隔离级别,然后在一个事务中查询,另一个事务中修改,未提交读,读取已提交,还有可序列化,自己模拟一下场景,试试你就明白上面说的什么意思了~~
自己动手,丰衣足食。

结语

数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上 “串行化”进行,这显然与“并发”是矛盾的。同时,不同的应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用对“不可重复读”和“幻读”并不敏感,可能更关心数据并发访问的能力。
大家只需要知道,鱼与熊掌不可兼得,既想马儿吃得少,又想马儿跑的快,是不可能的。性能和数据一致性,你只能选择一个,选择最适合你的业务的隔离级别就好了,当然默认RR,已经能满足大部分需求了~

你可能感兴趣的:(mysql)