ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ

ืึธื“ืขืจ ืึท ื‘ื™ืกืœ ืคื•ืŸ ื’ืขื•ื•ืขื ื“ื˜ ื˜ืขื˜ืจื™ืกืึธืœืึธื’ื™.
ืึทืœืฅ ื ื™ื™ึท ืื™ื– ื’ื•ื˜ ืคืืจื’ืขืกืŸ ืึทืœื˜.
ืขืคึผื™ื’ืจืึทืคืก.
ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ

ื•ื™ืกื–ืึธื’ื•ื ื’ ืคื•ืŸ ื“ื™ ืคึผืจืึธื‘ืœืขื

ืขืก ืื™ื– ื ื•ื™ื˜ื™ืง ืฆื• ืคึผืขืจื™ึดืึธื“ื™ืฉ ื“ืึทื•ื ืœืึธื•ื“ืŸ ื“ื™ ืื™ืฆื˜ื™ืงืข PostgreSQL ืœืึธื’ ื˜ืขืงืข ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ ืฆื• ื“ื™ ืœืึธืงืึทืœืข Linux ื‘ืึทืœืขื‘ืึธืก. ื ื™ืฉื˜ ืื™ืŸ ืคืึทืงื˜ื™ืฉืขืจ ืฆื™ื™ื˜, ื ืึธืจ, ื–ืึธื’ืŸ ืžื™ืจ, ืžื™ื˜ ืึท ืงืœื™ื™ื ืขืจ ืคืึทืจื”ืึทืœื˜ื•ื ื’.
ื“ื™ ืืจืืคืงืืคื™ืข ืฆื™ื™ึทื˜ ืคื•ืŸ ืงืœืึธืฅ ื˜ืขืงืข ื“ืขืจื”ื™ื™ึทื ื˜ื™ืงืŸ ืื™ื– 5 ืžื™ื ื•ื˜.
ื“ื™ ืงืœืึธืฅ ื˜ืขืงืข, ืื™ืŸ AWS, ืื™ื– ืจืึธื•ื˜ื™ื™ื˜ื™ื“ ื™ืขื“ืขืจ ืฉืขื”.

ื’ืขื•ื•ื™ื™ื ื˜ ืžื›ืฉื™ืจื™ื

ืฆื• ืฆื•ืคึฟืขืœื™ืงืขืจ ื“ื™ ืงืœืึธืฅ ื˜ืขืงืข ืฆื• ื“ืขืจ ื‘ืึทืœืขื‘ืึธืก, ืึท ื‘ืึทืฉ ืฉืจื™ืคื˜ ืื™ื– ื’ืขื ื™ืฆื˜ ื•ื•ืึธืก ืจื•ืคื˜ ื“ื™ AWS API "aws rds download-db-log-file-portion'.

ืคึผืึทืจืึทืžืขื˜ืขืจืก:

  • --db-instance-identifier: ื‘ื™ื™ึทืฉืคึผื™ืœ ื ืึธืžืขืŸ ืื™ืŸ AWS;
  • --ืœืึธื’-ื˜ืขืงืข-ื ืึธืžืขืŸ: ื ืึธืžืขืŸ ืคื•ืŸ ื“ื™ ืื™ืฆื˜ ื“ื–ืฉืขื ืขืจื™ื™ื˜ืึทื“ ืงืœืึธืฅ ื˜ืขืงืข
  • --max-item: ื“ื™ ื’ืึทื ืฅ ื ื•ืžืขืจ ืคื•ืŸ ื–ืื›ืŸ ืื•ืžื’ืขืงืขืจื˜ ืื™ืŸ ื“ืขืจ ืจืขื–ื•ืœื˜ืึทื˜ ืคื•ืŸ ื“ื™ ื‘ืึทืคึฟืขืœ.ื“ื™ ื’ืจื™ื™ืก ืคื•ืŸ ื“ื™ ื“ืึทื•ื ืœืึธื•ื“ื™ื“ ื˜ืขืงืข.
  • --ืกื˜ืึทืจื˜ื™ื ื’-ื˜ืึธืงืขืŸ: ืกื˜ืึทืจื˜ื™ื ื’ ื˜ืึธืงืขืŸ ืกื™ืžืขืŸ

ืื™ืŸ ื“ืขื ื‘ืึทื–ื•ื ื“ืขืจ ืคืึทืœ, ื“ื™ ืึทืจื‘ืขื˜ ืคื•ืŸ ื“ืึทื•ื ืœืึธื•ื“ื™ื ื’ ืœืึธื’ืก ืื™ื– ืื•ื™ืคื’ืขืฉื˜ืื ืขืŸ ืื™ืŸ ื“ื™ ืœื•ื™ืฃ ืคื•ืŸ ืึทืจื‘ืขื˜ ืคืึธืจืฉื˜ืขืœื•ื ื’ ืžืึธื ื™ื˜ืึธืจื™ื ื’ ืคื•ืŸ PostgreSQL ืงื•ื•ื™ืจื™ื–.

ื™ืึธ, ืื•ืŸ ืคืฉื•ื˜ - ืึท ื˜ืฉื™ืงืึทื•ื•ืข ืึทืจื‘ืขื˜ ืคึฟืึทืจ ื˜ืจื™ื™ื ื™ื ื’ ืื•ืŸ ืคืึทืจืฉื™ื™ื“ื ืงื™ื™ึทื˜ ื‘ืขืฉืึทืก ืึทืจื‘ืขื˜ ืฉืขื”.
ืื™ืš ื ืขื ืื– ื“ืขืจ ืคืจืื‘ืœืขื ืื™ื– ืฉื•ื™ืŸ ื’ืขืœื™ื™ื–ื˜ ื’ืขื•ื•ืืจืŸ ืžื›ื•ื— ืจื•ื˜ื™ืŸ. ืึธื‘ืขืจ ืึท ืฉื ืขืœ ื’ื•ื’ืœ ื”ืื˜ ื ื™ืฉื˜ ืคึฟืึธืจืฉืœืึธื’ืŸ ืกืึทืœื•ืฉืึทื ื–, ืื•ืŸ ืขืก ืื™ื– ืงื™ื™ืŸ ื‘ืึทื–ื•ื ื“ืขืจ ืคืึทืจืœืึทื ื’ ืฆื• ื–ื•ื›ืŸ ืื™ืŸ ืžืขืจ ื˜ื™ืฃ. ืื™ืŸ ืงื™ื™ืŸ ืคืึทืœ, ืขืก ืื™ื– ืึท ื’ื•ื˜ ื•ื•ืขืจืงืึทื•ื˜.

ืคืึธืจืžืึทืœื™ื–ื™ื™ืฉืึทืŸ ืคื•ืŸ ื“ื™ ืึทืจื‘ืขื˜

ื“ื™ ืœืขืฆื˜ ืงืœืึธืฅ ื˜ืขืงืข ืื™ื– ืึท ืกื›ื•ื ืคื•ืŸ ืฉื•ืจื•ืช ืคื•ืŸ ื‘ื™ื™ึทื˜ืขื•ื•ื“ื™ืง ืœืขื ื’. ื’ืจืึทืคื™ืงืœื™, ื“ื™ ืงืœืึธืฅ ื˜ืขืงืข ืงืขื ืขืŸ ื–ื™ื™ืŸ ืจืขืคึผืจื™ื–ืขื ื˜ื™ื“ ื•ื•ื™ ื“ืึธืก:
ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ

ืขืก ื“ืขืจืžืื ื˜ ื“ื™ืจ ืฉื•ื™ืŸ ืขืคืขืก? ื•ื•ืืก ืื™ื– ืžื™ื˜ "ื˜ืขื˜ืจื™ืก"? ืื•ืŸ ื“ืึธ ืก ื•ื•ืึธืก.
ืื•ื™ื‘ ืžื™ืจ ืคืึธืจืฉื˜ืขืœืŸ ื“ื™ ืžืขื’ืœืขืš ืึธืคึผืฆื™ืขืก ื•ื•ืึธืก ืฉื˜ื™ื™ืขืŸ ื•ื•ืขืŸ ืœืึธื•ื“ื™ื ื’ ื“ื™ ื•ื•ื™ื™ึทื˜ืขืจ ื˜ืขืงืข ื’ืจืึทืคื™ืงืœื™ (ืคึฟืึทืจ ืคึผืึทืฉื˜ืขืก, ืื™ืŸ ื“ืขื ืคืึทืœ, ืœืึธื–ืŸ ื“ื™ ืฉื•ืจื•ืช ื”ืึธื‘ืŸ ื“ื™ ื–ืขืœื‘ืข ืœืขื ื’), ืžื™ืจ ื‘ืึทืงื•ืžืขืŸ ื ืึธืจืžืึทืœ ื˜ืขื˜ืจื™ืก ืคื™ื’ื™ืขืจื–:

1) ื“ืขืจ ื˜ืขืงืข ืื™ื– ื“ืึทื•ื ืœืึธื•ื“ื™ื“ ืื™ืŸ ื–ื™ื™ืŸ ื™ื ื˜ื™ื™ืขืจืžืึทื ื˜ ืื•ืŸ ืื™ื– ืœืขืฆื˜. ื“ื™ ืคึผื™ื™ึทื“ืข ื’ืจื™ื™ืก ืื™ื– ื’ืจืขืกืขืจ ื•ื•ื™ ื“ื™ ืœืขืฆื˜ ื˜ืขืงืข ื’ืจื™ื™ืก:
ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ

