Влияние доступности данных для пользователей при выполнении больших обновлений таблицы - PullRequest
0 голосов
/ 09 мая 2020

Я пытаюсь понять, как огромный объем обновлений в таблицах влияет на доступность данных для пользователей. Я просматривал различные сообщения ( fastest-way-to-update-120-миллионные записи , Избегайте блокировки при обновлении ), в которых рассматриваются различные механизмы для выполнения больших обновлений, таких как заполнение полностью новой таблицы, если это можно сделать в автономном режиме. Если он не может быть в автономном режиме, то выполняются пакетные обновления.

Я пытаюсь понять, как эти большие обновления влияют на доступность таблицы для пользователя и как лучше всего делать большие обновления, обеспечивая при этом доступность таблицы для чтения.

Пример использования: обновление деталей транзакции на основе первичного ключа (например, обновление запасов из-за разделения акций)

1 Ответ

2 голосов
/ 09 мая 2020

Непонятно, что вам нужно сделать.

  • Заменить всю таблицу - заполнить новую таблицу, а затем поменять местами
  • Изменить один столбец для всех строк - Звучит как неряшливо дизайн. Пожалуйста, поясните, что вы делаете.
  • Измените один столбец для некоторых строк - то же самое.
  • Добавление нового столбца и его инициализация - Рассмотрите возможность создания параллельной таблицы и т.д. c. Это будет иметь нулевую блокировку, но усложнит ваш код.
  • Значения вычисляются из других столбцов - рассмотрим «сгенерированный» столбец. (Какую версию MySQL вы используете?)

Вот обсуждение того, как пройти по таблице с помощью PRIMARY KEY и минимизировать влияние на другие запросы: http://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks (Он написан с учетом DELETE, но принцип применим и к UPDATE)

Доступность таблицы

При любой операции При этом соответствующие строки «блокируются», чтобы другие запросы не могли изменять их одновременно. («Блокировка включает в себя управление несколькими версиями, et c, et c.) Они должны оставаться заблокированными до тех пор, пока не будет завершена вся« транзакция ». Между тем, любые изменения должны быть записаны на случай сбоя сервера или пользователя решает «откатить» изменения.

Итак, если изменяются миллионы строк, то удерживаются миллионы блокировок. Это требует времени.

Мой блог рекомендует делать только 1000 строк за раз; это обычно достаточно небольшое количество, чтобы иметь очень небольшое влияние на другие задачи, но достаточно большое, чтобы завершить задачу за разумный промежуток времени.

Stock Split

Предполагая, что желаемый запрос (к огромной таблице) имеет вид

UPDATE t
    SET price = 2 * price
    WHERE date < '...'
      AND ticker = '...' 

Вам нужен индекс (или, возможно, PRIMARY KEY), равный (ticker, date). Большинство записи ориентированы на дату, но большинство операций чтения ориентировано на тикер? Учитывая это, следующее может быть оптимальным:

PRIMARY KEY(ticker, date),
INDEX(date, ticker)

При этом строки, которые необходимо изменить с помощью UPDATE, - это ' кластеризованный '( последовательный) в BTree данных. Следовательно, есть некоторая степень эффективности. Если, однако, этого недостаточно, тогда будет довольно легко написать код вроде:

date_a = SELECT MIN(date) FROM t WHERE ticker = ?
SET AUTOCOMMIT=ON
Loop
    date_z = date_a + 1 month
    UPDATE t
        SET price = 2 * price
        WHERE date >= ?    -- put date_a here
          AND date <  ?    -- put date_z here
          AND ticker = '...' 
    check for deadlock; if found, re-run the UPDATE
    set date_a = date_z
    exit loop when finished
End Loop

Это будет достаточно быстро и мало повлияет на другие запросы. Однако, если кто-то смотрит на этот тикер в течение ряда дней, цены могут не обновляться постоянно. (Если это вас беспокоит, мы можем обсудить дальше.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...