MySQL之事务隔离级别

前言

MySQL事务主要用于处理一个包含操作量比较大、复杂的业务。比如说,删除一个学生,我们除了要删除该学生的基本信息,同时也要删除考试记录、违规记录等。诸多的操作组成一个事务。事务是用来管理insertupdatedelete基本指令的。当MySQL使用innodb引擎的前提下才支持事务操作。

事务的基本特点

  • 原子性

    一个事务的执行所有的操作,结果只有两种:要么全部执行、要么全部不执行。事务在执行的过程中,当在某一个节点执行发生错误的时候,事务会被执行rollback操作,将数据恢复到执行该事务之前的状态。A去银行转账,要么转账成功、要么转账失败。

  • 一致性

    从事务开始执行到执行完成后,数据库的完整性约束完全没有收到破坏。A转账给B,不可能发生这种情况:A转账成功、B没有收到款。

  • 隔离性

    在同一时间点,数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( read uncommitted )、读提交( read committed )、可重复读( repeatable read|默认方式 )和串行化( serializable )。

  • 持久性

    事务成功执行后,事务的所有操作对数据库的更新是永久的,不能回滚。

隔离性的类别

  • read uncommitted | 读未提交
  • read committed | 读已提交
  • repeatable read | 可重复读
  • serializable | 串行化

MySQL数据库中,引擎默认使用repeatable read

# SELECT @@tx_isolation 或者 SELECT @@transaction_isolation
# MySQL 8.x 
# transaction_isolation在MySQL 5.7.20中添加了作为别名 tx_isolation,现已弃用,并在MySQL 8.0中删除。
# 应调整应用程序transaction_isolation以优先使用 tx_isolation。
mysql> SELECT @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.01 sec)