2) ื“ืขืจ ื˜ืขืงืข ื”ืื˜ ืึท ืงืึทื ื˜ื™ื ื™ื•ื™ื™ืฉืึทืŸ. ื“ื™ ืคึผื™ื™ึทื“ืข ื’ืจื™ื™ืก ืื™ื– ืงืœืขื ืขืจืขืจ ื•ื•ื™ ื“ื™ ืœืขืฆื˜ ื˜ืขืงืข ื’ืจื™ื™ืก:
ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ

3) ื“ืขืจ ื˜ืขืงืข ืื™ื– ืึท ืงืึทื ื˜ื™ื ื™ื•ื™ื™ืฉืึทืŸ ืคื•ืŸ ื“ื™ ืคืจื™ืขืจื“ื™ืงืข ื˜ืขืงืข ืื•ืŸ ื”ืื˜ ืึท ืงืึทื ื˜ื™ื ื™ื•ื™ื™ืฉืึทืŸ. ื“ื™ ืคึผื™ื™ึทื“ืข ื’ืจื™ื™ืก ืื™ื– ื•ื•ื™ื™ื ื™ืงืขืจ ื•ื•ื™ ื“ื™ ื’ืจื™ื™ืก ืคื•ืŸ ื“ื™ ืจืขืฉื˜ ืคื•ืŸ ื“ื™ ืœืขืฆื˜ ื˜ืขืงืข:
ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ

4) ื“ื™ ื˜ืขืงืข ืื™ื– ืึท ืงืึทื ื˜ื™ื ื™ื•ื™ื™ืฉืึทืŸ ืคื•ืŸ ื“ื™ ืคืจื™ืขืจื“ื™ืงืข ื˜ืขืงืข ืื•ืŸ ืื™ื– ืœืขืฆื˜. ื“ื™ ืคึผื™ื™ึทื“ืข ื’ืจื™ื™ืก ืื™ื– ื’ืจืขืกืขืจ ื•ื•ื™ ื“ื™ ื’ืจื™ื™ืก ืคื•ืŸ ื“ื™ ืจืขืฉื˜ ืคื•ืŸ ื“ื™ ืœืขืฆื˜ ื˜ืขืงืข:
ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ

ื“ื™ ืึทืจื‘ืขื˜ ืื™ื– ืฆื• ืึทืกืขืžื‘ืึทืœ ืึท ื’ืจืึธื“ืขืง ืึธื“ืขืจ ืฉืคึผื™ืœืŸ ื˜ืขื˜ืจื™ืก ืื•ื™ืฃ ืึท ื ื™ื™ึทืข ืžื“ืจื’ื”.
ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ

ืคึผืจืึธื‘ืœืขืžืก ื•ื•ืึธืก ืฉื˜ื™ื™ืขืŸ ืื™ืŸ ื“ื™ ืœื•ื™ืฃ ืคื•ืŸ ืกืึทืœื•ื•ื™ื ื’ ื“ื™ ืคึผืจืึธื‘ืœืขื

1) ืงืœื™ื™ ืึท ืฉื˜ืจื™ืงืœ ืคื•ืŸ 2 ืคึผืึธืจืฉืึทื ื–

ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ
ืื™ืŸ ืึทืœื’ืขืžื™ื™ืŸ, ืขืก ื–ืขื ืขืŸ ืงื™ื™ืŸ ื‘ืึทื–ื•ื ื“ืขืจ ืคึผืจืึธื‘ืœืขืžืก. ื ื ืึธืจืžืึทืœ ืึทืจื‘ืขื˜ ืคื•ืŸ ื“ื™ ืขืจืฉื˜ ืคึผืจืึธื’ืจืึทืžืžื™ื ื’ ืงื•ืจืก.

ืึธืคึผื˜ื™ืžืึทืœ ืกืขืจื•ื•ื™ื ื’ ื’ืจื™ื™ืก

ืื‘ืขืจ ื“ืึธืก ืื™ื– ืึท ื‘ื™ืกืœ ืžืขืจ ื˜ืฉื™ืงืึทื•ื•ืข.
ืฆื•ื ื‘ืึทื“ื•ื™ืขืจืŸ, ืขืก ืื™ื– ืงื™ื™ืŸ ื•ื•ืขื’ ืฆื• ื ื•ืฆืŸ ืึท ืคืึธื˜ืึธ ื ืึธืš ื“ื™ ืึธื ื”ื™ื™ื‘ ื˜ืฉืึทื ื’ ืคื™ืจืžืข:

ื•ื•ื™ ืื™ืจ ืฉื•ื™ืŸ ื•ื•ื™ืกืŸ ื“ื™ ืึธืคึผืฆื™ืข ---starting-token ืื™ื– ื’ืขื ื™ืฆื˜ ืฆื• ืกืคึผืขืฆื™ืคื™ืฆื™ืจืŸ ื•ื•ื• ืฆื• ืึธื ื”ื™ื™ื‘ืŸ ืคึผืึทื“ื–ืฉืึทื ื™ื™ื˜ื™ื ื’. ื“ืขืจ ืึธืคึผืฆื™ืข ื ืขืžื˜ ืกื˜ืจื™ื ื’ ื•ื•ืึทืœื•ืขืก ื•ื•ืึธืก ื•ื•ืึธืœื˜ ืžื™ื™ื ืขืŸ ืึทื– ืื•ื™ื‘ ืื™ืจ ืคึผืจื•ื‘ื™ืจืŸ ืฆื• ืœื™ื™ื’ืŸ ืึท ืคืึธื˜ืึธ ื•ื•ืขืจื˜ ืื™ืŸ ืคืจืึธื ื˜ ืคื•ืŸ ื“ื™ ื•ื•ื™ื™ึทื˜ืขืจ ื˜ืึธืงืขืŸ ืฉื˜ืจื™ืงืœ, ื“ื™ ืึธืคึผืฆื™ืข ื•ื•ืขื˜ ื ื™ืฉื˜ ื–ื™ื™ืŸ ื‘ืึทื˜ืจืึทื›ื˜ ื•ื•ื™ ืึท ืคืึธื˜ืึธ.

ืื•ืŸ ืึทื–ื•ื™, ืื™ืจ ื”ืึธื‘ืŸ ืฆื• ืœื™ื™ืขื ืขืŸ ืื™ืŸ ืฉื˜ื™ืงืขืจ ืคึผืึธืจืฉืึทื ื–.
ืื•ื™ื‘ ืื™ืจ ืœื™ื™ืขื ืขืŸ ืื™ืŸ ื’ืจื•ื™ืก ืคึผืึธืจืฉืึทื ื–, ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืจื™ื“ื™ื ื’ื– ื•ื•ืขื˜ ื–ื™ื™ืŸ ืžื™ื ื™ืžืึทืœ, ืึธื‘ืขืจ ื“ืขืจ ื‘ืึทื ื“ ื•ื•ืขื˜ ื–ื™ื™ืŸ ืžืึทืงืกื™ืžื•ื.
ืื•ื™ื‘ ืื™ืจ ืœื™ื™ืขื ืขืŸ ืื™ืŸ ืงืœื™ื™ืŸ ืคึผืึธืจืฉืึทื ื–, ืื•ื™ืฃ ื“ื™ ืคืึทืจืงืขืจื˜, ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืจื™ื“ื™ื ื’ื– ื•ื•ืขื˜ ื–ื™ื™ืŸ ืžืึทืงืกื™ืžื•ื, ืึธื‘ืขืจ ื“ืขืจ ื‘ืึทื ื“ ื•ื•ืขื˜ ื–ื™ื™ืŸ ืžื™ื ื™ืžืึทืœ.
ื“ืขืจื™ื‘ืขืจ, ืื™ืŸ ืกื“ืจ ืฆื• ืจืขื“ื•ืฆื™ืจืŸ ืคืึทืจืงืขืจ ืื•ืŸ ืคึฟืึทืจ ื“ื™ ืงื•ื™ืœืขืœื“ื™ืง ืฉื™ื™ื ืงื™ื™ื˜ ืคื•ืŸ ื“ื™ ืœื™ื™ื–ื•ื ื’, ืื™ืš ื’ืขื”ืื˜ ืฆื• ืงื•ืžืขืŸ ืžื™ื˜ ืึท ืกืึธืจื˜ ืคื•ืŸ ืœื™ื™ื–ื•ื ื’, ื•ื•ืึธืก, ืœื™ื™ื“ืขืจ, ืงื•ืงื˜ ืึท ื‘ื™ืกืœ ื•ื•ื™ ืึท ืงืจืึทื˜ืฉ.

