21.2.7.3 Ограничения, связанные с обработкой транзакций в NDB Cluster
Существует ряд ограничений в NDB Cluster, касающихся обработки транзакций. Они включают следующее:
-
Уровень изоляции транзакций. СУБД
NDBCLUSTERподдерживает только уровень изоляции транзакцийREAD COMMITTED. (InnoDB, например, поддерживаетREAD COMMITTED,READ UNCOMMITTED,REPEATABLE READиSERIALIZABLE.) Следует учитывать, чтоNDBреализуетREAD COMMITTEDна основе каждой строки; когда запрос чтения поступает на узел данных, хранящий строку, возвращается последняя сохранённая версия строки на тот момент.Несохранённые данные никогда не возвращаются, но когда транзакция, изменяющая несколько строк, сохраняется одновременно с транзакцией, читающей те же строки, транзакция, выполняющая чтение, может наблюдать значения «перед» , «после» или оба для разных строк среди них, из-за того, что запрос чтения конкретной строки может быть обработан до или после сохранения другой транзакции.
Чтобы гарантировать, что данная транзакция читает только значения «перед» или «после», можно наложить блокировки на строки, используя
SELECT ... LOCK IN SHARE MODE. В таких случаях блокировка удерживается до тех пор, пока владеющая транзакция не сохранится. Использование блокировок строк также может вызвать следующие проблемы:Увеличение частоты ошибок таймаута ожидания блокировки и уменьшение конкурентности
Увеличение накладных расходов на обработку транзакций из-за того, что чтение требует фазы сохранения
Возможность исчерпания доступного количества одновременных блокировок, ограниченного параметром
MaxNoOfConcurrentOperations
NDBиспользуетREAD COMMITTEDдля всех чтений, если не используется модификатор, такой какLOCK IN SHARE MODEилиFOR UPDATE.LOCK IN SHARE MODEприводит к использованию общих блокировок строк;FOR UPDATEприводит к использованию эксклюзивных блокировок строк. Чтения уникальных ключей автоматически повышают свои блокировкиNDB, чтобы обеспечить согласованное чтение; чтенияBLOBтакже используют дополнительные блокировки для обеспечения согласованности.См. Раздел 21.6.8.4, «Отладка резервного копирования NDB Cluster» для получения информации о том, как реализация уровня изоляции транзакций NDB Cluster может повлиять на резервное копирование и восстановление баз данных
NDB. -
Транзакции и столбцы BLOB или TEXT.
NDBCLUSTERхранит только часть значения столбца, использующего любой из типов данныхBLOBилиTEXTMySQL в таблице, видимой для MySQL; остальная частьBLOBилиTEXTхранится в отдельной внутренней таблице, недоступной для MySQL. Это приводит к двум связанным проблемам, о которых следует помнить при выполнении запросовSELECTна таблицах, содержащих столбцы этих типов:Для любого
SELECTиз таблицы NDB Cluster: еслиSELECTвключает столбец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;
Это потому, что из этих четырёх запросов первый использует сканирование индекса, второй и третий — сканирование таблиц, а четвёртый, хотя и использует поиск по первичному ключу, не извлекает значение столбцов
BLOBилиTEXT.Можно минимизировать проблемы с общими блокировками чтения, избегая запросов, которые используют поиск по уникальным ключам для извлечения столбцов
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. ALTER TABLE и транзакции. При копировании таблицы
NDBв рамкахALTER TABLE, создание копии выполняется вне транзакции. (В любом случае, эта операция отменяется при удалении копии.)
Транзакции и функция COUNT(). При использовании репликации NDB Cluster невозможно гарантировать транзакционную согласованность функции
COUNT()на реплике. Другими словами, при выполнении на источнике последовательности инструкций (INSERT,DELETEили их комбинации), изменяющих количество строк в таблице в рамках одной транзакции, выполнение запросовSELECT COUNT(*) FROMна реплике может возвращать промежуточные результаты. Это происходит из-за того, чтоtableSELECT COUNT(...)может выполнять чтение несогласованных данных, и это не ошибка движка храненияNDB. (См. баг #31321 для получения дополнительной информации.)
© 2025 Oracle
Licensed under the GPLv2 License.