Рубрики
Без рубрики

Оптимистичная блокировка логических и физических часов

Автор оригинала: Vlad Mihalcea.

Вступление

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

Оптимистичная блокировка-это жизнеспособное решение для предотвращения потери обновлений при выполнении транзакций на уровне приложений .

Оптимистическая блокировка требует столбца версии, который может быть представлен в виде:

  • физические часы (значение метки времени, взятое из системных часов)
  • логические часы (увеличивающееся числовое значение)

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

Системное время

Системное время обеспечивается внутренними часами текущей операционной системы. Программируемый интервальный таймер периодически посылает сигнал прерывания (с частотой 1,193182 МГц). Процессор получает прерывание по времени и увеличивает счетчик тиков.

И Unix, и Window записывают время как количество тиков с момента заданной абсолютной привязки времени (эпоха). Разрешение часов операционной системы варьируется от 1 мс (Android) до 100 мс (Windows) и до 1 мс (Unix) .

Монотонное время

Чтобы упорядочить события, версия должна продвигаться монотонно. Хотя увеличение локального счетчика является монотонной функцией, системное время не всегда может возвращать монотонные метки времени.

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

  1. Система#currentTimeMillis() , которая дает вам количество миллисекунд, прошедших с эпохи Unix

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

    Для монотонного текущего времени вы можете проверить Решение Питера Лоури или |/Монотонные часы диспетчера транзакций Bitronix . Система#nanoTime()

  2. , которая возвращает количество наносекунд, прошедших с момента произвольно выбранной привязки времени Этот метод пытается использовать реализацию монотонных часов текущей операционной системы, но он
  3. возвращается к времени настенных часов , если монотонные часы не найдены.

Системное время не всегда монотонно увеличивается.

Точность временных меток базы данных

Стандарт SQL-92 определяет тип данных МЕТКИ ВРЕМЕНИ как ГГГГ-ММ-ДД чч:мм:сс. Часть дроби необязательна, и каждая база данных реализует определенный тип данных метки времени:

Оракул ВРЕМЕННАЯ МЕТКА(9) может содержать до 9 дробных цифр (с точностью до наносекунды).
MSSQL DATETIME2 имеет точность 100 нс.
MySQL MySQL 5.6.4 добавил поддержку точности в микросекундах для типов ВРЕМЕНИ, ДАТЫ и ВРЕМЕНИ и МЕТОК ВРЕМЕНИ. До версии 5.6.4 MySQL отбрасывает дробную часть всех временных типов.
PostgreSQL Оба типа ВРЕМЕНИ и МЕТОК ВРЕМЕНИ имеют точность в микросекунды.
DB2 ВРЕМЕННАЯ МЕТКА(12) может содержать до 12 дробных цифр (точность в пикосекунду).

Когда дело доходит до сохранения временных меток, большинство серверов баз данных предлагают не менее 6 дробных цифр. Пользователи MySQL долго ждали более точного временного типа, и версия 5.6.4 наконец-то добавила точность в микросекунды.

На сервере баз данных MySQL до версии 5.6.4 обновления могут быть потеряны в течение любой заданной секунды. Это связано с тем, что все транзакции, обновляющие одну и ту же строку базы данных, будут видеть одну и ту же отметку времени версии (которая указывает на начало текущей секунды).

До версии 5.6.4 MySQL поддерживал только временные метки второй точности.

Время обработки не так просто

Увеличение локального номера версии всегда безопаснее, потому что эта операция не зависит от каких-либо внешних факторов. Если строка базы данных уже содержит более высокий номер версии, ваши данные устарели. Все очень просто.

С другой стороны, время-одно из самых сложных измерений, с которым приходится иметь дело. Если вы мне не верите, проверьте на предмет учета перехода на летнее время .

Потребовалось 8 версий Java, чтобы, наконец, создать зрелый API даты/времени . Время обработки на разных уровнях приложений (от JavaScript до промежуточного программного обеспечения Java до типов даты/времени базы данных) ухудшает ситуацию.

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

Уроки распределенных вычислений

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

В распределенных вычислениях логические часы предпочтительнее физических (системные часы), потому что синхронизация времени в сетях подразумевает переменные задержки.

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

В то время как Метки времени Lamport были определены для синхронизации событий нескольких распределенных узлов, оптимистическая блокировка базы данных намного проще, поскольку существует только один узел (сервер базы данных), на котором синхронизируются все транзакции (исходящие из одновременных клиентских подключений).

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

Вывод

Использование физического времени поначалу может показаться удобным, но это оказывается наивным решением. В распределенной среде идеальная синхронизация системного времени наиболее маловероятна. В целом, вы всегда должны отдавать предпочтение логическим часам при реализации оптимистичного механизма блокировки.