ืฆื• ืื™ืœื•ืกื˜ืจื™ืจืŸ, ืœืึธืžื™ืจ ื‘ืึทื˜ืจืึทื›ื˜ืŸ ื“ืขื ืคึผืจืึธืฆืขืก ืคื•ืŸ ื“ืึทื•ื ืœืึธื•ื“ื™ื ื’ ืึท ืงืœืึธืฅ ื˜ืขืงืข ืื™ืŸ 2 ื–ื™ื™ืขืจ ืกื™ืžืคึผืœืึทืคื™ื™ื“ ื•ื•ืขืจืกื™ืขืก. ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืจื™ื“ื™ื ื’ื– ืื™ืŸ ื‘ื™ื™ื“ืข ืงืึทืกืขืก ื“ืขืคึผืขื ื“ืก ืื•ื™ืฃ ื“ื™ ื—ืœืง ื’ืจื™ื™ืก.

1) ืžืึทืกืข ืื™ืŸ ืงืœื™ื™ืŸ ืคึผืึธืจืฉืึทื ื–:
ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ

2) ืžืึทืกืข ืื™ืŸ ื’ืจื•ื™ืก ืคึผืึธืจืฉืึทื ื–:
ื•ืคึผืœืึธืึทื“ื™ื ื’ ืึท PostgreSQL ืงืœืึธืฅ ืคึฟื•ืŸ ื“ื™ AWS ื•ื•ืึธืœืงืŸ

ื•ื•ื™ ื’ืขื•ื•ื™ื™ื ื˜ืœืขืš, ื“ื™ ืึธืคึผื˜ื™ืžืึทืœ ืœื™ื™ื–ื•ื ื’ ืื™ื– ืื™ืŸ ื“ื™ ืžื™ื˜ืœ.
ื“ืขืจ ื—ืœืง ื’ืจื™ื™ืก ืื™ื– ืžื™ื ื™ืžืึทืœ, ืึธื‘ืขืจ ืื™ืŸ ื“ืขื ืคึผืจืึธืฆืขืก ืคื•ืŸ ืœื™ื™ืขื ืขืŸ, ื“ื™ ื’ืจื™ื™ืก ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขื•ื•ืืงืกืŸ ืฆื• ืจืขื“ื•ืฆื™ืจืŸ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ืจื™ื“ื™ื ื’ื–.

ืขืก ื–ืึธืœ ื–ื™ื™ืŸ ืื ื’ืขื•ื•ื™ื–ืŸ ืึทื– ื“ื™ ืคึผืจืึธื‘ืœืขื ืคื•ืŸ ืกืขืœืขืงื˜ื™ื ื’ ื“ื™ ืึธืคึผื˜ื™ืžืึทืœ ื’ืจื™ื™ืก ืคื•ืŸ ื“ื™ ืœื™ื™ืขื ืขืŸ ื—ืœืง ืื™ื– ื ืึธืš ื ื™ืฉื˜ ื’ืึธืจ ืกืึทืœื•ื•ื“ ืื•ืŸ ืจื™ืงื•ื•ื™ื™ืขืจื– ื“ื™ืคึผืขืจ ืœืขืจื ืขืŸ ืื•ืŸ ืึทื ืึทืœื™ืกื™ืก. ืืคึฟืฉืจ ืึท ื‘ื™ืกืœ ืฉืคึผืขื˜ืขืจ.

ืึทืœื’ืขืžื™ื™ื ืข ื‘ืึทืฉืจื™ื™ึทื‘ื•ื ื’ ืคื•ืŸ ื“ื™ ื™ืžืคึผืœืึทืžืขื ื˜ื™ื™ืฉืึทืŸ

ื’ืขื•ื•ื™ื™ื ื˜ ื“ื™ื ืกื˜ ื˜ื™ืฉืŸ

CREATE TABLE endpoint
(
id SERIAL ,
host text 
);

TABLE database
(
id SERIAL , 
โ€ฆ
last_aws_log_time text ,
last_aws_nexttoken text ,
aws_max_item_size integer 
);
last_aws_log_time โ€” ะฒั€ะตะผะตะฝะฝะฐั ะผะตั‚ะบะฐ ะฟะพัะปะตะดะฝะตะณะพ ะทะฐะณั€ัƒะถะตะฝะฝะพะณะพ ะปะพะณ-ั„ะฐะนะปะฐ ะฒ ั„ะพั€ะผะฐั‚ะต YYYY-MM-DD-HH24.
last_aws_nexttoken โ€” ั‚ะตะบัั‚ะพะฒะฐั ะผะตั‚ะบะฐ ะฟะพัะปะตะดะฝะตะน ะทะฐะณั€ัƒะถะตะฝะฝะพะน ะฟะพั€ั†ะธะธ.
aws_max_item_size- ัะผะฟะธั€ะธั‡ะตัะบะธะผ ะฟัƒั‚ะตะผ, ะฟะพะดะพะฑั€ะฐะฝะฝั‹ะน ะฝะฐั‡ะฐะปัŒะฝั‹ะน ั€ะฐะทะผะตั€ ะฟะพั€ั†ะธะธ.

ื’ืึทื ืฅ ื˜ืขืงืกื˜ ืคื•ืŸ ื“ื™ ืฉืจื™ืคื˜

download_aws_piece.sh

#!/bin/bash
#########################################################
# download_aws_piece.sh
# downloan piece of log from AWS
# version HABR
 let min_item_size=1024
 let max_item_size=1048576
 let growth_factor=3
 let growth_counter=1
 let growth_counter_max=3

 echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh:''STARTED'
 
 AWS_LOG_TIME=$1
 echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh:AWS_LOG_TIME='$AWS_LOG_TIME
  
 database_id=$2
 echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh:database_id='$database_id
 RESULT_FILE=$3 
  
 endpoint=`psql -h MONITOR_ENDPOINT.rds.amazonaws.com -U USER -d MONITOR_DATABASE_DATABASE -A -t -c "select e.host from endpoint e join database d on e.id = d.endpoint_id where d.id = $database_id "`
 echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh:endpoint='$endpoint
  
 db_instance=`echo $endpoint | awk -F"." '{print toupper($1)}'`
 
 echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh:db_instance='$db_instance

 LOG_FILE=$RESULT_FILE'.tmp_log'
 TMP_FILE=$LOG_FILE'.tmp'
 TMP_MIDDLE=$LOG_FILE'.tmp_mid'  
 TMP_MIDDLE2=$LOG_FILE'.tmp_mid2'  
  
 current_aws_log_time=`psql -h MONITOR_ENDPOINT.rds.amazonaws.com -U USER -d MONITOR_DATABASE -A -t -c "select last_aws_log_time from database where id = $database_id "`

 echo $(date +%Y%m%d%H%M)':      download_aws_piece.sh:current_aws_log_time='$current_aws_log_time
  
  if [[ $current_aws_log_time != $AWS_LOG_TIME  ]];
  then
    is_new_log='1'
	if ! psql -h MONITOR_ENDPOINT.rds.amazonaws.com -U USER -d MONITOR_DATABASE -v ON_ERROR_STOP=1 -A -t -q -c "update database set last_aws_log_time = '$AWS_LOG_TIME' where id = $database_id "
	then
	  echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: FATAL_ERROR - update database set last_aws_log_time .'
	  exit 1
	fi
  else
    is_new_log='0'
  fi
  
  echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh:is_new_log='$is_new_log
  
  let last_aws_max_item_size=`psql -h MONITOR_ENDPOINT.rds.amazonaws.com -U USER -d MONITOR_DATABASE -A -t -c "select aws_max_item_size from database where id = $database_id "`
  echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: last_aws_max_item_size='$last_aws_max_item_size
  
  let count=1
  if [[ $is_new_log == '1' ]];
  then    
	echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: START DOWNLOADING OF NEW AWS LOG'
	if ! aws rds download-db-log-file-portion 
		--max-items $last_aws_max_item_size 
		--region REGION 
		--db-instance-identifier  $db_instance 
		--log-file-name error/postgresql.log.$AWS_LOG_TIME > $LOG_FILE
	then
		echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: FATAL_ERROR - Could not get log from AWS .'
		exit 2
	fi  	
  else
    next_token=`psql -h MONITOR_ENDPOINT.rds.amazonaws.com -U USER -d MONITOR_DATABASE -v ON_ERROR_STOP=1 -A -t -c "select last_aws_nexttoken from database where id = $database_id "`
	
	if [[ $next_token == '' ]];
	then
	  next_token='0'	  
	fi
	
	echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: CONTINUE DOWNLOADING OF AWS LOG'
	if ! aws rds download-db-log-file-portion 
	    --max-items $last_aws_max_item_size 
		--starting-token $next_token 
		--region REGION 
		--db-instance-identifier  $db_instance 
		--log-file-name error/postgresql.log.$AWS_LOG_TIME > $LOG_FILE
	then
		echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: FATAL_ERROR - Could not get log from AWS .'
		exit 3
	fi       
	
	line_count=`cat  $LOG_FILE | wc -l`
	let lines=$line_count-1
	  
	tail -$lines $LOG_FILE > $TMP_MIDDLE 
	mv -f $TMP_MIDDLE $LOG_FILE
  fi
  
  next_token_str=`cat $LOG_FILE | grep NEXTTOKEN` 
  next_token=`echo $next_token_str | awk -F" " '{ print $2}' `
  
  grep -v NEXTTOKEN $LOG_FILE  > $TMP_FILE 
  
  if [[ $next_token == '' ]];
  then
	  cp $TMP_FILE $RESULT_FILE
	  
	  echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh:  NEXTTOKEN NOT FOUND - FINISH '
	  rm $LOG_FILE 
	  rm $TMP_FILE
	  rm $TMP_MIDDLE
          rm $TMP_MIDDLE2	  
	  exit 0  
  else
	psql -h MONITOR_ENDPOINT.rds.amazonaws.com -U USER -d MONITOR_DATABASE -v ON_ERROR_STOP=1 -A -t -q -c "update database set last_aws_nexttoken = '$next_token' where id = $database_id "
  fi
  
  first_str=`tail -1 $TMP_FILE`
  
  line_count=`cat  $TMP_FILE | wc -l`
  let lines=$line_count-1    
  
  head -$lines $TMP_FILE  > $RESULT_FILE

