PostgreSQL рдореЗрдВ рд▓реЙрдХ рдЗрддрд┐рд╣рд╛рд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛

рд▓реЗрдЦ рдХреА рдирд┐рд░рдВрддрд░рддрд╛ " PostgreSQL рдХреЗ рд▓рд┐рдП ASH рдХрд╛ рдПрдХ рдПрдирд╛рд▓реЙрдЧ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИ "ред

рд▓реЗрдЦ рдХреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рд╢реНрдиреЛрдВ рдФрд░ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдФрд░ рджрд┐рдЦрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ - pg_locks рджреГрд╢реНрдп рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреНрдпрд╛ рдЙрдкрдпреЛрдЧреА рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред
рдЪреЗрддрд╛рд╡рдиреАред
рд╡рд┐рд╖рдп рдХреА рдирд╡реАрдирддрд╛ рдФрд░ рдЕрдкреВрд░реНрдг рдкрд░реАрдХреНрд╖рдг рдЕрд╡рдзрд┐ рдХреЗ рдХрд╛рд░рдг, рд▓реЗрдЦ рдореЗрдВ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реЛ рд╕рдХрддреА рд╣реИрдВред рдЖрд▓реЛрдЪрдирд╛ рдФрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЛ рджреГрдврд╝рддрд╛ рд╕реЗ рдкреНрд░реЛрддреНрд╕рд╛рд╣рд┐рдд рдФрд░ рдЙрдореНрдореАрдж рдХреА рдЬрд╛рддреА рд╣реИред

рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛


Pg_locks рдкреНрд░рд╕реНрддреБрдд рдЗрддрд┐рд╣рд╛рд╕


archive_locking
CREATE TABLE archive_locking ( timepoint timestamp without time zone , locktype text , relation oid , mode text , tid xid , vtid text , pid integer , blocking_pids integer[] , granted boolean , queryid bigint ); 

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рддрд╛рд▓рд┐рдХрд╛ рдпрд╣рд╛рдВ рдЕрдзрд┐рдХ рд╡рд┐рд╡рд░рдг рдореЗрдВ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд┐рдП рдЧрдП рд╕рдВрдЧреНрд░рд╣_рд╕реНрдХреНрд░рд┐рдкреНрдЯ_рд╕реНрдЯреИрдЯ_рдПрдХреНрдЯрд┐рд╡рд┐рдЯреА рдЯреЗрдмрд▓ рдХреЗ рд╕рдорд╛рди рд╣реИ - pg_stat_statements + pg_stat_activity + loq_query = pg_ash? рдФрд░ рдпрд╣рд╛рдБ - PostgreSQL рдХреЗ рд▓рд┐рдП ASH рдХрд╛ рдПрдХ рдПрдирд╛рд▓реЙрдЧ рдмрдирд╛рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ред

рдХреНрд╡реЗрд░реА рдХреЙрд▓рдо рднрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ

update_history_locking_by_queryid
 --update_history_locking_by_queryid.sql CREATE OR REPLACE FUNCTION update_history_locking_by_queryid() RETURNS boolean AS $$ DECLARE result boolean ; current_minute double precision ; start_minute integer ; finish_minute integer ; start_period timestamp without time zone ; finish_period timestamp without time zone ; lock_rec record ; endpoint_rec record ; current_hour_diff double precision ; BEGIN RAISE NOTICE '***update_history_locking_by_queryid'; result = TRUE ; current_minute = extract ( minute from now() ); SELECT * FROM endpoint WHERE is_need_monitoring INTO endpoint_rec ; current_hour_diff = endpoint_rec.hour_diff ; IF current_minute < 5 THEN RAISE NOTICE 'Current time is less than 5 minute.'; start_period = date_trunc('hour',now()) + (current_hour_diff * interval '1 hour'); finish_period = start_period - interval '5 minute' ; ELSE finish_minute = extract ( minute from now() ) / 5 ; start_minute = finish_minute - 1 ; start_period = date_trunc('hour',now()) + interval '1 minute'*start_minute*5+(current_hour_diff * interval '1 hour'); finish_period = date_trunc('hour',now()) + interval '1 minute'*finish_minute*5+(current_hour_diff * interval '1 hour') ; END IF ; RAISE NOTICE 'start_period = %', start_period; RAISE NOTICE 'finish_period = %', finish_period; FOR lock_rec IN WITH act_queryid AS ( SELECT pid , timepoint , query_start AS started , MAX(timepoint) OVER (PARTITION BY pid , query_start ) AS finished , queryid FROM activity_hist.history_pg_stat_activity WHERE timepoint BETWEEN start_period and finish_period GROUP BY pid , timepoint , query_start , queryid ), lock_pids AS ( SELECT hl.pid , hl.locktype , hl.mode , hl.timepoint , MIN ( timepoint ) OVER (PARTITION BY pid , locktype ,mode ) as started FROM activity_hist.history_locking hl WHERE hl.timepoint between start_period and finish_period GROUP BY hl.pid , hl.locktype , hl.mode , hl.timepoint ) SELECT lp.pid , lp.locktype , lp.mode , lp.timepoint , aq.queryid FROM lock_pids lp LEFT OUTER JOIN act_queryid aq ON ( lp.pid = aq.pid AND lp.started BETWEEN aq.started AND aq.finished ) WHERE aq.queryid IS NOT NULL GROUP BY lp.pid , lp.locktype , lp.mode , lp.timepoint , aq.queryid LOOP UPDATE activity_hist.history_locking SET queryid = lock_rec.queryid WHERE pid = lock_rec.pid AND locktype = lock_rec.locktype AND mode = lock_rec.mode AND timepoint = lock_rec.timepoint ; END LOOP; RETURN result ; END $$ LANGUAGE plpgsql; 

рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг: рдХреНрд╡реЗрд░реА рдХреЙрд▓рдо рдХрд╛ рдорд╛рди History_locking рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдЕрджреНрдпрддрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЬрдм рдЖрд░реНрдХрд╛рдЗрд╡_locking рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рдЕрдиреБрднрд╛рдЧ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рдореВрд▓реНрдп рдРрддрд┐рд╣рд╛рд╕рд┐рдХ рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛ред

рдЙрддреНрдкрд╛рджрди


рдПрдХ рдкреВрд░реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдкрд░ рд╕рд╛рдорд╛рдиреНрдп рдЬрд╛рдирдХрд╛рд░реАред

LOCKTYPES рджреНрд╡рд╛рд░рд╛ LOCKS рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХреНрд╖рд╛ рдХреА рдЬрд╛ рд░рд╣реА рд╣реИ


рдЬрд╛рдВрдЪ
 WITH t AS ( SELECT locktype , mode , count(*) as total FROM activity_hist.archive_locking WHERE timepoint between pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND NOT granted GROUP BY locktype , mode ) SELECT locktype , mode , total * interval '1 second' as duration FROM t ORDER BY 3 DESC 

рдЙрджрд╛рд╣рд░рдг
  |  LOCKTYPES рджреНрд╡рд╛рд░рд╛ LOCKS рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХреНрд╖рд╛ рдХреА рдЬрд╛ рд░рд╣реА рд╣реИ
 + -------------------- + ---------------------------- - + --------------------
 |  рд▓реЙрдХрдЯрд╛рдЗрдк |  рдореЛрдб |  рдЕрд╡рдзрд┐
 + -------------------- + ---------------------------- - + --------------------
 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  19:39:26
 |  рдЯрдкрд▓ |  AccessExclusiveLock |  00:03:35
 + -------------------- + ---------------------------- - + --------------------

LOCKTYPES рджреНрд╡рд╛рд░рд╛ рд▓реЛрдХреЛрдВ рдХрд╛ рдзреНрдпрд╛рди рд░рдЦрдирд╛


рдЬрд╛рдВрдЪ
 WITH t AS ( SELECT locktype , mode , count(*) as total FROM activity_hist.archive_locking WHERE timepoint between pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND granted GROUP BY locktype , mode ) SELECT locktype , mode , total * interval '1 second' as duration FROM t ORDER BY 3 DESC 

рдЙрджрд╛рд╣рд░рдг
  |  LOCKTYPES рджреНрд╡рд╛рд░рд╛ рд▓реЛрдХреЛрдВ рдХрд╛ рдзреНрдпрд╛рди рд░рдЦрдирд╛
 + -------------------- + ---------------------------- - + --------------------
 |  рд▓реЙрдХрдЯрд╛рдЗрдк |  рдореЛрдб |  рдЕрд╡рдзрд┐
 + -------------------- + ---------------------------- - + --------------------
 |  рд░рд┐рд╢реНрддрд╛ |  RowExclusiveLock |  51:11:10
 |  virtualxid |  ExclusiveLock |  48:10:43
 |  рд▓реЗрди-рджреЗрди |  ExclusiveLock |  44:24:53
 |  рд░рд┐рд╢реНрддрд╛ |  AccessShareLock |  20:06:13
 |  рдЯрдкрд▓ |  AccessExclusiveLock |  17:58:47
 |  рдЯрдкрд▓ |  ExclusiveLock |  01:40:41
 |  рд░рд┐рд╢реНрддрд╛ |  ShareUpdateExclusiveLock |  00:26:41
 |  рд╡рд╕реНрддреБ |  RowExclusiveLock |  00:00:01
 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  00:00:01
 |  рд╡рд┐рд╕реНрддрд╛рд░ |  ExclusiveLock |  00:00:01
 + -------------------- + ---------------------------- - + --------------------

рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреНрд╡реЗрд░реА рдкреНрд░рд╢реНрдиреЛрдВ рдкрд░ рд╡рд┐рд╕реНрддреГрдд рдЬрд╛рдирдХрд╛рд░реА

QUERYID рджреНрд╡рд╛рд░рд╛ LOCKTYPES рджреНрд╡рд╛рд░рд╛ рд▓реЛрдХреЗрдХреНрд╕ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдирд╛


рдЬрд╛рдВрдЪ
 WITH lt AS ( SELECT pid , locktype , mode , timepoint , queryid , blocking_pids , MIN ( timepoint ) OVER (PARTITION BY pid , locktype ,mode ) as started FROM activity_hist.archive_locking WHERE timepoint between pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND NOT granted AND queryid IS NOT NULL GROUP BY pid , locktype , mode , timepoint , queryid , blocking_pids ) SELECT lt.pid , lt.locktype , lt.mode , lt.started , lt.queryid , lt.blocking_pids , COUNT(*) * interval '1 second' as duration FROM lt GROUP BY lt.pid , lt.locktype , lt.mode , lt.started , lt.queryid , lt.blocking_pids ORDER BY 4 

рдЙрджрд╛рд╣рд░рдг
  |  QUERYID рджреНрд╡рд╛рд░рд╛ LOCKTYPES рджреНрд╡рд╛рд░рд╛ рд▓реЛрдХреЗрдХреНрд╕ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдирд╛
 + ---------- + ------------------------- + ------------ -------- + ------------------------------ + ---------- ---------- + -------------------- + ------------------ -
 |  рдкрд┐рдб |  рд▓реЙрдХрдЯрд╛рдЗрдк |  рдореЛрдб |  рд╢реБрд░реВ рдХрд┐рдпрд╛ |  рдХреНрд╡реЗрд░реА |  block_pids |  рдЕрд╡рдзрд┐
 + ---------- + ------------------------- + ------------ -------- + ------------------------------ + ---------- ---------- + -------------------- + ------------------ -
 |  11288 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 00: 00.302936 |  389015618226997618 |  {11092} |  00:03:34
 |  11626 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 00: 21.380921 |  389015618226997618 |  {12380} |  00:00:29
 |  11626 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 00: 21.380921 |  389015618226997618 |  {11092} |  00:03:25
 |  11626 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 00: 21.380921 |  389015618226997618 |  {12213} |  00:01:55
 |  11626 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 00: 21.380921 |  389015618226997618 |  {12751} |  00:00:01
 |  11629 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 00: 24.331935 |  389015618226997618 |  {11092} |  00:03:22
 |  11629 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 00: 24.331935 |  389015618226997618 |  {12007} |  00:00:01
 |  12007 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 05: 03.327933 |  389015618226997618 |  {11629} |  00:00:13
 |  12007 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 05: 03.327933 |  389015618226997618 |  {11092} |  00:01:10
 |  12007 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 05: 03.327933 |  389015618226997618 |  {11288} |  00:00:05
 |  12213 |  рд▓реЗрди-рджреЗрди |  рд╢реЗрдпрд░реЙрдХ |  2019-09-17 10: 06: 07.328019 |  389015618226997618 |  {12007} |  00:00:10 

QUERYID рджреНрд╡рд╛рд░рд╛ LOCKTYPES рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛


рдЬрд╛рдВрдЪ
 WITH lt AS ( SELECT pid , locktype , mode , timepoint , queryid , blocking_pids , MIN ( timepoint ) OVER (PARTITION BY pid , locktype ,mode ) as started FROM activity_hist.archive_locking WHERE timepoint between pg_stat_history_begin+(current_hour_diff * interval '1 hour') AND pg_stat_history_end+(current_hour_diff * interval '1 hour') AND granted AND queryid IS NOT NULL GROUP BY pid , locktype , mode , timepoint , queryid , blocking_pids ) SELECT lt.pid , lt.locktype , lt.mode , lt.started , lt.queryid , lt.blocking_pids , COUNT(*) * interval '1 second' as duration FROM lt GROUP BY lt.pid , lt.locktype , lt.mode , lt.started , lt.queryid , lt.blocking_pids ORDER BY 4 

