Spec-Zone.ru › MySQL 9.2

25.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 также используют дополнительные блокировки для обеспечения согласованности.

    См. Раздел 25.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 чтения таблицы (см. Раздел 10.9.4, «Подсказки индексов»). Поскольку сервер MySQL создает отслеживающий упорядоченный индекс для каждого уникального индекса, созданного в NDB, это позволяет прочитать упорядоченный индекс вместо этого и избежать блокировки доступа к уникальному индексу. Результат чтения так же согласован, как и подтвержденное чтение по первичному ключу, возвращая последнее подтвержденное значение в момент чтения строки.

    Чтение через упорядоченный индекс менее эффективно использует ресурсы в кластере и может иметь более высокую задержку.

    Также можно избежать использования уникального индекса для доступа, запросив диапазоны, а не уникальные значения.

  • Откаты. Частичных транзакций и частичных откатов транзакций нет. Ошибка дублирования ключа или аналогичная ошибка приводит к откату всей транзакции.

    Это поведение отличается от поведения других транзакционных движков хранилища, таких как InnoDB, которые могут откатить отдельные инструкции.

  • Транзакции и использование памяти. Как отмечалось в другом месте данной главы, NDB Cluster не эффективно обрабатывает большие транзакции; лучше выполнить несколько небольших транзакций с несколькими операциями каждая, чем пытаться выполнить одну большую транзакцию, содержащую множество операций. Среди прочего, для больших транзакций требуется очень большой объем памяти. По этой причине поведенческий аспект транзакций ряда операторов 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 Replication невозможно гарантировать транзакционную согласованность функции 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-9.2-en/mysql-cluster-limitations-transactions.html

Spec-Zone.ru

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