###############################################
# MAIN CIRCLE
  let count=2
  while [[ $next_token != '' ]];
  do 
    echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: count='$count
	
	echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: START DOWNLOADING OF AWS LOG'
	if ! aws rds download-db-log-file-portion 
             --max-items $last_aws_max_item_size 
             --starting-token $next_token 
             --region REGION 
             --db-instance-identifier  $db_instance 
             --log-file-name error/postgresql.log.$AWS_LOG_TIME > $LOG_FILE
	then
		echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: FATAL_ERROR - Could not get log from AWS .'
		exit 4
	fi

	next_token_str=`cat $LOG_FILE | grep NEXTTOKEN` 
	next_token=`echo $next_token_str | awk -F" " '{ print $2}' `

	TMP_FILE=$LOG_FILE'.tmp'
	grep -v NEXTTOKEN $LOG_FILE  > $TMP_FILE  
	
	last_str=`head -1 $TMP_FILE`
  
    if [[ $next_token == '' ]];
	then
	  concat_str=$first_str$last_str
	  	  
	  echo $concat_str >> $RESULT_FILE
		 
	  line_count=`cat  $TMP_FILE | wc -l`
	  let lines=$line_count-1
	  
	  tail -$lines $TMP_FILE >> $RESULT_FILE
	  
	  echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh:  NEXTTOKEN NOT FOUND - FINISH '
	  rm $LOG_FILE 
	  rm $TMP_FILE
	  rm $TMP_MIDDLE
          rm $TMP_MIDDLE2	  
	  exit 0  
	fi
	
    if [[ $next_token != '' ]];
	then
		let growth_counter=$growth_counter+1
		if [[ $growth_counter -gt $growth_counter_max ]];
		then
			let last_aws_max_item_size=$last_aws_max_item_size*$growth_factor
			let growth_counter=1
		fi
	
		if [[ $last_aws_max_item_size -gt $max_item_size ]]; 
		then
			let last_aws_max_item_size=$max_item_size
		fi 

	  psql -h MONITOR_ENDPOINT.rds.amazonaws.com -U USER -d MONITOR_DATABASE -A -t -q -c "update database set last_aws_nexttoken = '$next_token' where id = $database_id "
	  
	  concat_str=$first_str$last_str
	  	  
	  echo $concat_str >> $RESULT_FILE
		 
	  line_count=`cat  $TMP_FILE | wc -l`
	  let lines=$line_count-1
	  
	  #############################
	  #Get middle of file
	  head -$lines $TMP_FILE > $TMP_MIDDLE
	  
	  line_count=`cat  $TMP_MIDDLE | wc -l`
	  let lines=$line_count-1
	  tail -$lines $TMP_MIDDLE > $TMP_MIDDLE2
	  
	  cat $TMP_MIDDLE2 >> $RESULT_FILE	  
	  
	  first_str=`tail -1 $TMP_FILE`	  
	fi
	  
    let count=$count+1

  done
#
#################################################################

exit 0  

ืกืงืจื™ืคึผื˜ ืคืจืึทื’ืžืึทื ืฅ ืžื™ื˜ ืขื˜ืœืขื›ืข ื“ืขืจืงืœืขืจื•ื ื’ืขืŸ:

ืกืงืจื™ืคึผื˜ ืึทืจื™ื™ึทื ืฉืจื™ื™ึทื‘ ืคึผืึทืจืึทืžืขื˜ืขืจืก:

  • ืฆื™ื™ื˜-ืกื˜ืึทืžืคึผ ืคื•ืŸ ืงืœืึธืฅ ื˜ืขืงืข ื ืึธืžืขืŸ ืื™ืŸ YYYY-MM-DD-HH24 ืคึฟืึธืจืžืึทื˜: AWS_LOG_TIME=$1
  • ื“ืึทื˜ืึทื‘ืึทืกืข ืฉื™ื™ึทืŸ: database_id=$2
  • ื’ืขื–ืืžืœื˜ ืงืœืึธืฅ ื˜ืขืงืข ื ืึธืžืขืŸ: RESULT_FILE=$3

ื‘ืึทืงื•ืžืขืŸ ื“ื™ ืฆื™ื™ื˜ ืกื˜ืึทืžืคึผ ืคื•ืŸ ื“ื™ ืœืขืฆื˜ืข ื•ืคึผืœืึธืึทื“ืขื“ ืงืœืึธืฅ ื˜ืขืงืข:

current_aws_log_time=`psql -h MONITOR_ENDPOINT.rds.amazonaws.com -U USER -d MONITOR_DATABASE -A -t -c "select last_aws_log_time from database where id = $database_id "`

ืื•ื™ื‘ ื“ื™ ืฆื™ื™ื˜ ืกื˜ืึทืžืคึผ ืคื•ืŸ ื“ื™ ืœืขืฆื˜ืข ืœืึธื•ื“ื™ื“ ืงืœืึธืฅ ื˜ืขืงืข ืื™ื– ื ื™ืฉื˜ ื’ืœื™ื™ืš ืžื™ื˜ ื“ื™ ืึทืจื™ื™ึทื ืฉืจื™ื™ึทื‘ ืคึผืึทืจืึทืžืขื˜ืขืจ, ืึท ื ื™ื™ึทืข ืงืœืึธืฅ ื˜ืขืงืข ืื™ื– ืœืึธื•ื“ื™ื“:

if [[ $current_aws_log_time != $AWS_LOG_TIME  ]];
  then
    is_new_log='1'
	if ! psql -h ENDPOINT.rds.amazonaws.com -U USER -d MONITOR_DATABASE -v ON_ERROR_STOP=1 -A -t -c "update database set last_aws_log_time = '$AWS_LOG_TIME' where id = $database_id "
	then
	  echo '***download_aws_piece.sh -FATAL_ERROR - update database set last_aws_log_time .'
	  exit 1
	fi
  else
    is_new_log='0'
  fi

ืžื™ืจ ื‘ืึทืงื•ืžืขืŸ ื“ื™ ื•ื•ืขืจื˜ ืคื•ืŸ ื“ื™ Nexttoken ืคื™ืจืžืข ืคึฟื•ืŸ ื“ื™ ืœืึธื•ื“ื™ื“ ื˜ืขืงืข:

  next_token_str=`cat $LOG_FILE | grep NEXTTOKEN` 
  next_token=`echo $next_token_str | awk -F" " '{ print $2}' `

ื“ืขืจ ืฆื™ื™ื›ืŸ ืคื•ืŸ ื“ื™ ืกื•ืฃ ืคื•ืŸ ื“ื™ ืืจืืคืงืืคื™ืข ืื™ื– ื“ื™ ืœื™ื™ื“ื™ืง ื•ื•ืขืจื˜ ืคื•ืŸ Nexttoken.

ืื™ืŸ ืึท ืฉืœื™ื™ืฃ, ืžื™ืจ ืฆื™ื™ืœืŸ ืคึผืึธืจืฉืึทื ื– ืคื•ืŸ ื“ืขืจ ื˜ืขืงืข, ืฆื•ื–ืืžืขืŸ ื“ื™ ื•ื•ืขื’, ืงืึทื ืงืึทื˜ืึทื ื™ื™ื˜ื™ื ื’ ืฉื•ืจื•ืช ืื•ืŸ ื™ื ืงืจื™ืกื™ื ื’ ื“ื™ ื’ืจื™ื™ืก ืคื•ืŸ ื“ืขืจ ื—ืœืง:
ื”ื•ื™ืคึผื˜ ืฉืœื™ื™ืฃ

