zoukankan      html  css  js  c++  java
  • 事务的隔离级别- 极客时间()

    初识事务隔离

    事务隔离级别的出现都是针对数据库的具体问题的, SQL-92标准对事务并发处理会存在的异常情况进行了分级, 分别为脏读(Dirty Read)、不可重复读(Unrepeatable Read)和幻读(Phantom Read).

    三种异常

    举个例子, 有个heros_temp表, 中有三条数据:

    先说脏读, 现在访问数据库, 对数据库进行了一次INSERT操作, 插入一条"吕布"的记录, 事务未提交, 现在重新开启一个事务, 查询数据库可以将吕布的记录查询出来. 这个就是脏读.

    不可重复读呢? 现在先查询数据库记录, 之后重新开启一个事务, 修改一条记录, 现在在前一个事务中再次查询可以查询出修改后的数据, 前后查询出的数据不一致. 这个就是不可重复度.

    幻读呢? 现在先查询数据库, 之后开启新事务INSERT一条记录, 在第一个事务中再次查询会多出插入的记录, 这个就是"幻读".

    1. 脏读: 读到事务中还没有提交的数据(可能事务回滚, 这个时候读到的数据无意义)
    2. 不可重复读: 对某数据进行读取, 发现两次读取的结果不同, 也就是没有读到相同的内容.(重点在于一条数据的修改, 也就是UPDATE 和 DELETE) 这个因为有其他事务对这个数据同时进行了修改和删除.
    3. 幻读: 事务A根据条件查询得到了N条数据, 但此时事务B更改或者增加了M条符合事务A查询条件的数据, 这样当事务A再次进行查询的时候大仙有N + M条数据, 产生了幻读.(重点在于新增多条记录INSERT)

    事务的隔离级别有哪些?

    解决异常数量从少到多的顺序决定了隔离级别的高低, 这四种隔离级别从低祷告分别是: 读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ)和可串行化(SERIALIZABLE). 这个隔离级别解决的异常情况如下:

    读未提交,也就是允许读到未提交的数据,这种情况下查询是不会使用锁的,可能会产生脏读、不可重复读、幻读等情况。

    读已提交就是只能读到已经提交的内容,可以避免脏读的产生,属于 RDBMS 中常见的默认隔离级别(比如说 Oracle 和 SQL Server),但如果想要避免不可重复读或者幻读,就需要我们在 SQL 查询的时候编写带加锁的 SQL 语句。

    可重复读,保证一个事务在相同查询条件下两次查询得到的数据结果是一致的,可以避免不可重复读和脏读,但无法避免幻读。MySQL 默认的隔离级别就是可重复读。

    可串行化,将事务进行串行化,也就是在一个队列中按照顺序执行,可串行化是最高级别的隔离等级,可以解决事务读取中所有可能出现的异常情况,但是它牺牲了系统的并发性。

    模拟异常

    模拟的数据库表如下:

    -- ----------------------------
    -- Table structure for heros_temp
    -- ----------------------------
    DROP TABLE IF EXISTS `heros_temp`;
    CREATE TABLE `heros_temp`  (
      `id` int(11) NOT NULL,
      `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of heros_temp
    -- ----------------------------
    INSERT INTO `heros_temp` VALUES (1, '张飞');
    INSERT INTO `heros_temp` VALUES (2, '关羽');
    INSERT INTO `heros_temp` VALUES (3, '刘备');
    

    开启两个客户端, 由于MySQL的默认隔离级别是可重复度, 所以需要先将级别设为读未提交:

    mysql> SHOW VARIABLES LIKE 'transaction_isolation'; // 查询当前隔离级别
    mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; // 设置隔离级别为读未提交
    mysql> SET autocommit = 0; // 设置事务不自动提交(由于MySQL的事务是自动提交的, 这里需要改一下)
    
    脏读

    客户端2中开启事务, 写入新英雄, 不要提交

    客户端1中查看

    模拟不可重复读

    客户端1查询

    客户端2修改

    客户端1再次查询

    模拟幻读

    客户端1查询

    客户端2新增

    客户端1再次查询

    隔离级别都是针对对应的异常问题, 并且隔离级别针对每种RDBMS都是相同的, 不同的是实现的原理不同.

  • 相关阅读:
    webpack介绍 安装 常用命令
    npm常用命令
    jQuery 实现点击页面其他地方隐藏菜单
    :after伪类+content内容生成经典应用举例
    几分钟前 几小时前 几天前... 7个阶段
    JS — 获取4个不重复的随机验证码
    JS — 数组去重(4种方法)
    Spring IOC原理简析
    浅谈Linux下的五种I/O模型
    大型分布式网站架构技术总结
  • 原文地址:https://www.cnblogs.com/wadmwz/p/11205802.html
Copyright © 2011-2022 走看看