Spec-Zone.ru › MySQL 5.7

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 или TEXT MySQL в таблице, видимой для MySQL; остальная часть BLOB или TEXT хранится в отдельной внутренней таблице, недоступной для MySQL. Это приводит к двум связанным проблемам, о которых следует помнить при выполнении запросов SELECT на таблицах, содержащих столбцы этих типов:

    1. Для любого SELECT из таблицы NDB Cluster: если SELECT включает столбец BLOB или TEXT, уровень изоляции транзакций READ COMMITTED преобразуется в чтение с блокировкой чтения. Это делается для обеспечения согласованности.

    2. Для любого 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.

      Важно

      При выполнении инструкции LOAD DATA, движок NDB выполняет фиксации в нерегулярные промежутки времени, что позволяет улучшить использование сети связи. Точное время таких фиксаций невозможно определить заранее.

    • ALTER TABLE и транзакции. При копировании таблицы NDB в рамках ALTER TABLE, создание копии выполняется вне транзакции. (В любом случае, эта операция отменяется при удалении копии.)

  • Транзакции и функция COUNT(). При использовании репликации NDB Cluster невозможно гарантировать транзакционную согласованность функции COUNT() на реплике. Другими словами, при выполнении на источнике последовательности инструкций (INSERT, DELETE или их комбинации), изменяющих количество строк в таблице в рамках одной транзакции, выполнение запросов SELECT COUNT(*) FROM table на реплике может возвращать промежуточные результаты. Это происходит из-за того, что SELECT COUNT(...) может выполнять чтение несогласованных данных, и это не ошибка движка хранения NDB. (См. баг #31321 для получения дополнительной информации.)

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/mysql-cluster-limitations-transactions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API