# MAIN CIRCLE
  let count=2
  while [[ $next_token != '' ]];
  do 
    echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: count='$count
	
	echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: START DOWNLOADING OF AWS LOG'
	if ! aws rds download-db-log-file-portion 
     --max-items $last_aws_max_item_size 
	 --starting-token $next_token 
     --region REGION 
     --db-instance-identifier  $db_instance 
     --log-file-name error/postgresql.log.$AWS_LOG_TIME > $LOG_FILE
	then
		echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh: FATAL_ERROR - Could not get log from AWS .'
		exit 4
	fi

	next_token_str=`cat $LOG_FILE | grep NEXTTOKEN` 
	next_token=`echo $next_token_str | awk -F" " '{ print $2}' `

	TMP_FILE=$LOG_FILE'.tmp'
	grep -v NEXTTOKEN $LOG_FILE  > $TMP_FILE  
	
	last_str=`head -1 $TMP_FILE`
  
    if [[ $next_token == '' ]];
	then
	  concat_str=$first_str$last_str
	  	  
	  echo $concat_str >> $RESULT_FILE
		 
	  line_count=`cat  $TMP_FILE | wc -l`
	  let lines=$line_count-1
	  
	  tail -$lines $TMP_FILE >> $RESULT_FILE
	  
	  echo $(date +%Y%m%d%H%M)':    download_aws_piece.sh:  NEXTTOKEN NOT FOUND - FINISH '
	  rm $LOG_FILE 
	  rm $TMP_FILE
	  rm $TMP_MIDDLE
         rm $TMP_MIDDLE2	  
	  exit 0  
	fi
	
    if [[ $next_token != '' ]];
	then
		let growth_counter=$growth_counter+1
		if [[ $growth_counter -gt $growth_counter_max ]];
		then
			let last_aws_max_item_size=$last_aws_max_item_size*$growth_factor
			let growth_counter=1
		fi
	
		if [[ $last_aws_max_item_size -gt $max_item_size ]]; 
		then
			let last_aws_max_item_size=$max_item_size
		fi 

	  psql -h MONITOR_ENDPOINT.rds.amazonaws.com -U USER -d MONITOR_DATABASE -A -t -q -c "update database set last_aws_nexttoken = '$next_token' where id = $database_id "
	  
	  concat_str=$first_str$last_str
	  	  
	  echo $concat_str >> $RESULT_FILE
		 
	  line_count=`cat  $TMP_FILE | wc -l`
	  let lines=$line_count-1
	  
	  #############################
	  #Get middle of file
	  head -$lines $TMP_FILE > $TMP_MIDDLE
	  
	  line_count=`cat  $TMP_MIDDLE | wc -l`
	  let lines=$line_count-1
	  tail -$lines $TMP_MIDDLE > $TMP_MIDDLE2
	  
	  cat $TMP_MIDDLE2 >> $RESULT_FILE	  
	  
	  first_str=`tail -1 $TMP_FILE`	  
	fi
	  
    let count=$count+1

  done

ื•ื•ืืก ืื™ื– ื ืขืงืกื˜?

ืึทื–ื•ื™, ื“ืขืจ ืขืจืฉื˜ืขืจ ื™ื ื˜ืขืจืžื™ื“ื™ื™ื˜ ืึทืจื‘ืขื˜ - "ืึธืคึผืœืึธื“ื™ืจืŸ ื“ื™ ืงืœืึธืฅ ื˜ืขืงืข ืคึฟื•ืŸ ื“ื™ ื•ื•ืึธืœืงืŸ" ืื™ื– ืกืึทืœื•ื•ื“. ื•ื•ืึธืก ืฆื• ื˜ืึธืŸ ืžื™ื˜ ื“ื™ ื“ืึทื•ื ืœืึธื•ื“ื™ื“ ืงืœืึธืฅ?
ืขืจืฉื˜ืขืจ ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืคึผืึทืจืก ื“ื™ ืงืœืึธืฅ ื˜ืขืงืข ืื•ืŸ ืขืงืกื˜ืจืึทืงื˜ ื“ื™ ืคืึทืงื˜ื™ืฉ ืจื™ืงื•ื•ืขืก ืคื•ืŸ ืขืก.
ื“ื™ ืึทืจื‘ืขื˜ ืื™ื– ื ื™ืฉื˜ ื–ื™ื™ืขืจ ืฉื•ื•ืขืจ. ื“ื™ ืกื™ืžืคึผืœืึทืกื˜ ื‘ืึทืฉ-ืฉืจื™ืคื˜ ืื™ื– ื’ื•ื˜.
upload_log_query.sh

#!/bin/bash
#########################################################
# upload_log_query.sh
# Upload table table from dowloaded aws file 
# version HABR
###########################################################  
echo 'TIMESTAMP:'$(date +%c)' Upload log_query table '
source_file=$1
echo 'source_file='$source_file
database_id=$2
echo 'database_id='$database_id

beginer=' '
first_line='1'
let "line_count=0"
sql_line=' '
sql_flag=' '    
space=' '
cat $source_file | while read line
do
  line="$space$line"

  if [[ $first_line == "1" ]]; then
    beginer=`echo $line | awk -F" " '{ print $1}' `
    first_line='0'
  fi

  current_beginer=`echo $line | awk -F" " '{ print $1}' `

  if [[ $current_beginer == $beginer ]]; then
    if [[ $sql_flag == '1' ]]; then
     sql_flag='0' 
     log_date=`echo $sql_line | awk -F" " '{ print $1}' `
     log_time=`echo $sql_line | awk -F" " '{ print $2}' `
     duration=`echo $sql_line | awk -F" " '{ print $5}' `

     #replace ' to ''
     sql_modline=`echo "$sql_line" | sed 's/'''/''''''/g'`
     sql_line=' '

	 ################
	 #PROCESSING OF THE SQL-SELECT IS HERE
     if ! psql -h ENDPOINT.rds.amazonaws.com -U USER -d DATABASE -v ON_ERROR_STOP=1 -A -t -c "select log_query('$ip_port',$database_id , '$log_date' , '$log_time' , '$duration' , '$sql_modline' )" 
     then
        echo 'FATAL_ERROR - log_query '
        exit 1
     fi
	 ################

    fi #if [[ $sql_flag == '1' ]]; then

    let "line_count=line_count+1"

    check=`echo $line | awk -F" " '{ print $8}' `
    check_sql=${check^^}    

    #echo 'check_sql='$check_sql
    
    if [[ $check_sql == 'SELECT' ]]; then
     sql_flag='1'    
     sql_line="$sql_line$line"
	 ip_port=`echo $sql_line | awk -F":" '{ print $4}' `
    fi
  else       

    if [[ $sql_flag == '1' ]]; then
      sql_line="$sql_line$line"
    fi   
    
  fi #if [[ $current_beginer == $beginer ]]; then

done

ืื™ืฆื˜ ืื™ืจ ืงืขื ืขืŸ ืึทืจื‘ืขื˜ืŸ ืžื™ื˜ ื“ื™ ืึธื ืคึฟืจืขื’ ื™ืงืกื˜ืจืึทืงื˜ื™ื“ ืคื•ืŸ ื“ื™ ืงืœืึธืฅ ื˜ืขืงืข.

ืื•ืŸ ืขืก ื–ืขื ืขืŸ ืขื˜ืœืขื›ืข ื ื•ืฆื™ืง ืคึผืึทืกืึทื‘ื™ืœืึทื˜ื™ื–.

ืคึผืึทืจืกืขื“ ืงื•ื•ื™ืจื™ื– ืžื•ื–ืŸ ื–ื™ื™ืŸ ืกื˜ืึธืจื“ ืขืจื’ืขืฅ. ืคึฟืึทืจ ื“ืขื, ืึท ื“ื™ื ืกื˜ ื˜ื™ืฉ ืื™ื– ื’ืขื ื™ืฆื˜. log_query

CREATE TABLE log_query
(
   id SERIAL ,
   queryid bigint ,
   query_md5hash text not null ,
   database_id integer not null ,  
   timepoint timestamp without time zone not null,
   duration double precision not null ,
   query text not null ,
   explained_plan text[],
   plan_md5hash text  , 
   explained_plan_wo_costs text[],
   plan_hash_value text  ,
   baseline_id integer ,
   ip text ,
   port text 
);
ALTER TABLE log_query ADD PRIMARY KEY (id);
ALTER TABLE log_query ADD CONSTRAINT queryid_timepoint_unique_key UNIQUE (queryid, timepoint );
ALTER TABLE log_query ADD CONSTRAINT query_md5hash_timepoint_unique_key UNIQUE (query_md5hash, timepoint );

CREATE INDEX log_query_timepoint_idx ON log_query (timepoint);
CREATE INDEX log_query_queryid_idx ON log_query (queryid);
ALTER TABLE log_query ADD CONSTRAINT database_id_fk FOREIGN KEY (database_id) REFERENCES database (id) ON DELETE CASCADE ;

ื“ื™ ืคึผืึทืจืกืขื“ ื‘ืงืฉื” ืื™ื– ืคึผืจืึทืกืขืกื˜ ืื™ืŸ plpgsql ืคืึทื ื’ืงืฉืึทื ื– "log_query'.
log_query.sql

--log_query.sql
--verison HABR
CREATE OR REPLACE FUNCTION log_query( ip_port text ,log_database_id integer , log_date text , log_time text , duration text , sql_line text   ) RETURNS boolean AS $$
DECLARE
  result boolean ;
  log_timepoint timestamp without time zone ;
  log_duration double precision ; 
  pos integer ;
  log_query text ;
  activity_string text ;
  log_md5hash text ;
  log_explain_plan text[] ;
  
  log_planhash text ;
  log_plan_wo_costs text[] ; 
  
  database_rec record ;
  
  pg_stat_query text ; 
  test_log_query text ;
  log_query_rec record;
  found_flag boolean;
  
  pg_stat_history_rec record ;
  port_start integer ;
  port_end integer ;
  client_ip text ;
  client_port text ;
  log_queryid bigint ;
  log_query_text text ;
  pg_stat_query_text text ; 
