NDB Cluster在事务处理方面存在许多限制。其中包括:
事务隔离级别。 NDBCLUSTER存储引擎只支持READ COMMITTED事务隔离级别。(InnoDB,例如,支持 READ COMMITTED, READ UNCOMMITTED, REPEATABLE READ,和 SERIALIZABLE。)你应该记住,NDB器具 READ COMMITTED在每行的基础; 当读取请求到达存储该行的数据节点时,返回的是该行当时的最后提交版本。
未提交的数据永远不会返回,但是当修改多个行的事务与读取相同行的事务同时提交时,执行读取操作的事务可以观察其中的不同行的“ before ” 值,“ after ”值或两者。 ,这是因为可以在提交另一个事务之前或之后处理给定的行读取请求。
为确保给定的事务仅读取值之前或之后,可以使用施加行锁 SELECT ... LOCK IN SHARE MODE。在这种情况下,锁定将一直保持到拥有事务提交为止。使用行锁也会导致以下问题:
锁定等待超时错误的频率增加,并发减少
由于读取需要提交阶段,因此增加了事务处理开销
耗尽可用并发锁数的可能性受到以下限制: MaxNoOfConcurrentOperations
NDB用途READ COMMITTED对于所有除非改性剂,例如读取, LOCK IN SHARE MODE或FOR UPDATE使用。LOCK IN SHARE MODE导致使用共享的行锁; FOR UPDATE导致使用排他的行锁。唯一键读取会自动更新其锁,NDB以确保读取前后一致。BLOB读取还使用额外的锁定来保持一致性。
事务和BLOB或TEXT列。 NDBCLUSTER仅存储使用MySQL 可见表中的任何MySQL BLOB或 TEXT数据类型的列值的一部分 ;BLOB或 的其余部分 TEXT存储在MySQL无法访问的单独的内部表中。这引起了两个相关的问题,每当SELECT在包含这些类型的列的表上执行语句时,您都应该意识到 这些问题:
对于SELECTNDB群集表中的任何表:如果 SELECT包括a BLOB或 TEXT列,则 READ COMMITTED 事务隔离级别将转换为具有读取锁定的读取。这样做是为了保证一致性。
对于SELECT使用唯一键查找来检索使用任何BLOB或 TEXT数据类型并且在事务内执行的任何列的任何事物,在事务期间(即直到事务进行之前),共享的读取锁将保留在表上。被提交或中止。
使用索引或表扫描的查询不会发生此问题,即使对于 NDB具有 BLOB或 TEXT列的表也是如此。
例如,考虑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 BLOB或 TEXTcolumn 的值 。
通过避免使用检索BLOB或 TEXT列的唯一键查找的查询,或者在无法避免此类查询的情况下,通过尽早提交事务,可以帮助最大程度地减少共享读取锁的问题。
唯一的键查找和事务隔离。 唯一索引是NDB 通过使用内部维护的隐藏索引表实现的。当NDB使用唯一索引访问用户创建的表时,首先将读取隐藏的索引表以找到主键,然后使用该主键读取用户创建的表。为了避免在此双读操作期间修改索引,在隐藏索引表中找到的行将被锁定。当用户创建的唯一索引引用的行NDB 如果更新表,隐藏索引表将受到执行更新的事务的排他锁。这意味着对同一张(用户创建的)NDB表的任何读取操作都必须等待更新完成。即使读取操作的事务级别为,也是如此 READ COMMITTED。
可以用来绕过潜在的阻塞读取的一种解决方法是,强制SQL节点在执行读取时忽略唯一索引。这可以通过将IGNORE INDEX索引提示用作SELECT读取表的语句的一部分来完成(请参见第8.9.4节“索引提示”)。由于MySQL服务器会为中创建的每个唯一索引创建一个阴影排序索引NDB,因此可以读取该排序索引,并避免了唯一索引访问锁定。结果读取与主键提交的读取保持一致,并在读取行时返回最后的提交值。
通过有序索引进行读取会使群集中的资源使用效率降低,并且可能会有更高的延迟。
通过查询范围而不是唯一值,还可以避免使用唯一索引进行访问。
回滚。 没有部分事务,也没有部分事务回滚。重复的密钥或类似错误会导致整个事务回滚。
此行为不同于其他事务存储引擎的行为,例如InnoDB 可能回滚单个语句的行为。
事务和内存使用情况。 如本章其他地方所述,NDB群集不能很好地处理大型事务。与尝试包含多个操作的单个大型事务相比,执行多个具有少量操作的小型事务要好。除其他考虑因素外,大型事务需要非常大量的内存。因此,如下列表中所述,许多MySQL语句的事务行为受到影响:
TRUNCATE TABLE在NDB表上使用时不是事务性的 。如果 TRUNCATE TABLE不能清空表,则必须重新运行它,直到成功。
DELETE FROM(即使没有 WHERE子句)也是 事务性的。对于包含很多行的表,您可能会发现通过使用多个DELETE FROM ... LIMIT ... 语句对删除操作进行“分块 ”可以提高性能。如果您的目标是清空表格,则不妨使用TRUNCATE TABLE。
LOAD DATA语句。 LOAD DATA在NDB表上使用时不是事务性的 。
重要
执行LOAD DATA语句时, NDB引擎以不规则的时间间隔执行提交,从而可以更好地利用通信网络。无法提前知道何时进行此类提交。
ALTER TABLE和事务。 当将NDB表格复制为的一部分时ALTER TABLE,副本的创建是非事务性的。(无论如何,删除副本后都会回滚此操作。)
事务和COUNT()函数。 使用NDB群集复制时,无法保证COUNT()从服务器上功能的事务一致性 。换句话说,在主服务器上执行更改单个事务中表中的行数的一系列语句(INSERT, DELETE或两者)时,在从服务器上执行查询可能会产生中间结果。这是由于可能执行脏读,而不是存储引擎中的错误 。(有关更多信息,请参见Bug#31321。) SELECT COUNT(*) FROM tableSELECT COUNT(...)NDB