Spec-Zone.ru › MySQL 8.4

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 хранит только часть значения столбца, использующего любой из типов данных MySQL BLOB или TEXT в таблице, видимой 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-8.4-en/mysql-cluster-limitations-transactions.html

Spec-Zone.ru

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