BEGIN
  result = TRUE ;

  RAISE NOTICE '***log_query';
  
  port_start = position('(' in ip_port);
  port_end = position(')' in ip_port);
  client_ip = substring( ip_port from 1 for port_start-1 );
  client_port = substring( ip_port from port_start+1 for port_end-port_start-1 );

  SELECT e.host , d.name , d.owner_pwd 
  INTO database_rec
  FROM database d JOIN endpoint e ON e.id = d.endpoint_id
  WHERE d.id = log_database_id ;
  
  log_timepoint = to_timestamp(log_date||' '||log_time,'YYYY-MM-DD HH24-MI-SS');
  log_duration = duration:: double precision; 

  
  pos = position ('SELECT' in UPPER(sql_line) );
  log_query = substring( sql_line from pos for LENGTH(sql_line));
  log_query = regexp_replace(log_query,' +',' ','g');
  log_query = regexp_replace(log_query,';+','','g');
  log_query = trim(trailing ' ' from log_query);
 

  log_md5hash = md5( log_query::text );
  
  --Explain execution plan--
  EXECUTE 'SELECT dblink_connect(''LINK1'',''host='||database_rec.host||' dbname='||database_rec.name||' user=DATABASE password='||database_rec.owner_pwd||' '')'; 
  
  log_explain_plan = ARRAY ( SELECT * FROM dblink('LINK1', 'EXPLAIN '||log_query ) AS t (plan text) );
  log_plan_wo_costs = ARRAY ( SELECT * FROM dblink('LINK1', 'EXPLAIN ( COSTS FALSE ) '||log_query ) AS t (plan text) );
    
  PERFORM dblink_disconnect('LINK1');
  --------------------------
  BEGIN
	INSERT INTO log_query
	(
		query_md5hash ,
		database_id , 
		timepoint ,
		duration ,
		query ,
		explained_plan ,
		plan_md5hash , 
		explained_plan_wo_costs , 
		plan_hash_value , 
		ip , 
		port
	) 
	VALUES 
	(
		log_md5hash ,
		log_database_id , 
		log_timepoint , 
		log_duration , 
		log_query ,
		log_explain_plan , 
		md5(log_explain_plan::text) ,
		log_plan_wo_costs , 
		md5(log_plan_wo_costs::text),
		client_ip , 
		client_port		
	);
	activity_string = 	'New query has logged '||
						' database_id = '|| log_database_id ||
						' query_md5hash='||log_md5hash||
						' , timepoint = '||to_char(log_timepoint,'YYYYMMDD HH24:MI:SS');
					
	RAISE NOTICE '%',activity_string;					
					 
	PERFORM pg_log( log_database_id , 'log_query' , activity_string);  

	EXCEPTION
	  WHEN unique_violation THEN
		RAISE NOTICE '*** unique_violation *** query already has logged';
	END;

	SELECT 	queryid
	INTO   	log_queryid
	FROM 	log_query 
	WHERE 	query_md5hash = log_md5hash AND
			timepoint = log_timepoint;

	IF log_queryid IS NOT NULL 
	THEN 
	  RAISE NOTICE 'log_query with query_md5hash = % and timepoint = % has already has a QUERYID = %',log_md5hash,log_timepoint , log_queryid ;
	  RETURN result;
	END IF;
	
	------------------------------------------------
	RAISE NOTICE 'Update queryid';	
	
	SELECT * 
	INTO log_query_rec
	FROM log_query
	WHERE query_md5hash = log_md5hash AND timepoint = log_timepoint ; 
	
	log_query_rec.query=regexp_replace(log_query_rec.query,';+','','g');
	
	FOR pg_stat_history_rec IN
	 SELECT 
         queryid ,
	  query 
	 FROM 
         pg_stat_db_queries 
     WHERE  
      database_id = log_database_id AND
       queryid is not null 
	LOOP
	  pg_stat_query = pg_stat_history_rec.query ; 
	  pg_stat_query=regexp_replace(pg_stat_query,'n+',' ','g');
	  pg_stat_query=regexp_replace(pg_stat_query,'t+',' ','g');
	  pg_stat_query=regexp_replace(pg_stat_query,' +',' ','g');
	  pg_stat_query=regexp_replace(pg_stat_query,'$.','%','g');
	
	  log_query_text = trim(trailing ' ' from log_query_rec.query);
	  pg_stat_query_text = pg_stat_query; 
	
	  
	  --SELECT log_query_rec.query like pg_stat_query INTO found_flag ; 
	  IF (log_query_text LIKE pg_stat_query_text) THEN
		found_flag = TRUE ;
	  ELSE
		found_flag = FALSE ;
	  END IF;	  
	  
	  
	  IF found_flag THEN
	    
		UPDATE log_query SET queryid = pg_stat_history_rec.queryid WHERE query_md5hash = log_md5hash AND timepoint = log_timepoint ;
		activity_string = 	' updated queryid = '||pg_stat_history_rec.queryid||
		                    ' for log_query with id = '||log_query_rec.id               
		   				    ;						
	    RAISE NOTICE '%',activity_string;	
		EXIT ;
	  END IF ;
	  
	END LOOP ;
	
  RETURN result ;
END
$$ LANGUAGE plpgsql;

ื•ื•ืขืŸ ืคึผืจืึทืกืขืกื™ื ื’, ื“ื™ ื“ื™ื ืกื˜ ื˜ื™ืฉ ืื™ื– ื’ืขื ื™ืฆื˜ pg_stat_db_queriesื ื•ื•ืึธืก ื›ึผื•ืœืœ ืึท ืžืึธืžืขื ื˜ื‘ื™ืœื“ ืคื•ืŸ ื“ื™ ืงืจืึทื ื˜ ืคึฟืจืื’ืŸ ืคื•ืŸ ื“ื™ ื˜ื™ืฉ pg_stat_history (ื˜ื™ืฉ ื‘ืึทื ื™ืฅ ืื™ื– ื“ื™ืกืงืจื™ื™ื‘ื“ ื“ืึธ - ืคืึธืจืฉื˜ืขืœื•ื ื’ ืžืึธื ื™ื˜ืึธืจื™ื ื’ ืคื•ืŸ PostgreSQL ืคึฟืจืื’ืŸ. ื˜ื™ื™ืœ 1 - ืจื™ืคึผืึธืจื˜ื™ื ื’)

TABLE pg_stat_db_queries
(
   database_id integer,  
   queryid bigint ,  
   query text , 
   max_time double precision 
);

TABLE pg_stat_history 
(
โ€ฆ
database_id integer ,
โ€ฆ
queryid bigint ,
โ€ฆ
max_time double precision	 , 	
โ€ฆ
);

ื“ื™ ืคึฟื•ื ืงืฆื™ืข ืึทืœืึทื•ื– ืื™ืจ ืฆื• ื™ื ืกื˜ืจื•ืžืขื ื˜ ืึท ื ื•ืžืขืจ ืคื•ืŸ ื ื•ืฆื™ืง ืคึฟืขื™ึดืงื™ื™ื˜ืŸ ืคึฟืึทืจ ืคึผืจืึทืกืขืกื™ื ื’ ืจื™ืงื•ื•ืขืก ืคึฟื•ืŸ ืึท ืงืœืึธืฅ ื˜ืขืงืข. ื ืขืžืœื™ืš:

ื’ืขืœืขื’ื ื”ื™ื™ื˜ #1 - ืึธื ืคึฟืจืขื’ ื“ื•ืจื›ืคื™ืจื•ื ื’ ื’ืขืฉื™ื›ื˜ืข