рдЙрджрд╛рд╣рд░рдг
  |  QUERYID рджреНрд╡рд╛рд░рд╛ LOCKTYPES рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛
 + ---------- + ------------------------- + ------------ -------- + ------------------------------ + ---------- ---------- + -------------------- + ------------------ -
 |  рдкрд┐рдб |  рд▓реЙрдХрдЯрд╛рдЗрдк |  рдореЛрдб |  рд╢реБрд░реВ рдХрд┐рдпрд╛ |  рдХреНрд╡реЗрд░реА |  block_pids |  рдЕрд╡рдзрд┐
 + ---------- + ------------------------- + ------------ -------- + ------------------------------ + ---------- ---------- + -------------------- + ------------------ -
 |  11288 |  рд░рд┐рд╢реНрддрд╛ |  RowExclusiveLock |  2019-09-17 10: 00: 00.302936 |  389015618226997618 |  {11092} |  00:03:34
 |  11092 |  рд▓реЗрди-рджреЗрди |  ExclusiveLock |  2019-09-17 10: 00: 00.302936 |  389015618226997618 |  {} |  00:03:34
 |  11288 |  рд░рд┐рд╢реНрддрд╛ |  RowExclusiveLock |  2019-09-17 10: 00: 00.302936 |  389015618226997618 |  {} |  00:00:10
 |  11092 |  рд░рд┐рд╢реНрддрд╛ |  RowExclusiveLock |  2019-09-17 10: 00: 00.302936 |  389015618226997618 |  {} |  00:03:34
 |  11092 |  virtualxid |  ExclusiveLock |  2019-09-17 10: 00: 00.302936 |  389015618226997618 |  {} |  00:03:34
 |  11288 |  virtualxid |  ExclusiveLock |  2019-09-17 10: 00: 00.302936 |  389015618226997618 |  {11092} |  00:03:34
 |  11288 |  рд▓реЗрди-рджреЗрди |  ExclusiveLock |  2019-09-17 10: 00: 00.302936 |  389015618226997618 |  {11092} |  00:03:34
 |  11288 |  рдЯрдкрд▓ |  AccessExclusiveLock |  2019-09-17 10: 00: 00.302936 |  389015618226997618 |  {11092} |  00:03:34 

рдкреНрд░рджрд░реНрд╢рди рдХреА рдШрдЯрдирд╛рдУрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддреЗ рд╕рдордп рд▓реЙрдХ рдЗрддрд┐рд╣рд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ред

  1. рдХреНрд╡рд┐рдб рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдиреБрд░реЛрдз = 389015618226997618, рдЬрд┐рд╕реЗ рдкреАрдЖрдИрдбреА тАЛтАЛ= 11288 рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рджреНрд╡рд╛рд░рд╛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛, 2019-09-17 10:00:00 рд╕реЗ 3 рдорд┐рдирдЯ рдХреЗ рд▓рд┐рдП рдЕрд╡рд░реБрджреНрдз рд╣реЛрдиреЗ рдХреА рдЙрдореНрдореАрдж рд╣реИред
  2. рд▓реЙрдХ рдХреЛ рдкреАрдЖрдИрдбреА тАЛтАЛ= 11092 рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рджреНрд╡рд╛рд░рд╛ рдЖрдпреЛрдЬрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛
  3. Pid рдХреЗ рд╕рд╛рде рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ = 11092 рдкрд░ рдХреНрд╡реЗрд░реА рдХреЗ рд╕рд╛рде рдПрдХ рдХреНрд╡реЗрд░реА рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдирд╛ = 389015618226997618 2019-09-17 рд╕реЗ рд╢реБрд░реВ 10:00:00 3 рдорд┐рдирдЯ рдХреЗ рд▓рд┐рдП рд▓реЙрдХ рдХрд╛ рдЖрдпреЛрдЬрди рдХрд┐рдпрд╛ред

рдкрд░рд┐рдгрд╛рдо


рдЕрдм, рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ, рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рдФрд░ рдЙрдкрдпреЛрдЧреА рдмрд╛рдд рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ - рдЖрдВрдХрдбрд╝реЛрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдирд╛ рдФрд░ рдЙрдореНрдореАрджреЛрдВ рдФрд░ рддрд╛рд▓реЗ рдХреЗ рдЗрддрд┐рд╣рд╛рд╕ рдкрд░ рдорд╛рдорд▓реЛрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдирд╛ред

рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рдореИрдВ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рдпрд╣ рдХрд┐рд╕реА рддрд░рд╣ рдХреЗ рдиреЛрдЯ (рдУрд░реЗрдХрд▓ рдореЗрдЯрд▓рд┐рдВрдХ рдХреЗ рд╕рдорд╛рди) рдХрд╛ рдПрдХ рд╕реЗрдЯ рдмрди рдЬрд╛рдПрдЧрд╛ред

рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдпрд╣ рдЗрд╕ рдХрд╛рд░рдг рд╕реЗ рд╣реИ рдХрд┐ рдЬрд┐рд╕ рддрдХрдиреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рд╡рд╣ рд╕рд╛рдорд╛рдиреНрдп рдкрд░рд┐рдЪрд┐рдд рдХреЗ рд▓рд┐рдП рдЬрд┐рддрдиреА рдЬрд▓реНрджреА рд╣реЛ рд╕рдХреЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдирд┐рдХрдЯ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдореИрдВ рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдЬреАрдердм рдкрд░ рд░рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред

Source: https://habr.com/ru/post/hi467719/


All Articles