自学内容网 自学内容网

事务隔离级别

事务隔离级别

事务隔离是数据库的基础之一 加工。Isolation 是首字母缩略词 ACID 中的 I;隔离级别为 微调 performance 和 结果的可靠性、一致性和可重复性 多个事务正在进行更改并执行查询 同时。

InnoDB提供所有四个事务隔离 SQL:1992 标准描述的级别:READ UNCOMMITTED、READ COMMITTED、REPEATABLE READREPEATABLE READREPEATABLE READ 和  SERIALIZABLE 。默认的 的隔离级别为 REPEATABLE READREPEATABLE READInnoDB 

用户可以更改单个会话的隔离级别,或者 对于使用 SET 的所有后续连接 TRANSACTION 语句。设置服务器的默认值 隔离级别,请使用 --transaction-isolation 选项 命令行或选项文件中。详细信息 有关隔离级别和级别设置语法,请参见第 15.3.7 节“ SET TRANSACTION 语句”。

InnoDB支持每笔交易 此处使用不同的锁定策略描述的隔离级别。您可以 强制与默认 REPEATABLE READ 级别高度一致,因为 对 ACID 合规性很重要的关键数据进行操作。 或者,您可以使用 READ COMMITTED 甚至 READ UNCOMMITTED 放宽一致性规则,在 例如批量报告的情况,其中精确一致性和 可重复的结果不如最小化数量重要 的开销进行锁定。SERIALIZABLE 甚至强制执行 比 REPEATABLE 更严格的规则 READ,主要用于特殊情况、 例如,使用 XA 事务和 用于排查并发和死锁问题。