事务的并发问题

  • 脏读

    事务A读取了事务B更新的数据,然后事务B在某些因素下执行了回滚,那么事务A读取的数据就是不合理的,即脏数据。

    ## (1)事务A的操作
    ## 设置为隔离方式为[读未提交 | read uncommitted]
    ## 开启事务并查询id为1的score的值 
    mysql> set session transaction isolation level read uncommitted;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> select * from score;
    +----+----------+-------+
    | id | name     | score |
    +----+----------+-------+
    |  1 | alicfeng |    80 |
    |  2 | feng     |   100 |
    |  3 | alic     |    90 |
    +----+----------+-------+
    3 rows in set (0.00 sec)
    
    ## (2)事务B的操作
    ## 开启事务并将id为1的score修改成 75
    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> update score set score=75 where id=1;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> select * from score;
    +----+----------+-------+
    | id | name     | score |
    +----+----------+-------+
    |  1 | alicfeng |    75 |
    |  2 | feng     |   100 |
    |  3 | alic     |    90 |
    +----+----------+-------+
    3 rows in set (0.00 sec)
    
    ## (3)事务A的操作
    ## 再次读取id为1的score值 75
    mysql> select * from score;
    +----+----------+-------+
    | id | name     | score |
    +----+----------+-------+
    |  1 | alicfeng |    75 |
    |  2 | feng     |   100 |
    |  3 | alic     |    90 |
    +----+----------+-------+
    3 rows in set (0.00 sec)
    
    ## (4) 事务B的操作
    ## 事务回滚
    mysql> rollback;
    Query OK, 0 rows affected (0.00 sec)
    

    上述四个步骤中,事务A事务B前读取的score的值为80,在事务B执行修改后读取score的值为75事务B再进行回滚操作,那么事务A在两次读取的score的值是不一致的,那么就是脏读。

  • 不可重复读

    事务A需要重复多次读取某组数据,事务A事务B对该组数据修改提交前后进行读取,很显然、两次读取的数据是不一致的,即不可重复读。侧重于元数据的修改。

    ## 使用[读已提交]的模式实践
    mysql> set session transaction isolation level read committed;
    Query OK, 0 rows affected (0.00 sec)
    
    ## (1) 事务A查询id为1的score 80
    mysql> select * from score;
    +----+----------+-------+
    | id | name     | score |
    +----+----------+-------+
    |  1 | alicfeng |    80 |
    |  2 | feng     |   100 |
    |  3 | alic     |    90 |
    +----+----------+-------+
    3 rows in set (0.00 sec)
    
    ## (2) 事务B修改id为1的score并提交事务 75
    mysql> update score set score=75 where id=1;
    Query OK, 1 row affected (0.01 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> commit;
    Query OK, 0 rows affected (0.00 sec)
    
    ## (3) 事务A再次查询id为1的score的值 75
    mysql> select * from score;
    +----+----------+-------+
    | id | name     | score |
    +----+----------+-------+
    |  1 | alicfeng |    80 |
    |  2 | feng     |   100 |
    |  3 | alic     |    90 |
    +----+----------+-------+
    3 rows in set (0.00 sec)
    
    mysql> select * from score;
    +----+----------+-------+
    | id | name     | score |
    +----+----------+-------+
    |  1 | alicfeng |    75 |
    |  2 | feng     |   100 |
    |  3 | alic     |    90 |
    +----+----------+-------+
    3 rows in set (0.00 sec)
    

    从上述的三个步骤中显而易见可以看出,事务A在事务B修改并提交的前后读取同一条数据的值得不一样的,具有不可重复读问题。

  • 幻读

    事务A在修改每一条元数据的时候,事务B在此时添加了一条新记录,事务A在处理的过程中突然多了一条数据,即幻读。侧重于数据的删除与修改。

    ## 将事务隔离的模式设置为[可重复读]
    mysql> set session transaction isolation level repeatable read;
    Query OK, 0 rows affected (0.00 sec)
    
    ## (1)事务A读取scor数据表
    mysql> select * from score;
    +----+----------+-------+
    | id | name     | score |
    +----+----------+-------+
    |  1 | alicfeng |    75 |
    |  2 | feng     |   100 |
    |  3 | alic     |    90 |
    +----+----------+-------+
    3 rows in set (0.00 sec)
    
    ## (2)事务B新增删除一条数据并提交
    mysql> delete from score where id=1;
    Query OK, 1 row affected (0.01 sec)
    
    mysql> commit;
    Query OK, 0 rows affected (0.01 sec)
    
    ## (3)事务A再次读取score数据表
    mysql> select * from score;
    +----+----------+-------+
    | id | name     | score |
    +----+----------+-------+
    |  1 | alicfeng |    75 |
    |  2 | feng     |   100 |
    |  3 | alic     |    90 |
    +----+----------+-------+
    3 rows in set (0.00 sec)
    

    可见,事务A事务B删除并提交前后读取的数据一样,出现了幻读。

事务隔离级别的影响

事务隔离级别 脏读 不可重复读 幻读
读未提交 | read uncommitted
读已提交 | read committed 不会
可重复读 | repeatable read 不会 不会
串行化 | serializable 不会 不会 不会

事务隔离性说明

  • 隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
  • 事务隔离级别为读提交时,写数据只会锁住相应的行
  • 事务隔离级别为串行化时,读写数据都会锁住整张表
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 一、事务 1、事务四要素:ACID 对于事务,我之前的理解是很粗糙的,不就是为了保证操作的原子性么?一般订单系统或...
    张伟科阅读 1,269评论 0 5
  • 一、上堂回顾 1.概念​ 数据库管理系统,数据库,表​ SQL的分类:DDL、DML、DQL、DCL2.数据库的使...
    WenErone阅读 407评论 0 0
  • 一、数据库操作 3.DQL 3.7分组查询 group by:分组查询 将字段中相同值归为一组having:...
    郑元吉阅读 295评论 0 0
  • 一、数据库简介 1.数据库系统 1.1数据库 DataBase【DB】,指的是长期保存到计算机上的数据,按照一定顺...
    郑元吉阅读 588评论 0 6
  • 文:坤爷 站在拥挤的正在运行中的地铁12号车厢门口小兮环顾四周, 因为北方人身形的关系, 165公分的身高再加上8...
    半米与坤爷阅读 308评论 0 0