ื–ื™ื™ืขืจ ื ื•ืฆื™ืง ืคึฟืึทืจ ืกื˜ืึทืจื˜ื™ื ื’ ืึท ืคืึธืจืฉื˜ืขืœื•ื ื’ ืื™ื ืฆื™ื“ืขื ื˜. ืขืจืฉื˜ืขืจ, ื‘ืึทืงื•ืžืขืŸ ื‘ืึทืงืึทื ื˜ ืžื™ื˜ ื“ื™ ื’ืขืฉื™ื›ื˜ืข - ืื•ืŸ ื•ื•ืขืŸ ื”ืื˜ ื“ื™ ืกืœืึธื•ื“ืึทื•ืŸ ืื ื’ืขื”ื•ื™ื‘ืŸ?
ื“ืขืจื ืึธืš, ืœื•ื™ื˜ ื“ื™ ืงืœืึทืกื™ืงืก, ืงื•ืง ืคึฟืึทืจ ืคื•ื ื“ืจื•ื™ืกื ื“ื™ืง ืกื™ื‘ื•ืช. ืขืก ืงืขืŸ ื ืึธืจ ื–ื™ื™ืŸ ืึทื– ื“ื™ ื“ืึทื˜ืึทื‘ื™ื™ืก ืžืึทืกืข ืื™ื– ื’ืขื•ื•ืืงืกืŸ ื“ืจืึทืžืึทื˜ื™ืงืœื™ ืื•ืŸ ื“ื™ ืกืคึผืขืฆื™ืคื™ืฉ ื‘ืงืฉื” ื”ืื˜ ื’ืึธืจื ื™ืฉื˜ ืฆื• ื˜ืึธืŸ ืžื™ื˜ ืื™ื.
ืœื™ื™ื’ ื ื™ื™ึท ืคึผืึธื–ื™ืฆื™ืข ืฆื• ืœืึธื’_ืงื•ื•ืขืจื™ ื˜ื™ืฉ

  port_start = position('(' in ip_port);
  port_end = position(')' in ip_port);
  client_ip = substring( ip_port from 1 for port_start-1 );
  client_port = substring( ip_port from port_start+1 for port_end-port_start-1 );

  SELECT e.host , d.name , d.owner_pwd 
  INTO database_rec
  FROM database d JOIN endpoint e ON e.id = d.endpoint_id
  WHERE d.id = log_database_id ;
  
  log_timepoint = to_timestamp(log_date||' '||log_time,'YYYY-MM-DD HH24-MI-SS');
  log_duration = to_number(duration,'99999999999999999999D9999999999'); 

  
  pos = position ('SELECT' in UPPER(sql_line) );
  log_query = substring( sql_line from pos for LENGTH(sql_line));
  log_query = regexp_replace(log_query,' +',' ','g');
  log_query = regexp_replace(log_query,';+','','g');
  log_query = trim(trailing ' ' from log_query);
 
  RAISE NOTICE 'log_query=%',log_query ;   

  log_md5hash = md5( log_query::text );
  
  --Explain execution plan--
  EXECUTE 'SELECT dblink_connect(''LINK1'',''host='||database_rec.host||' dbname='||database_rec.name||' user=DATABASE password='||database_rec.owner_pwd||' '')'; 
  
  log_explain_plan = ARRAY ( SELECT * FROM dblink('LINK1', 'EXPLAIN '||log_query ) AS t (plan text) );
  log_plan_wo_costs = ARRAY ( SELECT * FROM dblink('LINK1', 'EXPLAIN ( COSTS FALSE ) '||log_query ) AS t (plan text) );
    
  PERFORM dblink_disconnect('LINK1');
  --------------------------
  BEGIN
	INSERT INTO log_query
	(
		query_md5hash ,
		database_id , 
		timepoint ,
		duration ,
		query ,
		explained_plan ,
		plan_md5hash , 
		explained_plan_wo_costs , 
		plan_hash_value , 
		ip , 
		port
	) 
	VALUES 
	(
		log_md5hash ,
		log_database_id , 
		log_timepoint , 
		log_duration , 
		log_query ,
		log_explain_plan , 
		md5(log_explain_plan::text) ,
		log_plan_wo_costs , 
		md5(log_plan_wo_costs::text),
		client_ip , 
		client_port		
	);

ืฉื˜ืจื™ืš #2 - ื”ื™ื˜ ืงื•ื•ืขืจื™ ืขืงืกืขืงื•ื˜ื™ืึธืŸ ืคึผืœืึทื ืก

ืื™ืŸ ื“ืขื ืคื•ื ื˜, ืึท ืึทื‘ื“ื–ืฉืขืงืฉืึทืŸ-ืงืœืขืจืึทืคืึทืงื™ื™ืฉืึทืŸ-ื‘ืึทืžืขืจืงื•ื ื’ ืงืขืŸ ืื•ื™ืคืฉื˜ื™ื™ืŸ: "ืื‘ืขืจ ืขืก ืื™ื– ืฉื•ื™ืŸ ืึทื•ื˜ืึธืขืงืกืคึผืœืึทื™ืŸ". ื™ืึธ, ืขืก ืื™ื–, ืึธื‘ืขืจ ื•ื•ืึธืก ืื™ื– ื“ื™ ืคื•ื ื˜ ืื•ื™ื‘ ื“ืขืจ ื“ื•ืจื›ืคื™ืจื•ื ื’ ืคึผืœืึทืŸ ืื™ื– ืกื˜ืึธืจื“ ืื™ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืงืœืึธืฅ ื˜ืขืงืข ืื•ืŸ ืฆื• ืจืึทื˜ืขื•ื•ืขืŸ ืขืก ืคึฟืึทืจ ื•ื•ื™ื™ึทื˜ืขืจ ืึทื ืึทืœื™ืกื™ืก, ืื™ืจ ืžื•ื–ืŸ ืคึผืึทืจืก ื“ื™ ืงืœืึธืฅ ื˜ืขืงืข?

ืึธื‘ืขืจ, ืื™ืš ื“ืืจืฃ:
ืขืจืฉื˜ืขืจ: ืงืจืึธื ื“ื™ ื“ื•ืจื›ืคื™ืจื•ื ื’ ืคึผืœืึทืŸ ืื™ืŸ ื“ื™ ื“ื™ื ืกื˜ ื˜ื™ืฉ ืคื•ืŸ ื“ื™ ืžืึธื ื™ื˜ืึธืจื™ื ื’ ื“ืึทื˜ืึทื‘ื™ื™ืก;
ืฆื•ื•ื™ื™ื˜ื ืก: ืฆื• ืงืขื ืขืŸ ืคืึทืจื’ืœื™ื™ึทื›ืŸ ื“ื•ืจื›ืคื™ืจื•ื ื’ ืคึผืœืึทื ื– ืžื™ื˜ ื™ืขื“ืขืจ ืื ื“ืขืจืข ืื™ืŸ ืกื“ืจ ืฆื• ืžื™ื“ ื–ืขืŸ ืึทื– ื“ื™ ืึธื ืคึฟืจืขื’ ื“ื•ืจื›ืคื™ืจื•ื ื’ ืคึผืœืึทืŸ ื”ืื˜ ื’ืขื‘ื™ื˜ืŸ.

ื ื‘ืงืฉื” ืžื™ื˜ ืกืคึผืขืฆื™ืคื™ืฉ ื“ื•ืจื›ืคื™ืจื•ื ื’ ืคึผืึทืจืึทืžืขื˜ืขืจืก ืื™ื– ื‘ื ื™ืžืฆื. ื‘ืึทืงื•ืžืขืŸ ืื•ืŸ ืกื˜ืึธืจื™ื ื’ ื–ื™ื™ืŸ ื“ื•ืจื›ืคื™ืจื•ื ื’ ืคึผืœืึทืŸ ืžื™ื˜ EXPLAIN ืื™ื– ืึทืŸ ืขืœืขืžืขื ื˜ืึทืจ ืึทืจื‘ืขื˜.
ื“ืขืจืฆื•, ื ื™ืฆืŸ ื“ื™ EXPLAIN (COSTS FALSE) ืื•ื™ืกื“ืจื•ืง, ืื™ืจ ืงืขื ืขืŸ ื‘ืึทืงื•ืžืขืŸ ื“ื™ ืคืจื™ื™ืžื•ื•ืขืจืง ืคื•ืŸ ื“ืขื ืคึผืœืึทืŸ, ื•ื•ืึธืก ื•ื•ืขื˜ ื–ื™ื™ืŸ ื’ืขื ื•ืฆื˜ ืฆื• ื‘ืึทืงื•ืžืขืŸ ื“ื™ ื”ืึทืฉ ื•ื•ืขืจื˜ ืคื•ืŸ ื“ืขื ืคึผืœืึทืŸ, ื•ื•ืึธืก ื•ื•ืขื˜ ื”ืขืœืคึฟืŸ ืื™ืŸ ื“ื™ ืกืึทื‘ืกืึทืงื•ื•ืึทื ื˜ ืึทื ืึทืœื™ืกื™ืก ืคื•ืŸ ื“ื™ ืขื ื“ืขืจื•ื ื’ืขืŸ ื’ืขืฉื™ื›ื˜ืข ืคื•ืŸ โ€‹โ€‹ื“ื™ ื“ื•ืจื›ืคื™ืจื•ื ื’ ืคึผืœืึทืŸ.
ื‘ืึทืงื•ืžืขืŸ ืึท ื“ื•ืจื›ืคื™ืจื•ื ื’ ืคึผืœืึทืŸ ืžื•ืกื˜ืขืจ

  --Explain execution plan--
  EXECUTE 'SELECT dblink_connect(''LINK1'',''host='||database_rec.host||' dbname='||database_rec.name||' user=DATABASE password='||database_rec.owner_pwd||' '')'; 
  
  log_explain_plan = ARRAY ( SELECT * FROM dblink('LINK1', 'EXPLAIN '||log_query ) AS t (plan text) );
  log_plan_wo_costs = ARRAY ( SELECT * FROM dblink('LINK1', 'EXPLAIN ( COSTS FALSE ) '||log_query ) AS t (plan text) );
    
  PERFORM dblink_disconnect('LINK1');

ื’ืขืœืขื’ื ื”ื™ื™ื˜ #3 - ื ื™ืฆืŸ ื“ื™ ืึธื ืคึฟืจืขื’ ืงืœืึธืฅ ืคึฟืึทืจ ืžืึธื ื™ื˜ืึธืจื™ื ื’