以下列表描述了 MySQL 如何支持不同的 交易级别。该列表从最常用的 level 设置为最少使用的级别。

  • REPEATABLE READ

    这是 的默认隔离级别。同一事务中的一致性读取读取由 第一次阅读。这意味着,如果您发出多个 plain (非锁定)SELECT 语句,这些 SELECT 语句是 彼此之间也一致。参见第 17.7.2.3 节“一致的非锁定读取”。InnoDB

    对于锁定读取SELECT 和 或 )、UPDATE 和 DELETE 语句,锁定 取决于语句是否使用带有 唯一搜索条件,或范围类型搜索条件。FOR UPDATEFOR SHARE

    • 对于具有唯一搜索条件的唯一索引,仅锁定索引记录 找到的,而不是之前的差距InnoDB

    • 对于其他搜索条件,锁定扫描的索引范围,使用间隙锁下一键锁来阻止其他会话插入间隙 覆盖范围。有关间隙锁定的信息 和下一个键锁,请参见第 17.7.1 节“ InnoDB 锁定”。InnoDB

    不建议混合使用锁定语句 (UPDATE、INSERT、DELETE 或 )替换为非锁定 SELECT 语句,因为通常在这种情况下,您希望 SERIALIZABLE。这是 因为非锁定 SELECT 语句表示读取时数据库的状态 视图,该视图包含在 read 视图,并且在当前事务的 own 写入,而 locking 语句使用最新的 state 的数据库来使用锁定。一般来说,这两个 不同的表状态彼此不一致,并且 难以解析。SELECT ... FORM ...

  • READ COMMITTED

    每个一致性读取,即使在同一个事务中,也会设置 并读取自己的新快照。有关 consistent reads,请参见第 17.7.2.3 节“一致的非锁定读取”。

    对于锁定读取(SELECT with or )、UPDATE 语句和 DELETE 语句,仅锁定索引 记录,而不是它们之前的间隙,因此允许 free 在锁定记录旁边插入新记录。间隙锁定 仅用于外键约束检查,而 重复键检查。FOR UPDATEFOR SHAREInnoDB

    由于禁用了间隙锁定,因此幻像行问题可能会 发生,因为其他会话可以将新行插入到间隙中。 有关幻像行的信息,请参见第 17.7.4 节“幻像行”。

    隔离级别仅支持基于行的二进制日志记录。如果你 与 binlog_format=MIXED 一起使用时, Server 自动使用基于行的日志记录。READ COMMITTEDREAD COMMITTED

  • 使用 has additional 影响:READ COMMITTED

    • 对于 UPDATE 或 DELETE 语句,仅对满足以下条件的行保持锁定 它会更新或删除。不匹配行的记录锁 在 MySQL 评估条件后释放。这大大降低了 死锁的可能性,但它们仍然可能发生。InnoDBWHERE

    • 对于 UPDATE 语句,如果 行已锁定,执行 “半一致” 读取, 将最新提交的版本返回给 MySQL,以便 MySQL 可以确定该行是否与 UPDATE 的条件匹配。如果行 matches(必须更新),MySQL 会再次读取该行,并且 这次要么锁定它,要么 等待其上的锁定。InnoDBWHEREInnoDB

    请考虑以下示例,从下表开始:

    CREATE TABLE t (a INT NOT NULL, b INT) ENGINE = InnoDB;
    INSERT INTO t VALUES (1,2),(2,3),(3,2),(4,3),(5,2);
    COMMIT;

    在这种情况下,表没有索引,因此搜索和 索引扫描使用隐藏的聚集索引作为记录 锁定而不是 比索引列。

  •   聚集索引和二级索引

    每个表都有一个名为 存储行数据的聚集索引。通常,集群 index 与主键同义。为了获得最佳效果 查询、插入和其他数据库操作的性能, 了解如何使用 用于优化常用查找和 DML 的聚集索引 操作。InnoDBInnoDB

    • 在表上定义 时,将其用作聚集索引。一个 应为每个表定义主键。如果没有 逻辑唯一和非 null 列或一组列来使用 主键,添加自增列。自动递增 列值是唯一的,并自动添加新值 行。PRIMARY KEYInnoDB

    • 如果您没有为 table 使用定义了所有键列的第一个索引 as 作为聚集索引。PRIMARY KEYInnoDBUNIQUENOT NULL

    • 如果表没有索引或具有合适的索引,则生成一个在合成列上命名的隐藏聚集索引,该索引 包含行 ID 值。行按行 ID 排序 那分配。行 ID 为 6 字节 字段,该字段在插入新行时单调增加。 因此,按行 ID 排序的行在物理上是有序的 的插入。PRIMARY KEYUNIQUEInnoDBGEN_CLUST_INDEXInnoDB

    聚集索引如何加快查询速度

    通过聚集索引访问行的速度很快,因为 索引搜索直接指向包含该行的页面 数据。如果表很大,则聚集索引体系结构 与存储相比,通常可以节省磁盘 I/O 操作 使用不同页面存储行数据的组织 索引记录。

    二级索引与聚集索引的关系

    聚集索引以外的索引称为辅助索引 指标。在 中,每条记录中的 secondary index 包含该行的主键列,因为 以及为 Secondary Index(二级索引)指定的列。 使用此主键值进行搜索 对于聚集索引中的行。InnoDBInnoDB

    如果主键很长,则二级索引使用更多 space,因此使用较短的主键是有利的。

    假设一个会话使用这些执行 UPDATE 语句:
    # Session A
    START TRANSACTION;
    UPDATE t SET b = 5 WHERE b = 3;

    还假设第二个会话通过执行这些 在第一次会议之后的发言:

    # Session B
    UPDATE t SET b = 4 WHERE b = 2;

    当 InnoDB 执行每个 UPDATE 时,它首先会获取一个 独占锁,然后确定是否 修改它。如果 InnoDB 没有 修改 Row,它会释放锁。否则,InnoDB 将保留锁定,直到 交易结束。这会影响交易 处理如下。

    当使用默认隔离级别时,第一个 UPDATE 会获取 x-lock on 它读取且不释放任何一行:REPEATABLE READ

    <span style="background-color:#ffffff"><span style="color:#555555"><span style="background-color:#f8f8f8"><span style="color:#000000"><code class="language-none">x-lock(1,2); retain x-lock
    x-lock(2,3); update(2,3) to (2,5); retain x-lock
    x-lock(3,2); retain x-lock
    x-lock(4,3); update(4,3) to (4,5); retain x-lock
    x-lock(5,2); retain x-lock</code></span></span></span></span>

    第二个 UPDATE 块为 一旦它尝试获取任何锁(因为第一次更新 在所有行上都保留了锁),并且在 第一个 UPDATE 提交或 回滚:

    x-lock(1,2); block and wait for first UPDATE to commit or roll back

    If 改用 第一个 UPDATE 获取 x-lock 读取的每一行,并释放行的 x-lock 它不会修改:READ COMMITTED

    <span style="background-color:#ffffff"><span style="color:#555555"><span style="background-color:#f8f8f8"><span style="color:#000000"><code class="language-none">x-lock(1,2); unlock(1,2)
    x-lock(2,3); update(2,3) to (2,5); retain x-lock
    x-lock(3,2); unlock(3,2)
    x-lock(4,3); update(4,3) to (4,5); retain x-lock
    x-lock(5,2); unlock(5,2)</code></span></span></span></span>

    对于第二个 ,执行 “semi-consistent” 读取,返回最新的 committed 版本读取到 MySQL 中,以便 MySQL 可以确定该行是否与 UPDATE 的条件匹配:UPDATEInnoDBWHERE

  • CREATE TABLE t (a INT NOT NULL, b INT, c INT, INDEX (b)) ENGINE = InnoDB;
    INSERT INTO t VALUES (1,2,3),(2,2,4);
    COMMIT;
    
    # Session A
    START TRANSACTION;
    UPDATE t SET b = 3 WHERE b = 2 AND c = 3;
    
    # Session B
    UPDATE t SET b = 4 WHERE b = 2 AND c = 4;

    隔离级别可以是 在启动时设置或在运行时更改。在运行时,它可以是 为所有会话全局设置,或为每个会话单独设置。READ COMMITTED

  • READ UNCOMMITTED

    SELECT 语句是 以非锁定方式执行,但可能更早 版本。因此,使用此隔离 级别,则此类读取不一致。这也称为脏读。 否则,此隔离级别的工作方式类似于 READ COMMITTED

  • SERIALIZABLE

    这个级别类似于 REPEATABLE READ,但隐式 将所有普通 SELECT 语句转换为 SELECT ...FOR SHARE(如果禁用了自动提交)。如果启用了自动提交,则 SELECT 是它自己的 交易。因此,已知它是只读的,并且可以 如果作为一致(非锁定)读取执行,则被序列化 并且不需要为其他交易冻结。(强制普通 SELECT 在显示其他 事务修改了所选行,请禁用自动提交InnoDB


原文地址:https://blog.csdn.net/whs_8792/article/details/144383496

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!