Ну как можно утверждать, что "такое-то значение такого-то параметра приводит к таким-то ожиданиям"? Нехорошее значение может привести к избыточно большому объему работы, которое может привести к тому, что каких-то ожиданий станет больше, чем могло бы. Сплошная спекуляция, короче.
Как это формализовать для автоматической диагностики - не знаю. По идее, признаком плохой настройки являются пики дисковой активности (но кто даст гарантию, что зарегистрированный пик вызван именно контрольной точкой?) и в целом избыточная дисковая активность (но как понять без экспериментов с разными настройками на одной и той же нагрузке, что активность избыточна?).
Мм, да, я имел в виду ситуацию, когда две транзакции действительно пересеклись по данным. PostgreSQL на уровне Repeatable Read перечитает строку, которая была заблокирована, и, если она изменилась, оборвет транзакцию.
Я бы так сказал: про рекомендательные блокировки надо вспомнить, когда потребуется сделать что-то такое, что на обычные блокировки ложится плохо. Не всегда может найтись подходящая таблица.
И еще - рекомендательные блокировки работают быстрее блокировок строк, поскольку никак не меняют страницы данных. В каких-то случаях это может оказаться важным для быстродействия.
А как насчет gap lock и Next-Key Locks в Mysql? Не являются ли они по сути теми же предикатными блокировками?
Возможно я неточно выразился. Похожие по смыслу блокировки есть, но их реализация радикально отличается от предложенного в статье. В PostgreSQL (и, насколько я представляю, в MySQL тоже) они опираются на индекс. Только в PostgreSQL это даже и не блокировка, а способ отследить зависимость.
Хотя опять же непонятно, если Mysql реализует честный MVCC, то зачем ему вообще такого рода блокировки.
PostgreSQL в такой ситуации оборвет одну из транзакций при попытке фиксации. Возможно, в MySQL этого пытаются избежать с помощью блокировки. Но тогда после снятия блокировки транзакция должна перечитывать новое состояние; не знаю, как с этим в MySQL, не исследовал.
А так ли это? Можно цитату из стандарта, где это прямо говорится?
Конечно можно цитату:
The execution of concurrent SQL-transactions at isolation level SERIALIZABLE is guaranteed to be serializable. A serializable execution is defined to be an execution of the operations of concurrently executing SQL-transactions that produces the same effect as some serial execution of those same SQL-transactions. A serial execution is one in which each SQL-transaction executes to completion before the next SQL-transaction begins.
Я думаю, что согласно Стандарту, Serializable - это как раз - таки уровень, на котором не допускаются грязное, неповторяющееся и фантомное чтение. И не более того.
Минус — средняя черта (–), которая используется в числовых диапазонах.
В диапазонах принято использовать либо обычное тире без отбивки, либо (в западной типографике, а в последнее время часто и у нас) — короткое тире. А минус — это отдельный знак, который используется в математическом наборе. Он отличается тем, что по ширине как плюс и выровнен по высоте цифр.
Там есть к чему попридираться (например, «с одним объектом может работать несколько рабочих процессов» — на самом деле нет) и некоторые рекомендации конкретных цифр мне сомнительны, но в целом адекватно, вредных советов я не заметил.
Кстати, в грядущей 17-й версии сильно уменьшили потребление памяти, и она к тому же будет выделяется по мере необходимости, а не вся сразу.
checkpoint_completion_target = 0.1 и max_wal_size = 10GB
это то же самое, что и (в плане объема данных, которые будут записаны):
checkpoint_completion_target = 0.5 и max_wal_size = 2GB
Так ведь нет же.
Если считать, что max_wal_size - это объем данных, который должен быть записан между контрольными точками (что само по себе не верно), то объем данных в первом случае будет 10GB, а во втором - 2GB.
А если смотреть на необходимую скорость записи, то (считая для простоты, что контрольные точки выполняются раз в 10 минут) в первом случае надо писать со скоростью 10GB/min, а во втором - 0.4GB/min. Вот вы и создали пик на пустом месте.
Кстати, с 14-й версии значение по умолчанию 0.9, и это неспроста.
Это максимальный объем памяти, выделяемый для каждого подключения (для обработки запросов). Следовательно, посчитать общий объем занимаемой памяти можно путем умножения на максимально возможное количество одновременных подключений со стороны приложения.
Этот объем памяти может при необходимости выделяться каждому узлуплана. (Не говоря уже о том, что в некоторых случаях и это ограничение не учитывается.) Поэтому умножать примерно бесполезно.
Сильно сомневаюсь. Хотя бы потому, что производительность — это объем работы в единицу времени, а стоимость — это оценка общего объема работы. А во-вторых, оценка может слабо коррелировать с реальностью, это характеристики из двух разных вселенных.
В этом примере обновление отработало верно, но запрос SELECT, который выполнялся долго (для демонстрации эффекта в него вставлен pg_sleep), увидел разные состояния таблицы: одна строка - до обновления, вторая - уже после.
Загадочные ~>=~ и ~<~. В документации, в разделе посвященным текстовым операторам, они отсутствуют. Я пытался гуглить, по ним вообще нет никакой информации. Знаю только, что еще существуют операторы ~<=~ и ~>~. И все они работают с текстом таинственным образом.
Там ничего таинственного, эти операторы сравнивают строки посимвольно, без учета правил сортировки (collation). В доке их, действительно, почему-то нет. Они входят в классы операторов *_pattern_ops, про которые мимоходом сказано в https://postgrespro.ru/docs/postgresql/16/indexes-opclass#INDEXES-OPCLASS. Видимо, считается, что этого и достаточно.
Ну как можно утверждать, что "такое-то значение такого-то параметра приводит к таким-то ожиданиям"? Нехорошее значение может привести к избыточно большому объему работы, которое может привести к тому, что каких-то ожиданий станет больше, чем могло бы. Сплошная спекуляция, короче.
А на тему оптимальной настройки контрольной точки можно диссертации писать. Мое изложение традиционного подхода есть в https://postgrespro.ru/education/books/internals, раздел 10.6. Другой взгляд (практика!) есть в https://postgrespro.ru/education/books/monitoring, раздел 5.7.
Как это формализовать для автоматической диагностики - не знаю. По идее, признаком плохой настройки являются пики дисковой активности (но кто даст гарантию, что зарегистрированный пик вызван именно контрольной точкой?) и в целом избыточная дисковая активность (но как понять без экспериментов с разными настройками на одной и той же нагрузке, что активность избыточна?).
Мм, да, я имел в виду ситуацию, когда две транзакции действительно пересеклись по данным. PostgreSQL на уровне Repeatable Read перечитает строку, которая была заблокирована, и, если она изменилась, оборвет транзакцию.
А с MySQL я бы начал разбираться с изучения https://jepsen.io/analyses/mysql-8.0.34. Там много интересного.
Я бы так сказал: про рекомендательные блокировки надо вспомнить, когда потребуется сделать что-то такое, что на обычные блокировки ложится плохо. Не всегда может найтись подходящая таблица.
И еще - рекомендательные блокировки работают быстрее блокировок строк, поскольку никак не меняют страницы данных. В каких-то случаях это может оказаться важным для быстродействия.
Возможно я неточно выразился. Похожие по смыслу блокировки есть, но их реализация радикально отличается от предложенного в статье. В PostgreSQL (и, насколько я представляю, в MySQL тоже) они опираются на индекс. Только в PostgreSQL это даже и не блокировка, а способ отследить зависимость.
PostgreSQL в такой ситуации оборвет одну из транзакций при попытке фиксации. Возможно, в MySQL этого пытаются избежать с помощью блокировки. Но тогда после снятия блокировки транзакция должна перечитывать новое состояние; не знаю, как с этим в MySQL, не исследовал.
Конечно можно цитату:
The execution of concurrent SQL-transactions at isolation level SERIALIZABLE is guaranteed to be serializable. A serializable execution is defined to be an execution of the operations of concurrently executing SQL-transactions that produces the same effect as some serial execution of those same SQL-transactions. A serial execution is one in which each SQL-transaction executes to completion before the next SQL-transaction begins.
Ни в коем случае.
Стоило бы получше разобраться в теме.
Это всё не лапки. Лапки — это „вот что такое“.
В диапазонах принято использовать либо обычное тире без отбивки, либо (в западной типографике, а в последнее время часто и у нас) — короткое тире. А минус — это отдельный знак, который используется в математическом наборе. Он отличается тем, что по ширине как плюс и выровнен по высоте цифр.
Вот сейчас обидно было.
Там есть к чему попридираться (например, «с одним объектом может работать несколько рабочих процессов» — на самом деле нет) и некоторые рекомендации конкретных цифр мне сомнительны, но в целом адекватно, вредных советов я не заметил.
Кстати, в грядущей 17-й версии сильно уменьшили потребление памяти, и она к тому же будет выделяется по мере необходимости, а не вся сразу.
Так ведь нет же.
Если считать, что max_wal_size - это объем данных, который должен быть записан между контрольными точками (что само по себе не верно), то объем данных в первом случае будет 10GB, а во втором - 2GB.
А если смотреть на необходимую скорость записи, то (считая для простоты, что контрольные точки выполняются раз в 10 минут) в первом случае надо писать со скоростью 10GB/min, а во втором - 0.4GB/min. Вот вы и создали пик на пустом месте.
Кстати, с 14-й версии значение по умолчанию 0.9, и это неспроста.
Вам уже советовали RTFM в первой статье, ну ещё раз посоветую — почитайте про контрольные точки, чтобы не писать такое:
А совет выставить checkpoint_completion_target в 0.1 не приведет ни к чему, кроме пиковых нагрузок на ввод-вывод.
Чему ж вы людей-то учите?
Этот объем памяти может при необходимости выделяться каждому узлу плана. (Не говоря уже о том, что в некоторых случаях и это ограничение не учитывается.) Поэтому умножать примерно бесполезно.
Или каждый второй день?
Сильно сомневаюсь. Хотя бы потому, что производительность — это объем работы в единицу времени, а стоимость — это оценка общего объема работы. А во-вторых, оценка может слабо коррелировать с реальностью, это характеристики из двух разных вселенных.
Увы, увы. Микросервисы да паттерны.
СУБД — фундамент любой системы, поэтому: Владимир Комаров, «Путеводитель по базам данных»
В этом примере обновление отработало верно, но запрос SELECT, который выполнялся долго (для демонстрации эффекта в него вставлен pg_sleep), увидел разные состояния таблицы: одна строка - до обновления, вторая - уже после.
Там ничего таинственного, эти операторы сравнивают строки посимвольно, без учета правил сортировки (collation). В доке их, действительно, почему-то нет. Они входят в классы операторов *_pattern_ops, про которые мимоходом сказано в https://postgrespro.ru/docs/postgresql/16/indexes-opclass#INDEXES-OPCLASS. Видимо, считается, что этого и достаточно.
Caps Lock бы починить бы.
Протестую, ваша честь! Можно и без ptrack, в режимах page или delta.
Да, примерно так, но это уже гомеопатия — без тестирования в реальных условиях не поймёшь, что окажется эффективнее.
Есть ещё рекомендательные блокировки, это совсем быстро, но с ними надо аккуратно.