前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >事务隔离级别总结

事务隔离级别总结

作者头像
张申傲
发布2020-09-03 16:04:05
6450
发布2020-09-03 16:04:05
举报
文章被收录于专栏:漫漫架构路漫漫架构路

事务隔离级别总结

一. ACID特性

事务(Transaction)是数据库系统中一系列操作的一个逻辑单元,所有操作要么全部成功要么全部失

。 事务是区分文件存储系统与Nosql数据库重要特性之一,其存在的意义是为了保证即使在并发情况下也

能正确的执行CRUD操作。怎样才算是正确的呢?这时提出了事务需要保证的四个特性即ACID:

  1. A:原子性(Atomicity) 一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  2. C: 一致性(Consistency) 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  3. I:隔离性(Isolation) 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行 时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(read uncommitted)、读已提交(read committed)、可重复读(repeatable read)和串行化(serializable)。
  4. D:持久性(Durability) 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

二. 事务隔离级别

在高并发的情况下,要完全保证其ACID特性是非常困难的,除非把所有的事务串行化执行,但带来的负 面的影响将是性能大打折扣。很多时候我们有些业务对事务的要求是不一样的,所以数据库中设计了四 种隔离级别,供用户基于业务进行选择。这四种隔离级别分别是:

  1. 读未提交(read uncommitted)
  2. 读已提交(read committed)
  3. 可重复读(repeatable read)
  4. 串行化(serializable)

其中,Oracle默认的级别是read committed,而MySQL默认为repeatable read。

注:MySQL中查看、设置事务隔离级别:

代码语言:javascript
复制
#查看事务隔离级别
SELECT @@tx_isolation;

#设置隔离级别为read-uncommitted
set tx_isolation='read-uncommitted';

三. 常见的数据库事务的问题

  1. 脏读(Dirty Read) 指一个事务读取到另一事务未提交的更新数据。
  2. 不可重复读(NonRepeatable Read) 指在同一事务中,多次读取同一数据返回的结果有所不同。也就是说,后续读取可以读到另一事务已提交的更 新数据。相反, 可重复读在同一事务中多次读取数据时,能够保证所读数据一样,也就是后续读取不能读到另一事务已提交的更新数据。
  3. 幻读(Phantom Read) 指在同一个事务中,多次读取到的数据数量不一致。也就是说,后续读取可以读取到另一个事务删除或者新增的数据。 不可重复读与幻读在概念上容易混淆,其不同在于:不可重复读侧重的是另一个事务对数据的修改,是行级别的操作。而幻读侧重的是另一个事务对数据的新增或删除,是整个表级别的操作。

采用不同的事务隔离级别,可解决不同的问题,总结如下:

隔离级别

脏读

不可重复读

幻读

read uncommitted

不可解决

不可解决

不可解决

read committed

可解决

不可解决

不可解决

repeatable read

可解决

可解决

不可解决

serializable

可解决

可解决

可解决

可以看到,隔离级别越高,事务的安全性就越高,但是对性能的影响也越大,实际应用中应根据不同业务场景选择不同的隔离级别。

四. 事务隔离级别演示

  1. 准备 表结构:
代码语言:javascript
复制
CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `money` bigint(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
  1. 脏读 开启2个数据库session,session1执行
代码语言:javascript
复制
#设置为读未提交
set tx_isolation='read-uncommitted';
BEGIN;
insert INTO `account` (`name`,`money`) VALUES ('Kobe',100);
  1. 此时session1向数据库插入了一条数据,还未提交。 这时,在session2中读取数据:
代码语言:javascript
复制
#设置为读未提交
set tx_isolation='read-uncommitted';
SELECT * from `account`;
  1. 不可重复读 初始化数据:
代码语言:javascript
复制
insert INTO `account` (`name`,`money`) VALUES ('Kobe',100);
  1. 在session1中执行查询:
代码语言:javascript
复制
#设置为读已提交
set tx_isolation='read-committed';
BEGIN;
SELECT * from `account`; 
# 其他操作

此时查询到表中的数据是{1,Kobe,100}。

这时session2更新了表中的数据

代码语言:javascript
复制
#设置为读已提交
set tx_isolation='read-committed';
UPDATE `account` SET money= money+100 where `id`=1;
  1. 这时再在session1的当前事务中执行查询:
代码语言:javascript
复制
SELECT * from `account`; 
  1. 幻读 初始化数据:
代码语言:javascript
复制
insert INTO `account` (`name`,`money`) VALUES ('Kobe',); 
代码语言:javascript
复制
#设置为可重复读
set tx_isolation='REPEATABLE-READ';
BEGIN;
SELECT * FROM `account`;
代码语言:javascript
复制
#设置为可重复读
set tx_isolation='REPEATABLE-READ';
insert INTO `account` (`name`,`money`) VALUES ('James',100);
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-07-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 事务隔离级别总结
    • 一. ACID特性
      • 二. 事务隔离级别
        • 三. 常见的数据库事务的问题
          • 四. 事务隔离级别演示
          相关产品与服务
          云数据库 SQL Server
          腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档