PostgreSQL се предлага с множество опции за конфигурация, но промяната на настройките по подразбиране на някои от тези опции драстично подобрява видимостта на вашия PostgreSQL сървър. Ще искате да зададете и конфигурирате тези опции, преди да възникнат проблеми в производството, тъй като те могат да предоставят необходима информация за разбирането и разрешаването на тези проблеми.
Прочетете, за да научите повече за настройките и разширенията, които разкриват показатели и информация за вътрешната работа на вашия PostgreSQL сървър.
Префикс на регистрационния ред
log_line_prefix опцията за конфигурация определя какво пише PostgreSQL в началото на всеки ред на дневника. По подразбиране зависи от конкретната дистрибуция на Linux или управлявано решение, което използвате, но по-често то не включва няколко елемента, които могат да се окажат много полезни при проследяване на клиенти с лошо поведение. Опитайте този log_line_prefix :
log_line_prefix = '%m [%p] %a %u %d %h '
Включва времевата марка (%m ), PID на задния процес (%p ), името на приложението (%a ) на клиента, потребителското име, с което клиентът се е свързал (%u ), базата данни, към която клиентът се е свързал (%d ) и името на хоста или IP, откъдето идва връзката (%h ). Това води до логлайни като този:
2021-01-30 05:06:03.675 UTC [73] psql postgres bench 172.17.0.1 ERROR: relation "pgbench_akkounts" does not exist at character 15
2021-01-30 05:06:03.675 UTC [73] psql postgres bench 172.17.0.1 STATEMENT: select * from pgbench_akkounts;
които са много по-полезни от стандартните. Можете да видите, че клиент се свързва от 172.17.0.1 като потребител postgres към бенч на базата данни , а приложението беше psql . Определено подобрение спрямо опцията по подразбиране, която показва само това:
2021-01-30 05:13:22.630 UTC [63] ERROR: relation "pgbench_akkounts" does not exist at character 15
2021-01-30 05:13:22.630 UTC [63] STATEMENT: select * from pgbench_akkounts;
Регистриране на бавни заявки
PostgreSQL може да бъде конфигуриран да регистрира заявки, които отнемат повече от определено време за изпълнение. Те влизат в същия регистрационен файл; няма отделен регистрационен файл с бавни заявки, както в MySQL.
За да регистрирате изрази, чието изпълнение отнема повече от 1 секунда, използвайте log_min_duration_statement опция като тази:
log_min_duration_statement = 1s
Имайте предвид, че log_min_duration_statement ще разгледа всички изрази (включително например дългосрочни администраторски изрази като REINDEX TABLE ), а не само заявки (SELECT ). Ето някои записи в дневника, създадени от тази опция:
2021-01-30 08:42:57.473 UTC [62] psql postgres postgres 172.17.0.1 LOG: duration: 1016.283 ms statement: select pg_sleep(1);
2021-01-30 08:52:00.541 UTC [62] psql postgres postgres 172.17.0.1 LOG: duration: 1118.277 ms statement: select pg_sleep(1.1);
Ако това доведе до твърде много регистрационни файлове с подобни изрази, можете да кажете на Postgres tolog само процент от него, като използвате:
log_min_duration_statement = -1
log_min_duration_sample = 1s
log_statement_sample_rate = 0.25
Това регистрира само 25% от изявленията, които отговарят на условията за регистриране (изпълнението на които е отнело повече от 1 секунда). Резултатът от журнала е същият като преди. Няма начин да разберете колко отговарящи на условията изявления не са били регистрирани.
За да регистрирате всички изрази, заедно с времето, необходимо за тяхното изпълнение, използвайтеlog_statement опция вместо това:
log_statement = mod
log_duration = on
Опцията „mod“ казва на Postgres да регистрира DDL и оператори за модифициране на данни. Това води до регистрационни файлове като тези:
2021-01-30 08:35:08.985 UTC [64] pgbench postgres bench 172.17.0.1 LOG: statement: insert into pgbench_tellers(tid,bid,tbalance) values (10,1,0)
2021-01-30 08:35:08.985 UTC [64] pgbench postgres bench 172.17.0.1 LOG: duration: 0.241 ms
Бъдете предупредени, че не Възможно е да се направи пробно регистриране на отчети, активирано по този начин, всички изрази ще бъдат регистрирани и в крайна сметка ще получите много записи в регистрационния файл.
Регистриране на заключвания и блокирания
Заявките могат да чакат твърде дълго, за да придобият заключване. Обикновено се задава горна граница на времето за чакане с помощта на опцията lock_timeout , обикновено от страна на клиента. Ако заявка е чакала толкова дълго, за да получи заключване, Postgres ще отмени изпълнението на тази заявка и ще регистрира грешка:
2021-01-30 09:35:52.415 UTC [67] psql postgres testdb 172.17.0.1 ERROR: canceling statement due to lock timeout
2021-01-30 09:35:52.415 UTC [67] psql postgres testdb 172.17.0.1 STATEMENT: cluster t;
Да приемем, че искате да зададете време за изчакване на заключване от 1 минута, но регистрирайте заявки, които чакат заключване за повече от, да речем, 30 секунди. Можете да направите това с помощта на:
log_lock_waits = on
deadlock_timeout = 30s
Това ще създаде логове като този:
2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 LOG: process 70 still waiting for ShareLock on transaction 493 after 30009.004 ms
2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 DETAIL: Process holding the lock: 68. Wait queue: 70.
2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 CONTEXT: while locking tuple (0,3) in relation "t"
2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 STATEMENT: select * from t for update;
Използването на deadlock_timeout не е печатна грешка:това е стойността, която използва механизмът за изчакване на заключване. В идеалния случай трябваше да има нещо като log_min_duration_lock_wait ,но за съжаление това не е така.
В случай на действителни блокирания, Postgres ще прекъсне блокираните транзакции след deadlock_timeout продължителност и ще регистрира обидните изявления. Не е необходима изрична конфигурация.
2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 LOG: process 68 detected deadlock while waiting for ShareLock on transaction 496 after 30007.633 ms
2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 DETAIL: Process holding the lock: 70. Wait queue: .
2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 CONTEXT: while locking tuple (0,3) in relation "t"
2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 STATEMENT: select * from t where a=4 for update;
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 ERROR: deadlock detected
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 DETAIL: Process 68 waits for ShareLock on transaction 496; blocked by process 70.
Process 70 waits for ShareLock on transaction 495; blocked by process 68.
Process 68: select * from t where a=4 for update;
Process 70: select * from t where a=0 for update;
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 HINT: See server log for query details.
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 CONTEXT: while locking tuple (0,3) in relation "t"
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 STATEMENT: select * from t where a=4 for update;
Регистриране на автоматично вакуумиране
Процесът на автоматично вакуумиране започва, когато Postgres определи, че данните в таблицата са се променили достатъчно, за да гарантират вакуум и анализ. За да следите този процес, активирайте записването на автоматично вакуумиране:
log_autovacuum_min_duration = 250ms
Ето примерен запис, причинен от прекомерни промени в една таблица:
2021-01-30 10:23:33.201 UTC [63] LOG: automatic vacuum of table "postgres.public.t": index scans: 0
pages: 0 removed, 95 remain, 0 skipped due to pins, 0 skipped frozen
tuples: 8991 removed, 10000 remain, 0 are dead but not yet removable, oldest xmin: 492
buffer usage: 215 hits, 4 misses, 4 dirtied
avg read rate: 1.885 MB/s, avg write rate: 1.885 MB/s
system usage: CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s
WAL usage: 244 records, 1 full page images, 67984 bytes
2021-01-30 10:23:33.222 UTC [63] LOG: automatic analyze of table "postgres.public.t" system usage: CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s
Имайте предвид, че автоматичното вакуумиране обикновено задейства анализ след вакуумирането и това също ще бъде регистрирано.
Тези регистрационни файлове ще ви помогнат да разберете как най-добре да настроите параметрите за автоматично вакуумиране и ще ви помогнат да проучите дали и кога автовакуумът не е толкова ефективен, колкото си мислехте, че ще бъде.
Пропускателни пунктове за регистриране
Контролните точки е процесът на избутване на регистрираните от WAL промени в действителните файлове, които обратно таблиците. В идеалния случай контролните точки трябва да се появяват на редовни и не твърде чести интервали, тъй като това е процес с интензивен процесор и диск. По различни причини контролните точки също са принудени да се случат преди следващия насрочен час и това води до намалена производителност на заявката.
За да следите честотата и ефективността на контролните точки, активирайте регистрирането на контролните точки:
log_checkpoints = on
Това казва на PostgreSQL да регистрира следното всеки път, когато възникне контролна точка:
2021-01-30 10:05:57.085 UTC [56] LOG: checkpoint starting: immediate force wait
2021-01-30 10:05:57.159 UTC [56] LOG: checkpoint complete: wrote 0 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.000 s, sync=0.000 s, total=0.074 s; sync files=0, longest=0.000 s, average=0.000 s; distance=0 kB, estimate=0 kB
Първият ред съдържа флаговете, които бекендът е предал на контролния указател. Можете да видите, че „силата“ е причинила контролна точка, въпреки че няма предстоящи промени в контролната точка. Ако „незабавен“ не беше посочен, контролната точка щеше да е контролна точка до checkpoint_completion_target .
Други настройки от страна на сървъра
Има няколко други настройки, които можете да включите във вашата PostgreSQL конфигурация, които ще помогнат при диагностицирането на проблеми:
- track_io_timing - задаване на включено ви позволява да видите времето, прекарано в дисков вход/изход за всяка заявка (в комбинация с разширението pg_stat_statements, описано по-долу). Вижте документацията за предупреждение за включване на това, но трябва да бъде безопасно в почти всеки модерен Linux. Виждането на цената на входно/изходния диск на заявката е невъзможно, без да го включите.
- track_commit_timestamp - задаване на включено може да бъде полезен при отстраняване на грешки при забавяне на репликацията и други проблеми, свързани с репликацията.
Статистически данни за заявките чрез pg_stat_statements
Разширението pg_stat_statements е основен аксесоар за всяко разгръщане на PostgreSQL. Той събира и записва статистически данни за всяка изпълнена заявка и ги представя като изглед, наречен „pg_stat_statements“. Това е разширение, което означава, че трябва да го инсталирате изрично във всяка база данни, за която искате данни, като използвате командата:
CREATE EXTENSION pg_stat_statements;
Тъй като разширението разчита на .so , ще трябва да го заредите чрезshared_preload_libraries :
shared_preload_libraries = 'pg_stat_statements'
Това за съжаление изисква рестартиране на PostgreSQL сървъра; така че не забравяйте да направите това, преди да пуснете на живо.
Ако сте надстроили от предишна версия на PostgreSQL, не забравяйте да надстроите и вашето разширение pg_stat_statement, като използвате:
ALTER EXTENSION pg_stat_statements UPDATE;
Разширението pg_stat_statements не регистрира нищо, то се използва чрез запитване на изгледа със същото име. За повече подробности вижте официалната документация.
Планове за изпълнение на заявки чрез auto_explain
auto_explain е друго разширение, присъстващо в ядрото на PostgreSQL. Може да регистрира плановете за изпълнение на бавни заявки. Трябва само да се добави къмshared_preload_libraries , и не е необходимо да се инсталира като разширение. Освен това има няколко други опции, които обикновено трябва да бъдат зададени на стойности, които не са по подразбиране:
shared_preload_libraries = 'pg_stat_statements,auto_explain'
auto_explain.log_min_duration = 1s
auto_explain.log_analyze = on
auto_explain.log_buffers = on
auto_explain.log_triggers = on
auto_explain.log_timing = on
auto_explain.log_verbose = on
auto_explain.log_format = json
Горното регистрира плана за изпълнение за всяка заявка, която отнема повече от 1 секунда за завършване. Ето примерен изход:
2021-01-30 11:28:25.977 UTC [64] psql postgres postgres 172.17.0.1 LOG: duration: 1.305 ms plan:
{
"Query Text": "SELECT n.nspname as \"Schema\",\n c.relname as \"Name\",\n CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' TH
EN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'table' WHEN 'I' THEN 'index' END as \"Type\",\n pg_catalog.pg_get_userbyid(c.relowner) as \"Owner\"\nFROM pg_catalog.pg_class c
\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\nWHERE c.relkind IN ('r','p','v','m','S','f','')\n AND n.nspname <> 'pg_catalog'\n AND n.nspname <> 'information_schema'\n AND
n.nspname !~ '^pg_toast'\n AND pg_catalog.pg_table_is_visible(c.oid)\nORDER BY 1,2;",
"Plan": {
"Node Type": "Sort",
"Parallel Aware": false,
"Startup Cost": 32.93,
"Total Cost": 33.01,
"Plan Rows": 32,
"Plan Width": 224,
"Actual Startup Time": 1.292,
"Actual Total Time": 1.298,
"Actual Rows": 0,
[... lots of text snipped ...]
За да научите повече за auto_explain, вижте официалните документи.
Разширенията pg_stat_statements и auto_explain са единствените две широко поддържани опции, които PostgreSQL има за управление на производителността на заявките и управление на плана на заявките. Струва си да се запознаете с тези две функции и да планирате предварително да ги използвате в производството.
Име на приложението
Името на приложението е параметър от страна на клиента и обикновено може да бъде зададено в DSN или низове за връзка в стил libpq, които вашето приложение използва за информация за свързване. Много инструменти и помощни програми в PostgreSQL eco system разбират името на приложението и помага да зададете това на значима стойност, например:
application_name = weekly-revenue-report
Това ще бъде зададено за всяко клиентско приложение, което се свързва с вашия PostgreSQLserver.