• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • NDB群集中与事务处理相关的限制

    NDB Cluster在事务处理方面存在许多限制。其中包括:

    • 事务隔离级别。NDBCLUSTER存储引擎只支持READ COMMITTED事务隔离级别。(InnoDB,例如,支持READ COMMITTEDREAD UNCOMMITTEDREPEATABLE READ,和SERIALIZABLE。)你应该记住,NDB器具READ COMMITTED在每行的基础;当读取请求到达存储该行的数据节点时,返回的是该行当时的最后提交版本。

      未提交的数据永远不会返回,但是当修改多个行的事务与读取相同行的事务同时提交时,执行读取操作的事务可以观察其中的不同行的“ before ”值,“ after ”值或两者。,这是因为可以在提交另一个事务之前或之后处理给定的行读取请求。

      为确保给定的事务仅读取值之前或之后,可以使用施加行锁SELECT ... LOCK IN SHARE MODE。在这种情况下,锁定将一直保持到拥有事务提交为止。使用行锁也会导致以下问题:

      • 锁定等待超时错误的频率增加,并发减少
      • 由于读取需要提交阶段,因此增加了事务处理开销
      • 耗尽可用并发锁数的可能性受到以下限制:MaxNoOfConcurrentOperations

      NDB用途READ COMMITTED对于所有除非改性剂,例如读取,LOCK IN SHARE MODEFOR UPDATE使用。LOCK IN SHARE MODE导致使用共享的行锁;FOR UPDATE导致使用排他的行锁。唯一键读取会自动更新其锁,NDB以确保读取前后一致。BLOB读取还使用额外的锁定来保持一致性。

      有关NDB Cluster的事务隔离级别的实现如何影响数据库的备份和还原的信息,请参见“ NDB Cluster备份故障排除”NDB

    • 事务和BLOB或TEXT列。NDBCLUSTER仅存储使用MySQL 可见表中的任何MySQL BLOBTEXT数据类型的列值的一部分;BLOB或的其余部分TEXT存储在MySQL无法访问的单独的内部表中。这引起了两个相关的问题,每当SELECT在包含这些类型的列的表上执行语句时,您都应该意识到这些问题:

      1. 对于SELECTNDB群集表中的任何表:如果SELECT包括a BLOBTEXT列,则READ COMMITTED事务隔离级别将转换为具有读取锁定的读取。这样做是为了保证一致性。
      2. 对于SELECT使用唯一键查找来检索使用任何BLOBTEXT数据类型并且在事务内执行的任何列的任何事物,在事务期间(即直到事务进行之前),共享的读取锁将保留在表上。被提交或中止。

        使用索引或表扫描的查询不会发生此问题,即使对于NDB具有BLOBTEXT列的表也是如此。

        例如,考虑t以下CREATE TABLE语句定义的表:

        CREATE TABLE t (
            a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
            b INT NOT NULL,
            c INT NOT NULL,
            d TEXT,
            INDEX i(b),
            UNIQUE KEY u(c)
        ) ENGINE = NDB,
        

        以下查询t由于使用唯一键查找而导致共享读取锁定:

        SELECT * FROM t WHERE c = 1;
        

        但是,此处显示的四个查询都不会导致共享读取锁定:

        SELECT * FROM t WHERE b = 1;
        
        SELECT * FROM t WHERE d = '1';
        
        SELECT * FROM t;
        
        SELECT b,c WHERE a = 1;
        

        这是因为在这四个查询中,第一个使用索引扫描,第二个和第三个使用表扫描,而第四个在使用主键查找时,不检索any BLOBTEXTcolumn 的值。

        通过避免使用检索BLOBTEXT列的唯一键查找的查询,或者在无法避免此类查询的情况下,通过尽早提交事务,可以帮助最大程度地减少共享读取锁的问题。

    • 唯一的键查找和事务隔离。唯一索引是NDB通过使用内部维护的隐藏索引表实现的。当NDB使用唯一索引访问用户创建的表时,首先将读取隐藏的索引表以找到主键,然后使用该主键读取用户创建的表。为了避免在此双读操作期间修改索引,在隐藏索引表中找到的行将被锁定。当用户创建的唯一索引引用的行NDB如果更新表,隐藏索引表将受到执行更新的事务的排他锁。这意味着对同一张(用户创建的)NDB表的任何读取操作都必须等待更新完成。即使读取操作的事务级别为,也是如此READ COMMITTED

      可以用来绕过潜在的阻塞读取的一种解决方法是,强制SQL节点在执行读取时忽略唯一索引。这可以通过将IGNORE INDEX索引提示用作SELECT读取表的语句的一部分来完成(请参见“索引提示”)。由于MySQL服务器会为中创建的每个唯一索引创建一个阴影排序索引NDB,因此可以读取该排序索引,并避免了唯一索引访问锁定。结果读取与主键提交的读取保持一致,并在读取行时返回最后的提交值。

      通过有序索引进行读取会使群集中的资源使用效率降低,并且可能会有更高的延迟。

      通过查询范围而不是唯一值,还可以避免使用唯一索引进行访问。

    • 回滚。没有部分事务,也没有部分事务回滚。重复的密钥或类似错误会导致整个事务回滚。

      此行为不同于其他事务存储引擎的行为,例如InnoDB可能回滚单个语句的行为。

    • 事务和内存使用情况。如本章其他地方所述,NDB群集不能很好地处理大型事务。与尝试包含多个操作的单个大型事务相比,执行多个具有少量操作的小型事务要好。除其他考虑因素外,大型事务需要非常大量的内存。因此,如下列表中所述,许多MySQL语句的事务行为受到影响:

      • TRUNCATE TABLENDB表上使用时不是事务性的。如果TRUNCATE TABLE不能清空表,则必须重新运行它,直到成功。
      • DELETE FROM(即使没有WHERE子句)也是事务性的。对于包含很多行的表,您可能会发现通过使用多个DELETE FROM ... LIMIT ...语句对删除操作进行“分块”可以提高性能。如果您的目标是清空表格,则不妨使用TRUNCATE TABLE
      • LOAD DATA语句。LOAD DATANDB表上使用时不是事务性的。

        重要

        执行LOAD DATA语句时,NDB引擎以不规则的时间间隔执行提交,从而可以更好地利用通信网络。无法提前知道何时进行此类提交。

      • ALTER TABLE和事务。当将NDB表格复制为的一部分时ALTER TABLE,副本的创建是非事务性的。(无论如何,删除副本后都会回滚此操作。)
    • 事务和COUNT()函数。使用NDB群集复制时,无法保证COUNT()从服务器上功能的事务一致性。换句话说,在主服务器上执行更改单个事务中表中的行数的一系列语句(INSERTDELETE或两者)时,在从服务器上执行查询可能会产生中间结果。这是由于可能执行脏读,而不是存储引擎中的错误。(有关更多信息,请参见Bug#31321。)SELECT COUNT(*)FROM tableSELECT COUNT(...)NDB