ื–ื™ื ื˜ ื“ื™ ืคืึธืจืฉื˜ืขืœื•ื ื’ ืžืขื˜ืจื™ืงืก ื–ืขื ืขืŸ ืงืึทื ืคื™ื’ื™ืขืจื“ ื ื™ืฉื˜ ืคึฟืึทืจ ื“ื™ ื‘ืขื˜ืŸ ื˜ืขืงืกื˜, ืึธื‘ืขืจ ืคึฟืึทืจ ื–ื™ื™ืŸ ืฉื™ื™ึทืŸ, ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืคืึทืจื‘ื™ื ื“ืŸ ืจื™ืงื•ื•ืขืก ืคื•ืŸ ื“ื™ ืงืœืึธืฅ ื˜ืขืงืข ืžื™ื˜ ืจื™ืงื•ื•ืขืก ืคึฟืึทืจ ื•ื•ืึธืก ืคืึธืจืฉื˜ืขืœื•ื ื’ ืžืขื˜ืจื™ืงืก ื–ืขื ืขืŸ ืงืึทื ืคื™ื’ื™ืขืจื“.
ื ื•, ืื™ืŸ ืžื™ื ื“ืกื˜ืขืจ ืื™ืŸ ืกื“ืจ ืฆื• ื”ืึธื‘ืŸ ื“ื™ ืคึผื™ื ื˜ืœืขืš ืฆื™ื™ื˜ ืคื•ืŸ ืคึผืึทืกื™ืจื•ื ื’ ืคื•ืŸ ืึท ืคืึธืจืฉื˜ืขืœื•ื ื’ ืื™ื ืฆื™ื“ืขื ื˜.

ืื–ื•ื™, ื•ื•ืขืŸ ืึท ืคืึธืจืฉื˜ืขืœื•ื ื’ ืื™ื ืฆื™ื“ืขื ื˜ ืึทืงืขืจื– ืคึฟืึทืจ ืึท ื‘ืขื˜ืŸ ืฉื™ื™ึทืŸ, ืขืก ื•ื•ืขื˜ ื–ื™ื™ืŸ ืึท ืจืขืคึฟืขืจืขื ืฅ ืฆื• ืึท ืกืคึผืขืฆื™ืคื™ืฉ ื‘ืขื˜ืŸ ืžื™ื˜ ืกืคึผืขืฆื™ืคื™ืฉ ืคึผืึทืจืึทืžืขื˜ืขืจ ื•ื•ืึทืœื•ืขืก ืื•ืŸ ื“ื™ ืคึผื™ื ื˜ืœืขืš ื“ื•ืจื›ืคื™ืจื•ื ื’ ืฆื™ื™ื˜ ืื•ืŸ ื’ืขื“ื•ื™ืขืจ ืคื•ืŸ ื“ื™ ื‘ืขื˜ืŸ. ื‘ืึทืงื•ืžืขืŸ ื“ื™ ื’ืขื’ืขื‘ืŸ ืื™ื ืคึฟืึธืจืžืึทืฆื™ืข ื ื™ืฆืŸ ื‘ืœื•ื™ื– ื“ื™ ืžื™ื™ื ื•ื ื’ pg_stat_statements โ€” ืืณืื™ื– ืคืืจื‘ืื˜ืŸ.
ื’ืขืคึฟื™ื ืขืŸ ื“ื™ queryid ืคื•ืŸ ื“ื™ ืึธื ืคึฟืจืขื’ ืื•ืŸ ื“ืขืจื”ื™ื™ึทื ื˜ื™ืงืŸ ื“ื™ ืคึผืึธื–ื™ืฆื™ืข ืื™ืŸ ื“ื™ log_query ื˜ื™ืฉ

SELECT * 
	INTO log_query_rec
	FROM log_query
	WHERE query_md5hash = log_md5hash AND timepoint = log_timepoint ; 
	
	log_query_rec.query=regexp_replace(log_query_rec.query,';+','','g');
	
	FOR pg_stat_history_rec IN
	 SELECT 
      queryid ,
	  query 
	 FROM 
       pg_stat_db_queries 
     WHERE  
	   database_id = log_database_id AND
       queryid is not null 
	LOOP
	  pg_stat_query = pg_stat_history_rec.query ; 
	  pg_stat_query=regexp_replace(pg_stat_query,'n+',' ','g');
	  pg_stat_query=regexp_replace(pg_stat_query,'t+',' ','g');
	  pg_stat_query=regexp_replace(pg_stat_query,' +',' ','g');
	  pg_stat_query=regexp_replace(pg_stat_query,'$.','%','g');
	
	  log_query_text = trim(trailing ' ' from log_query_rec.query);
	  pg_stat_query_text = pg_stat_query; 
	  
	  --SELECT log_query_rec.query like pg_stat_query INTO found_flag ; 
	  IF (log_query_text LIKE pg_stat_query_text) THEN
		found_flag = TRUE ;
	  ELSE
		found_flag = FALSE ;
	  END IF;	  
	  
	  
	  IF found_flag THEN
	    
		UPDATE log_query SET queryid = pg_stat_history_rec.queryid WHERE query_md5hash = log_md5hash AND timepoint = log_timepoint ;
		activity_string = 	' updated queryid = '||pg_stat_history_rec.queryid||
		                    ' for log_query with id = '||log_query_rec.id		                    
		   				    ;						
					
	    RAISE NOTICE '%',activity_string;	
		EXIT ;
	  END IF ;
	  
	END LOOP ;

ืึทืคื˜ืขืจื•ื•ืึธืจื“

ื•ื•ื™ ืึท ืจืขื–ื•ืœื˜ืึทื˜, ื“ื™ ื“ื™ืกืงืจื™ื™ื‘ื“ ืื•ืคึฟืŸ ื”ืื˜ ื’ืขืคึฟื•ื ืขืŸ ื–ื™ื™ึทืŸ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืื™ืŸ ื“ืขื•ื•ืขืœืึธืคึผืขื“ ืกื™ืกื˜ืขื ืคึฟืึทืจ ืžืึธื ื™ื˜ืึธืจื™ื ื’ ื“ื™ ืคืึธืจืฉื˜ืขืœื•ื ื’ ืคื•ืŸ PostgreSQL ืงื•ื•ื™ืจื™ื–, ืึทืœืึทื•ื™ื ื’ ืื™ืจ ืฆื• ื”ืึธื‘ืŸ ืžืขืจ ืื™ื ืคึฟืึธืจืžืึทืฆื™ืข ืคึฟืึทืจ ืึทื ืึทืœื™ืกื™ืก ื•ื•ืขืŸ ืจื™ื–ืึทืœื•ื•ื™ื ื’ ื™ืžืขืจื“ื–ืฉื™ื ื’ ืึธื ืคึฟืจืขื’ ืคืึธืจืฉื˜ืขืœื•ื ื’ ื™ื ืกืึทื“ืึทื ืฅ.

ื›ืึธื˜ืฉ, ืคื•ืŸ ืงื•ืจืก, ืื™ืŸ ืžื™ื™ืŸ ืคึผืขืจื–ืขื ืœืขืš ืžื™ื™ื ื•ื ื’, ืขืก ื•ื•ืขื˜ ื ืึธืš ื–ื™ื™ืŸ ื ื™ื™ื˜ื™ืง ืฆื• ืึทืจื‘ืขื˜ืŸ ืื•ื™ืฃ ื“ื™ ืึทืœื’ืขืจื™ื“ืึทื ืคึฟืึทืจ ืกืขืœื™ื ื’ ืื•ืŸ ื˜ืฉืึทื ื’ื™ื ื’ ื“ื™ ื’ืจื™ื™ืก ืคื•ืŸ ื“ื™ ื“ืึทื•ื ืœืึธื•ื“ื™ื“ ื—ืœืง. ื“ืขืจ ืคึผืจืึธื‘ืœืขื ืื™ื– ื ืึธืš ื ื™ืฉื˜ ืกืึทืœื•ื•ื“ ืื™ืŸ ื“ื™ ืึทืœื’ืขืžื™ื™ื ืข ืคืึทืœ. ืขืก ื•ื•ืขื˜ ืžื™ืกื˜ืึธืžืข ื–ื™ื™ืŸ ื˜ืฉื™ืงืึทื•ื•ืข.

ืื‘ืขืจ ื“ืืก ืื™ื– ื’ืืจ ืืŸ ืื ื“ืขืจืข ืžืขืฉื”...

ืžืงื•ืจ: www.habr.com

ืงื•ื™ืคืŸ ืคืึทืจืœืึธื–ืœืขืš ื”ืึธืกื˜ื™ื ื’ ืคึฟืึทืจ ื–ื™ื™ื˜ืœืขืš ืžื™ื˜ DDoS ืฉื•ืฅ, VPS VDS ืกืขืจื•ื•ืขืจืก ๐Ÿ”ฅ ืงื•ื™ืคื˜ ืคืึทืจืœืขืกืœืขื›ืข ื•ื•ืขื‘ื–ื™ื™ื˜ืœ ื”ืึธืกื˜ื™ื ื’ ืžื™ื˜ DDoS ืฉื•ืฅ, VPS VDS ืกืขืจื•ื•ืขืจืก | ProHoster