例说MySQL事务的4种隔离级别

版权声明:版权所有,翻版我也没办法!!! https://blog.csdn.net/tebtebtebteb/article/details/82852235

引言:

SQL标准定义了4中隔离级别,包括一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级别支持更高的并发处理,并拥有更低的系统开销。

事务的基本要素:

  1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

   2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

   3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

   4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

MySql事务隔离级别(InnoDB引擎)分为4类:

  1. READ UNCOMMITED – 读取未提交内容,会产生脏读
  2. READ COMMITED – 读取已提交内容,导致不可重复读,同一个sql,读取到的数据不一致
  3. REPEATABLE READ – 可重复读(InnoDB 默认的),可能会产生幻读
  4. SERIALIZABLE – 可串行化,比RR严格,可能会产生deadlock和并发性问题

首先,先新建一个数据库test,再建一个表account,并且在DOS环境下打开两个命令行窗口来操作同一个表。

级别1:Read Uncommitted(读取未提交内容)

(1)所有事务都可以看到其他未提交事务的执行结果
(2)本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少
(3)该级别引发的问题是——脏读(Dirty Read):读取到了未提交的数据

#首先,修改隔离级别

set tx_isolation='READ_UNCOMMITTED';

select @@tx_isolation;

#事务A:启动一个事务

start transaction;

select * from account;

#事务B:也启动一个事务(两个事务交叉了)

在事务B中执行更新语句,且不提交

start transaction;

update account set balance = balance - 20 where id = 1;

select * from account;

#事务A:那么这个时候事务A能看到这个更新了的数据吗?

select * from account;

#事务B:事务B回滚,依然未提交

#事务A:在事务A中看到的也是刚才事务B还未提交的数据

select * from account;

级别2:Read Committed(读取提交内容)

(1)这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)
(2)它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变
(3)这种隔离级别出现的问题是——不可重复读(Nonrepeatable Read):不可重复读意味着我们在同一个事务中执行完全相同的select语句时可能看到不一样的结果。导致这种情况的原因可能有:(1)有一个交叉的事务有新的commit,导致了数据的改变;(2)一个数据库被多个实例操作时,同一事务的其他实例在该实例处理其间可能会有新的commit

#首先修改事务级别

set tx_isolation='READ_COMMITTED';

select @@tx_isolation;

#事务A:启动一个事务

start transaction;

select * from account;

#事务B也启动一个事务(两个事务交叉了),在这事务中更新数据,且未提交

start transaction;

update account set balance = balance - 20 where id = 1;

select * from account;

#事务A:这个时候我们在事务A中能看到数据的变化吗?

select * from account;

#事务B:如果提交了事务B呢?

#事务B:commit

#事务A:;

级别3:Repeatable Read(可重复读)

(1)这是MySQL的默认事务隔离级别
(2)它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行
(3)此级别可能出现的问题——幻读(Phantom Read):当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行
(4)InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

#首先,更改隔离级别

set tx_isolation='repeatable-read';

select @@tx_isolation;

#事务A:启动一个事务

start transaction;

select * from tx;

#事务B:开启一个新事务(两个事务交叉了),在事务B中更新数据,并提交

start transaction;

update account set balance = balance - 20 where id = 1;

select * from account;

commit;

#事务B:commit;

#事务A:这个时候事务B已经提交,那么事务A能不能看到数据的变化呢?

select * from account;

#事务A:只有当事务A也提交了,它才能看到数据的变化

级别4:Serializable(可串行化)

(1)这是最高的隔离级别
(2)它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。
(3)在这个级别,可能导致大量的超时现象和锁竞争

#首先修改隔离级别

set tx_isolation='serializable';

select @@tx_isolation;

#事务A:开启一个新事务

start transaction;

#事务B:在A没有commit之前,这个交叉事务是不能更改数据的

参考文章:

      MySQL事务隔离级别详解

猜你喜欢

转载自blog.csdn.net/tebtebtebteb/article/details/82852235