PostgreSQL แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ AWS แƒฆแƒ แƒฃแƒ‘แƒšแƒ˜แƒ“แƒแƒœ

แƒแƒœ แƒชแƒแƒขแƒ แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒ—แƒ˜ แƒขแƒ”แƒขแƒ แƒ˜แƒกแƒแƒšแƒแƒ’แƒ˜แƒ.
แƒงแƒ•แƒ”แƒšแƒแƒคแƒ”แƒ แƒ˜ แƒแƒฎแƒแƒšแƒ˜ แƒ™แƒแƒ แƒ’แƒแƒ“ แƒ“แƒแƒ•แƒ˜แƒฌแƒงแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒซแƒ•แƒ”แƒšแƒ˜แƒ.
แƒ”แƒžแƒ˜แƒ’แƒ แƒแƒคแƒ”แƒ‘แƒ˜.
PostgreSQL แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ AWS แƒฆแƒ แƒฃแƒ‘แƒšแƒ˜แƒ“แƒแƒœ

แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ˜แƒก แƒจแƒ”แƒกแƒแƒฎแƒ”แƒ‘ แƒ’แƒแƒœแƒชแƒฎแƒแƒ“แƒ”แƒ‘แƒ

แƒ—แƒฅแƒ•แƒ”แƒœ แƒžแƒ”แƒ แƒ˜แƒแƒ“แƒฃแƒšแƒแƒ“ แƒฃแƒœแƒ“แƒ แƒฉแƒแƒ›แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒแƒ— PostgreSQL แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒคแƒแƒ˜แƒšแƒ˜ AWS แƒฆแƒ แƒฃแƒ‘แƒšแƒ˜แƒ“แƒแƒœ แƒ—แƒฅแƒ•แƒ”แƒœแƒก แƒแƒ“แƒ’แƒ˜แƒšแƒแƒ‘แƒ แƒ˜แƒ• Linux แƒฐแƒแƒกแƒขแƒจแƒ˜. แƒแƒ แƒ แƒ แƒ”แƒแƒšแƒฃแƒ  แƒ“แƒ แƒแƒจแƒ˜, แƒ›แƒแƒ’แƒ แƒแƒ›, แƒ•แƒ—แƒฅแƒ•แƒแƒ—, แƒ›แƒชแƒ˜แƒ แƒ” แƒ“แƒแƒ’แƒ•แƒ˜แƒแƒœแƒ”แƒ‘แƒ˜แƒ—.
แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒ’แƒแƒœแƒแƒฎแƒšแƒ”แƒ‘แƒ˜แƒก แƒฉแƒแƒ›แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ˜แƒก แƒžแƒ”แƒ แƒ˜แƒแƒ“แƒ˜ 5 แƒฌแƒฃแƒ—แƒ˜แƒ.
แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒคแƒแƒ˜แƒšแƒ˜ AWS-แƒจแƒ˜ แƒ‘แƒ แƒฃแƒœแƒแƒ•แƒก แƒงแƒแƒ•แƒ”แƒš แƒกแƒแƒแƒ—แƒจแƒ˜.

แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ˜แƒœแƒกแƒขแƒ แƒฃแƒ›แƒ”แƒœแƒขแƒ”แƒ‘แƒ˜

แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒฐแƒแƒกแƒขแƒจแƒ˜ แƒฉแƒแƒ›แƒแƒกแƒแƒขแƒ•แƒ˜แƒ แƒ—แƒแƒ“ แƒ’แƒแƒ›แƒแƒ˜แƒงแƒ”แƒœแƒ”แƒ‘แƒ bash แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒฃแƒฌแƒแƒ“แƒ”แƒ‘แƒก AWS API-แƒก.aws rds download-db-log-file-portion".

แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ”แƒ‘แƒ˜:

  • โ€”db-instance-identifier: AWS แƒ˜แƒœแƒกแƒขแƒแƒœแƒชแƒ˜แƒ˜แƒก แƒกแƒแƒฎแƒ”แƒšแƒ˜;
  • --log-file-name: แƒแƒ›แƒŸแƒแƒ›แƒแƒ“ แƒ’แƒ”แƒœแƒ”แƒ แƒ˜แƒ แƒ”แƒ‘แƒฃแƒšแƒ˜ แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒกแƒแƒฎแƒ”แƒšแƒ˜
  • --max-item: แƒ‘แƒ แƒซแƒแƒœแƒ”แƒ‘แƒ˜แƒก แƒ’แƒแƒ›แƒแƒ›แƒแƒ•แƒแƒšแƒจแƒ˜ แƒ“แƒแƒ‘แƒ แƒฃแƒœแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ”แƒšแƒ”แƒ›แƒ”แƒœแƒขแƒ”แƒ‘แƒ˜แƒก แƒกแƒแƒ”แƒ แƒ—แƒ แƒ แƒแƒแƒ“แƒ”แƒœแƒแƒ‘แƒ.แƒ’แƒแƒ“แƒ›แƒแƒฌแƒ”แƒ แƒ˜แƒšแƒ˜ แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒœแƒแƒฌแƒ˜แƒšแƒ˜แƒก แƒ–แƒแƒ›แƒ.
  • --starting-token: แƒกแƒแƒฌแƒงแƒ˜แƒกแƒ˜ แƒœแƒ˜แƒจแƒแƒœแƒ˜

แƒแƒ› แƒ™แƒแƒœแƒ™แƒ แƒ”แƒขแƒฃแƒš แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒ›แƒแƒ แƒ”แƒ‘แƒ˜แƒก แƒฉแƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ˜แƒก แƒแƒ›แƒแƒชแƒแƒœแƒ แƒฌแƒแƒ แƒ›แƒแƒ˜แƒจแƒ•แƒ แƒ›แƒฃแƒจแƒแƒแƒ‘แƒ˜แƒก แƒ“แƒ แƒแƒก PostgreSQL แƒจแƒ”แƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ›แƒแƒœแƒ˜แƒขแƒแƒ แƒ˜แƒœแƒ’แƒ˜.

แƒ“แƒ แƒ”แƒก แƒ›แƒแƒ แƒขแƒ˜แƒ•แƒ˜แƒ - แƒกแƒแƒ˜แƒœแƒขแƒ”แƒ แƒ”แƒกแƒ แƒแƒ›แƒแƒชแƒแƒœแƒ แƒ•แƒแƒ แƒฏแƒ˜แƒจแƒ˜แƒกแƒ แƒ“แƒ แƒ›แƒ แƒแƒ•แƒแƒšแƒคแƒ”แƒ แƒแƒ•แƒœแƒ”แƒ‘แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก แƒกแƒแƒ›แƒฃแƒจแƒแƒ แƒกแƒแƒแƒ—แƒ”แƒ‘แƒจแƒ˜.
แƒ•แƒ˜แƒ•แƒแƒ แƒแƒฃแƒ“แƒ”แƒ‘, แƒ แƒแƒ› แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ แƒฃแƒ™แƒ•แƒ” แƒ›แƒแƒ’แƒ•แƒแƒ แƒ”แƒ‘แƒฃแƒšแƒ˜แƒ แƒงแƒแƒ•แƒ”แƒšแƒ“แƒฆแƒ˜แƒฃแƒ แƒแƒ‘แƒ˜แƒก แƒ’แƒแƒ›แƒ. แƒ›แƒแƒ’แƒ แƒแƒ› แƒกแƒฌแƒ แƒแƒคแƒ›แƒ Google-แƒ›แƒ แƒแƒ  แƒจแƒ”แƒ›แƒแƒ’แƒ•แƒ—แƒแƒ•แƒแƒ–แƒ แƒ แƒแƒ˜แƒ›แƒ” แƒ’แƒแƒ“แƒแƒฌแƒงแƒ•แƒ”แƒขแƒ แƒ“แƒ แƒ›แƒ” แƒแƒ  แƒ›แƒฅแƒแƒœแƒ˜แƒ แƒ“แƒ˜แƒ“แƒ˜ แƒกแƒฃแƒ แƒ•แƒ˜แƒšแƒ˜, แƒ แƒแƒ› แƒฃแƒคแƒ แƒ แƒฆแƒ แƒ›แƒแƒ“ แƒ›แƒแƒซแƒ”แƒ‘แƒœแƒ. แƒœแƒ”แƒ‘แƒ˜แƒกแƒ›แƒ˜แƒ”แƒ  แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒ”แƒก แƒ™แƒแƒ แƒ’แƒ˜ แƒ•แƒแƒ แƒฏแƒ˜แƒจแƒ˜แƒ.

แƒ“แƒแƒ•แƒแƒšแƒ”แƒ‘แƒ˜แƒก แƒคแƒแƒ แƒ›แƒแƒšแƒ˜แƒ–แƒ”แƒ‘แƒ

แƒกแƒแƒ‘แƒแƒšแƒแƒ แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒคแƒแƒ˜แƒšแƒ˜ แƒจแƒ”แƒ“แƒ’แƒ”แƒ‘แƒ แƒชแƒ•แƒšแƒแƒ“แƒ˜ แƒกแƒ˜แƒ’แƒ แƒซแƒ˜แƒก แƒ›แƒ แƒแƒ•แƒแƒšแƒ˜ แƒฎแƒแƒ–แƒ˜แƒกแƒ’แƒแƒœ. แƒ’แƒ แƒแƒคแƒ˜แƒ™แƒฃแƒšแƒแƒ“, แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒคแƒแƒ˜แƒšแƒ˜ แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒแƒกแƒ” แƒ˜แƒงแƒแƒก แƒฌแƒแƒ แƒ›แƒแƒ“แƒ’แƒ”แƒœแƒ˜แƒšแƒ˜:
PostgreSQL แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ AWS แƒฆแƒ แƒฃแƒ‘แƒšแƒ˜แƒ“แƒแƒœ

แƒ”แƒก แƒฃแƒ™แƒ•แƒ” แƒ แƒแƒฆแƒแƒชแƒแƒก แƒ’แƒแƒฎแƒกแƒ”แƒœแƒ”แƒ‘แƒก? แƒ แƒ แƒจแƒฃแƒแƒจแƒ˜แƒ แƒขแƒ”แƒขแƒ แƒ˜แƒกแƒ˜? แƒ“แƒ แƒแƒ˜, แƒ แƒ แƒ™แƒแƒ•แƒจแƒ˜แƒ แƒ˜ แƒแƒฅแƒ•แƒก แƒ›แƒแƒก.
แƒ—แƒฃ แƒฌแƒแƒ แƒ›แƒแƒ•แƒ˜แƒ“แƒ’แƒ”แƒœแƒ— แƒจแƒ”แƒกแƒแƒซแƒšแƒ แƒ•แƒแƒ แƒ˜แƒแƒœแƒขแƒ”แƒ‘แƒก, แƒ แƒแƒ›แƒšแƒ”แƒ‘แƒ˜แƒช แƒฌแƒแƒ แƒ›แƒแƒ˜แƒฅแƒ›แƒœแƒ”แƒ‘แƒ แƒจแƒ”แƒ›แƒ“แƒ”แƒ’แƒ˜ แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒ’แƒ แƒแƒคแƒ˜แƒ™แƒฃแƒšแƒแƒ“ แƒฉแƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ˜แƒกแƒแƒก (แƒกแƒ˜แƒ›แƒแƒ แƒขแƒ˜แƒ•แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก, แƒแƒ› แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒ›แƒ˜แƒ”แƒชแƒ˜แƒ— แƒฎแƒแƒ–แƒ”แƒ‘แƒก แƒ˜แƒ’แƒ˜แƒ•แƒ” แƒกแƒ˜แƒ’แƒ แƒซแƒ”), แƒ›แƒ˜แƒ•แƒ˜แƒฆแƒ”แƒ‘แƒ— แƒกแƒขแƒแƒœแƒ“แƒแƒ แƒขแƒฃแƒšแƒ˜ แƒขแƒ”แƒขแƒ แƒ˜แƒกแƒ˜แƒก แƒœแƒแƒญแƒ แƒ”แƒ‘แƒ˜:

1) แƒคแƒแƒ˜แƒšแƒ˜ แƒ›แƒ—แƒšแƒ˜แƒแƒœแƒแƒ“ แƒ’แƒแƒ“แƒ›แƒแƒฌแƒ”แƒ แƒ˜แƒšแƒ˜แƒ แƒ“แƒ แƒกแƒแƒ‘แƒแƒšแƒแƒแƒ. แƒœแƒแƒฌแƒ˜แƒšแƒ˜แƒก แƒ–แƒแƒ›แƒ แƒฃแƒคแƒ แƒ แƒ“แƒ˜แƒ“แƒ˜แƒ, แƒ•แƒ˜แƒ“แƒ แƒ” แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒกแƒแƒ‘แƒแƒšแƒแƒ แƒ–แƒแƒ›แƒ:
PostgreSQL แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ AWS แƒฆแƒ แƒฃแƒ‘แƒšแƒ˜แƒ“แƒแƒœ

2) แƒคแƒแƒ˜แƒšแƒ˜ แƒ’แƒ แƒซแƒ”แƒšแƒ“แƒ”แƒ‘แƒ. แƒœแƒแƒฌแƒ˜แƒšแƒ˜แƒก แƒ–แƒแƒ›แƒ แƒฃแƒคแƒ แƒ แƒ›แƒชแƒ˜แƒ แƒ”แƒ แƒ•แƒ˜แƒ“แƒ แƒ” แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒกแƒแƒ‘แƒแƒšแƒแƒ แƒ–แƒแƒ›แƒ:
PostgreSQL แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ AWS แƒฆแƒ แƒฃแƒ‘แƒšแƒ˜แƒ“แƒแƒœ

3) แƒคแƒแƒ˜แƒšแƒ˜ แƒแƒ แƒ˜แƒก แƒฌแƒ˜แƒœแƒ แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒ’แƒแƒ’แƒ แƒซแƒ”แƒšแƒ”แƒ‘แƒ แƒ“แƒ แƒแƒฅแƒ•แƒก แƒ’แƒแƒ’แƒ แƒซแƒ”แƒšแƒ”แƒ‘แƒ. แƒœแƒแƒฌแƒ˜แƒšแƒ˜แƒก แƒ–แƒแƒ›แƒ แƒฃแƒคแƒ แƒ แƒ›แƒชแƒ˜แƒ แƒ”แƒ, แƒ•แƒ˜แƒ“แƒ แƒ” แƒกแƒแƒ‘แƒแƒšแƒแƒ แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒ“แƒแƒ แƒฉแƒ”แƒœแƒ˜แƒšแƒ˜ แƒ–แƒแƒ›แƒ:
PostgreSQL แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ AWS แƒฆแƒ แƒฃแƒ‘แƒšแƒ˜แƒ“แƒแƒœ

4) แƒคแƒแƒ˜แƒšแƒ˜ แƒแƒ แƒ˜แƒก แƒฌแƒ˜แƒœแƒ แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒ’แƒแƒ’แƒ แƒซแƒ”แƒšแƒ”แƒ‘แƒ แƒ“แƒ แƒแƒ แƒ˜แƒก แƒกแƒแƒ‘แƒแƒšแƒแƒ. แƒœแƒแƒฌแƒ˜แƒšแƒ˜แƒก แƒ–แƒแƒ›แƒ แƒฃแƒคแƒ แƒ แƒ“แƒ˜แƒ“แƒ˜แƒ, แƒ•แƒ˜แƒ“แƒ แƒ” แƒกแƒแƒ‘แƒแƒšแƒแƒ แƒคแƒแƒ˜แƒšแƒ˜แƒก แƒ“แƒแƒ แƒฉแƒ”แƒœแƒ˜แƒšแƒ˜ แƒ–แƒแƒ›แƒ:
PostgreSQL แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ AWS แƒฆแƒ แƒฃแƒ‘แƒšแƒ˜แƒ“แƒแƒœ

แƒแƒ›แƒแƒชแƒแƒœแƒแƒ แƒ›แƒแƒ แƒ—แƒ™แƒฃแƒ—แƒฎแƒ”แƒ“แƒ˜แƒก แƒแƒฌแƒงแƒแƒ‘แƒ แƒแƒœ แƒขแƒ”แƒขแƒ แƒ˜แƒกแƒ˜แƒก แƒแƒฎแƒแƒš แƒ“แƒแƒœแƒ”แƒ–แƒ” แƒ—แƒแƒ›แƒแƒจแƒ˜.
PostgreSQL แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ AWS แƒฆแƒ แƒฃแƒ‘แƒšแƒ˜แƒ“แƒแƒœ

แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ”แƒ‘แƒ˜, แƒ แƒแƒ›แƒšแƒ”แƒ‘แƒ˜แƒช แƒฌแƒแƒ แƒ›แƒแƒ˜แƒฅแƒ›แƒœแƒ”แƒ‘แƒ แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ˜แƒก แƒ’แƒแƒ“แƒแƒญแƒ แƒ˜แƒกแƒแƒก

1) แƒฌแƒ”แƒ‘แƒ 2 แƒชแƒแƒšแƒ˜ แƒกแƒขแƒ แƒ˜แƒฅแƒแƒœแƒ˜

PostgreSQL แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ AWS แƒฆแƒ แƒฃแƒ‘แƒšแƒ˜แƒ“แƒแƒœ
แƒ–แƒแƒ’แƒแƒ“แƒแƒ“, แƒ’แƒแƒœแƒกแƒแƒ™แƒฃแƒ—แƒ แƒ”แƒ‘แƒฃแƒšแƒ˜ แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ”แƒ‘แƒ˜ แƒแƒ  แƒงแƒแƒคแƒ˜แƒšแƒ. แƒกแƒขแƒแƒœแƒ“แƒแƒ แƒขแƒฃแƒšแƒ˜ แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ แƒกแƒแƒฌแƒงแƒ˜แƒกแƒ˜ แƒžแƒ แƒแƒ’แƒ แƒแƒ›แƒ˜แƒ แƒ”แƒ‘แƒ˜แƒก แƒ™แƒฃแƒ แƒกแƒ˜แƒ“แƒแƒœ.

แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒแƒžแƒขแƒ˜แƒ›แƒแƒšแƒฃแƒ แƒ˜ แƒ–แƒแƒ›แƒ

แƒ›แƒแƒ’แƒ แƒแƒ› แƒ”แƒก แƒชแƒแƒขแƒ แƒฃแƒคแƒ แƒ แƒกแƒแƒ˜แƒœแƒขแƒ”แƒ แƒ”แƒกแƒแƒ.
แƒกแƒแƒ›แƒฌแƒฃแƒฎแƒแƒ แƒแƒ“, แƒแƒ  แƒแƒ แƒกแƒ”แƒ‘แƒแƒ‘แƒก แƒแƒคแƒกแƒ”แƒขแƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒก แƒกแƒแƒจแƒฃแƒแƒšแƒ”แƒ‘แƒ แƒกแƒแƒฌแƒงแƒ˜แƒกแƒ˜ แƒœแƒแƒฌแƒ˜แƒšแƒ˜แƒก แƒ”แƒขแƒ˜แƒ™แƒ”แƒขแƒ˜แƒก แƒจแƒ”แƒ›แƒ“แƒ”แƒ’:

แƒ แƒแƒ’แƒแƒ แƒช แƒฃแƒ™แƒ•แƒ” แƒ˜แƒชแƒ˜แƒ—, แƒ•แƒแƒ แƒ˜แƒแƒœแƒขแƒ˜ โ€” starting-token แƒ’แƒแƒ›แƒแƒ˜แƒงแƒ”แƒœแƒ”แƒ‘แƒ แƒ˜แƒ›แƒ˜แƒก แƒ“แƒแƒกแƒแƒ–แƒฃแƒกแƒขแƒ”แƒ‘แƒšแƒแƒ“, แƒ—แƒฃ แƒกแƒแƒ“ แƒฃแƒœแƒ“แƒ แƒ“แƒแƒ˜แƒฌแƒงแƒแƒก แƒžแƒแƒ’แƒ˜แƒœแƒ˜แƒ แƒ”แƒ‘แƒ. แƒ”แƒก แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ˜ แƒ˜แƒฆแƒ”แƒ‘แƒก String แƒ›แƒœแƒ˜แƒจแƒ•แƒœแƒ”แƒšแƒแƒ‘แƒ”แƒ‘แƒก, แƒ แƒแƒช แƒœแƒ˜แƒจแƒœแƒแƒ•แƒก, แƒ แƒแƒ› แƒ—แƒฃ แƒ—แƒฅแƒ•แƒ”แƒœ แƒชแƒ“แƒ˜แƒšแƒแƒ‘แƒ— แƒ“แƒแƒแƒ›แƒแƒขแƒแƒ— แƒแƒคแƒกแƒ”แƒขแƒฃแƒ แƒ˜ แƒ›แƒœแƒ˜แƒจแƒ•แƒœแƒ”แƒšแƒแƒ‘แƒ Next 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.แƒจ

#!/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
  • แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒ‘แƒแƒ–แƒ˜แƒก ID: 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

แƒฉแƒ•แƒ”แƒœ แƒ•แƒ˜แƒฆแƒ”แƒ‘แƒ— แƒจแƒ”แƒ›แƒ“แƒ”แƒ’แƒ˜ แƒขแƒแƒ™แƒ”แƒœแƒ˜แƒก แƒšแƒ”แƒ˜แƒ‘แƒšแƒ˜แƒก แƒ›แƒœแƒ˜แƒจแƒ•แƒœแƒ”แƒšแƒแƒ‘แƒแƒก แƒ’แƒแƒ“แƒ›แƒแƒฌแƒ”แƒ แƒ˜แƒšแƒ˜ แƒคแƒแƒ˜แƒšแƒ˜แƒ“แƒแƒœ:

  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

แฒ แƒ แƒแƒ แƒ˜แƒก แƒจแƒ”แƒ›แƒ“แƒ”แƒ’แƒ˜?

แƒแƒกแƒ” แƒ แƒแƒ›, แƒžแƒ˜แƒ แƒ•แƒ”แƒšแƒ˜ แƒจแƒฃแƒแƒšแƒ”แƒ“แƒฃแƒ แƒ˜ แƒแƒ›แƒแƒชแƒแƒœแƒ - "แƒฉแƒแƒ›แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ”แƒ— แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒคแƒแƒ˜แƒšแƒ˜ แƒฆแƒ แƒฃแƒ‘แƒ”แƒšแƒ˜แƒ“แƒแƒœ" แƒ›แƒแƒ’แƒ•แƒแƒ แƒ”แƒ‘แƒฃแƒšแƒ˜แƒ. แƒ แƒ แƒ•แƒฃแƒงแƒแƒ— แƒฉแƒแƒ›แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒฃแƒš แƒŸแƒฃแƒ แƒœแƒแƒšแƒก?
แƒžแƒ˜แƒ แƒ•แƒ”แƒš แƒ แƒ˜แƒ’แƒจแƒ˜, แƒ—แƒฅแƒ•แƒ”แƒœ แƒฃแƒœแƒ“แƒ แƒ’แƒแƒแƒแƒœแƒแƒšแƒ˜แƒ–แƒแƒ— แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒคแƒแƒ˜แƒšแƒ˜ แƒ“แƒ แƒแƒ›แƒแƒ˜แƒฆแƒแƒ— แƒ›แƒ˜แƒกแƒ’แƒแƒœ แƒ แƒ”แƒแƒšแƒฃแƒ แƒ˜ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ”แƒ‘แƒ˜.
แƒแƒ›แƒแƒชแƒแƒœแƒ แƒแƒ  แƒแƒ แƒ˜แƒก แƒซแƒแƒšแƒ˜แƒแƒœ แƒ แƒ—แƒฃแƒšแƒ˜. แƒฃแƒ›แƒแƒ แƒขแƒ˜แƒ•แƒ”แƒกแƒ˜ bash แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒ˜ แƒกแƒแƒ™แƒ›แƒแƒแƒ“ แƒ™แƒแƒ แƒ’แƒแƒ“ แƒแƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒก แƒกแƒแƒฅแƒ›แƒ”แƒก.
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 - แƒจแƒ”แƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ˜แƒกแƒขแƒแƒ แƒ˜แƒ

แƒซแƒแƒšแƒ˜แƒแƒœ แƒกแƒแƒกแƒแƒ แƒ’แƒ”แƒ‘แƒšแƒแƒ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ˜แƒœแƒชแƒ˜แƒ“แƒ”แƒœแƒขแƒ˜แƒก แƒ›แƒแƒกแƒแƒ’แƒ•แƒแƒ แƒ”แƒ‘แƒšแƒแƒ“. แƒฏแƒ”แƒ  แƒ’แƒแƒ”แƒชแƒแƒœแƒ˜แƒ— แƒ˜แƒกแƒขแƒแƒ แƒ˜แƒแƒก - แƒ แƒแƒ“แƒ˜แƒก แƒ“แƒแƒ˜แƒฌแƒงแƒ แƒจแƒ”แƒœแƒ”แƒšแƒ”แƒ‘แƒ?
แƒจแƒ”แƒ›แƒ“แƒ”แƒ’, แƒ™แƒšแƒแƒกแƒ˜แƒ™แƒ˜แƒก แƒ›แƒ˜แƒฎแƒ”แƒ“แƒ•แƒ˜แƒ—, แƒ›แƒแƒซแƒ”แƒ‘แƒœแƒ”แƒ— แƒ’แƒแƒ แƒ”แƒ’แƒแƒœแƒ˜ แƒ›แƒ˜แƒ–แƒ”แƒ–แƒ”แƒ‘แƒ˜. แƒจแƒ”แƒกแƒแƒซแƒšแƒแƒ, แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒ‘แƒแƒ–แƒ˜แƒก แƒ“แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ แƒฃแƒ‘แƒ แƒแƒšแƒแƒ“ แƒ›แƒ™แƒ•แƒ”แƒ—แƒ แƒแƒ“ แƒ’แƒแƒ˜แƒ–แƒแƒ แƒ“แƒ แƒ“แƒ แƒ™แƒแƒœแƒ™แƒ แƒ”แƒขแƒฃแƒšแƒ˜ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ แƒแƒ แƒแƒคแƒ”แƒ  แƒจแƒฃแƒแƒจแƒ˜แƒ.
แƒ“แƒแƒแƒ›แƒแƒขแƒ”แƒ— แƒแƒฎแƒแƒšแƒ˜ แƒฉแƒแƒœแƒแƒฌแƒ”แƒ แƒ˜ 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 = 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 - แƒจแƒ”แƒ˜แƒœแƒแƒฎแƒ”แƒ— แƒจแƒ”แƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ’แƒ”แƒ’แƒ›แƒ”แƒ‘แƒ˜

แƒแƒ› แƒ“แƒ แƒแƒก แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒฌแƒแƒ แƒ›แƒแƒ˜แƒจแƒ•แƒแƒก แƒžแƒ แƒแƒขแƒ”แƒกแƒขแƒ˜-แƒ’แƒแƒœแƒ›แƒแƒ แƒขแƒ”แƒ‘แƒ-แƒ™แƒแƒ›แƒ”แƒœแƒขแƒแƒ แƒ˜: โ€žแƒ›แƒแƒ’แƒ แƒแƒ› แƒฃแƒ™แƒ•แƒ” แƒแƒ แƒกแƒ”แƒ‘แƒแƒ‘แƒก แƒแƒ•แƒขแƒแƒ›แƒแƒขแƒฃแƒ แƒ˜ แƒแƒฎแƒกแƒœแƒ" แƒ“แƒ˜แƒแƒฎ, แƒแƒ แƒกแƒ”แƒ‘แƒแƒ‘แƒก, แƒ›แƒแƒ’แƒ แƒแƒ› แƒ แƒ แƒแƒ–แƒ แƒ˜ แƒแƒฅแƒ•แƒก, แƒ—แƒฃ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ’แƒ”แƒ’แƒ›แƒ แƒ˜แƒœแƒแƒฎแƒ”แƒ‘แƒ แƒ˜แƒ›แƒแƒ•แƒ” log แƒคแƒแƒ˜แƒšแƒจแƒ˜ แƒ“แƒ แƒจแƒ”แƒ›แƒ“แƒ’แƒแƒ›แƒ˜ แƒแƒœแƒแƒšแƒ˜แƒ–แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก แƒจแƒ”แƒกแƒแƒœแƒแƒฎแƒแƒ“, แƒ—แƒฅแƒ•แƒ”แƒœ แƒฃแƒœแƒ“แƒ แƒ’แƒแƒแƒแƒœแƒแƒšแƒ˜แƒ–แƒแƒ— log แƒคแƒแƒ˜แƒšแƒ˜?

แƒ แƒแƒช แƒ›แƒญแƒ˜แƒ แƒ“แƒ”แƒ‘แƒแƒ“แƒ แƒ˜แƒงแƒ:
แƒžแƒ˜แƒ แƒ•แƒ”แƒšแƒ˜: แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ’แƒ”แƒ’แƒ›แƒ˜แƒก แƒจแƒ”แƒœแƒแƒฎแƒ•แƒ แƒ›แƒแƒœแƒ˜แƒขแƒแƒ แƒ˜แƒœแƒ’แƒ˜แƒก แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ—แƒ แƒ‘แƒแƒ–แƒ˜แƒก แƒกแƒ”แƒ แƒ•แƒ˜แƒก แƒชแƒฎแƒ แƒ˜แƒšแƒจแƒ˜;
แƒ›แƒ”แƒแƒ แƒ”: แƒจแƒ”แƒซแƒšแƒแƒœ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ’แƒ”แƒ’แƒ›แƒ”แƒ‘แƒ˜แƒก แƒ”แƒ แƒ—แƒ›แƒแƒœแƒ”แƒ—แƒ—แƒแƒœ แƒจแƒ”แƒ“แƒแƒ แƒ”แƒ‘แƒ, แƒ แƒแƒ—แƒ แƒ“แƒแƒฃแƒงแƒแƒ•แƒœแƒ”แƒ‘แƒšแƒ˜แƒ• แƒ“แƒแƒ˜แƒœแƒแƒฎแƒแƒœ, แƒ แƒแƒ› แƒจแƒ”แƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ’แƒ”แƒ’แƒ›แƒ แƒจแƒ”แƒ˜แƒชแƒ•แƒแƒšแƒ.

แƒแƒ แƒกแƒ”แƒ‘แƒแƒ‘แƒก แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ แƒ™แƒแƒœแƒ™แƒ แƒ”แƒขแƒฃแƒšแƒ˜ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ”แƒ‘แƒ˜แƒ—. แƒ›แƒ˜แƒกแƒ˜ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ’แƒ”แƒ’แƒ›แƒ˜แƒก แƒ›แƒ˜แƒฆแƒ”แƒ‘แƒ แƒ“แƒ แƒจแƒ”แƒœแƒแƒฎแƒ•แƒ 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 - แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ˜แƒก แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ แƒ›แƒแƒœแƒ˜แƒขแƒแƒ แƒ˜แƒœแƒ’แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก

แƒ•แƒ˜แƒœแƒแƒ˜แƒ“แƒแƒœ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ›แƒ”แƒขแƒ แƒ˜แƒ™แƒ แƒ™แƒแƒœแƒคแƒ˜แƒ’แƒฃแƒ แƒ˜แƒ แƒ”แƒ‘แƒฃแƒšแƒ˜แƒ แƒแƒ แƒ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ˜แƒก แƒขแƒ”แƒฅแƒกแƒขแƒ–แƒ”, แƒแƒ แƒแƒ›แƒ”แƒ“ แƒ›แƒ˜แƒก ID-แƒ–แƒ”, แƒ—แƒฅแƒ•แƒ”แƒœ แƒฃแƒœแƒ“แƒ แƒ“แƒแƒแƒ™แƒแƒ•แƒจแƒ˜แƒ แƒแƒ— แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ”แƒ‘แƒ˜ แƒŸแƒฃแƒ แƒœแƒแƒšแƒ˜แƒก แƒคแƒแƒ˜แƒšแƒ˜แƒ“แƒแƒœ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ”แƒ‘แƒ—แƒแƒœ, แƒ แƒแƒ›แƒšแƒ”แƒ‘แƒ˜แƒกแƒ—แƒ•แƒ˜แƒกแƒแƒช แƒแƒ แƒ˜แƒก แƒ™แƒแƒœแƒคแƒ˜แƒ’แƒฃแƒ แƒ˜แƒ แƒ”แƒ‘แƒฃแƒšแƒ˜ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ›แƒ”แƒขแƒ แƒ˜แƒ™แƒ.
แƒ˜แƒกแƒ”, แƒงแƒแƒ•แƒ”แƒš แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒ˜แƒ›แƒ˜แƒกแƒแƒ—แƒ•แƒ˜แƒก, แƒ แƒแƒ› แƒ’แƒฅแƒแƒœแƒ“แƒ”แƒ— แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ˜แƒœแƒชแƒ˜แƒ“แƒ”แƒœแƒขแƒ˜แƒก แƒ“แƒแƒ“แƒ’แƒแƒ›แƒ˜แƒก แƒ–แƒฃแƒกแƒขแƒ˜ แƒ“แƒ แƒ.

แƒแƒ› แƒ’แƒ–แƒ˜แƒ—, แƒ แƒแƒ“แƒ”แƒกแƒแƒช แƒฎแƒ“แƒ”แƒ‘แƒ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ˜แƒœแƒชแƒ˜แƒ“แƒ”แƒœแƒขแƒ˜ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ˜แƒก ID-แƒกแƒ—แƒ•แƒ˜แƒก, แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ แƒ‘แƒ›แƒฃแƒšแƒ˜ แƒ™แƒแƒœแƒ™แƒ แƒ”แƒขแƒฃแƒš แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒแƒกแƒ—แƒแƒœ แƒ™แƒแƒœแƒ™แƒ แƒ”แƒขแƒฃแƒšแƒ˜ แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ˜แƒก แƒ›แƒœแƒ˜แƒจแƒ•แƒœแƒ”แƒšแƒแƒ‘แƒ”แƒ‘แƒ˜แƒ— แƒ“แƒ แƒ–แƒฃแƒกแƒขแƒ˜ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ“แƒ แƒ แƒ“แƒ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ˜แƒก แƒฎแƒแƒœแƒ’แƒ แƒซแƒšแƒ˜แƒ•แƒแƒ‘แƒ. แƒ›แƒ˜แƒ˜แƒฆแƒ”แƒ— แƒ”แƒก แƒ˜แƒœแƒคแƒแƒ แƒ›แƒแƒชแƒ˜แƒ แƒ›แƒฎแƒแƒšแƒแƒ“ แƒฎแƒ”แƒ“แƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒ— pg_stat_statements - แƒแƒ™แƒ แƒซแƒแƒšแƒฃแƒšแƒ˜แƒ.
แƒ˜แƒžแƒแƒ•แƒ”แƒ— แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ˜แƒก แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ แƒ“แƒ แƒ’แƒแƒœแƒแƒแƒฎแƒšแƒ”แƒ— แƒฉแƒแƒœแƒแƒฌแƒ”แƒ แƒ˜ 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 ;

Afterword

แƒแƒฆแƒฌแƒ”แƒ แƒ˜แƒšแƒ›แƒ แƒขแƒ”แƒฅแƒœแƒ˜แƒ™แƒแƒ› แƒกแƒแƒ‘แƒแƒšแƒแƒแƒ“ แƒ˜แƒžแƒแƒ•แƒ แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ แƒจแƒ”แƒ›แƒฃแƒจแƒแƒ•แƒ”แƒ‘แƒฃแƒšแƒ˜ PostgreSQL แƒจแƒ”แƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒก แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ›แƒแƒœแƒ˜แƒขแƒแƒ แƒ˜แƒœแƒ’แƒ˜แƒก แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒ, แƒ แƒแƒช แƒกแƒแƒจแƒฃแƒแƒšแƒ”แƒ‘แƒแƒก แƒ›แƒแƒ’แƒชแƒ”แƒ›แƒ— แƒ’แƒฅแƒแƒœแƒ“แƒ”แƒ— แƒ›แƒ”แƒขแƒ˜ แƒ˜แƒœแƒคแƒแƒ แƒ›แƒแƒชแƒ˜แƒ แƒ’แƒแƒกแƒแƒแƒœแƒแƒšแƒ˜แƒ–แƒ”แƒ‘แƒšแƒแƒ“ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ˜แƒก แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ˜แƒก แƒ˜แƒœแƒชแƒ˜แƒ“แƒ”แƒœแƒขแƒ”แƒ‘แƒ˜แƒก แƒแƒ›แƒแƒฎแƒกแƒœแƒ˜แƒกแƒแƒก.

แƒ—แƒฃแƒ›แƒชแƒ, แƒ แƒ แƒ—แƒฅแƒ›แƒ แƒฃแƒœแƒ“แƒ, แƒฉแƒ”แƒ›แƒ˜ แƒžแƒ˜แƒ แƒแƒ“แƒ˜ แƒแƒ–แƒ แƒ˜แƒ—, แƒกแƒแƒญแƒ˜แƒ แƒ แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ แƒ›แƒ”แƒขแƒ˜ แƒ›แƒฃแƒจแƒแƒแƒ‘แƒ แƒฉแƒแƒ›แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒฃแƒšแƒ˜ แƒœแƒแƒฌแƒ˜แƒšแƒ˜แƒก แƒแƒ แƒฉแƒ”แƒ•แƒ˜แƒกแƒ แƒ“แƒ แƒ–แƒแƒ›แƒ˜แƒก แƒจแƒ”แƒชแƒ•แƒšแƒ˜แƒก แƒแƒšแƒ’แƒแƒ แƒ˜แƒ—แƒ›แƒ–แƒ”. แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ แƒ–แƒแƒ’แƒแƒ“ แƒกแƒแƒฅแƒ›แƒ”แƒจแƒ˜ แƒฏแƒ”แƒ  แƒแƒ  แƒ›แƒแƒ’แƒ•แƒแƒ แƒ”แƒ‘แƒฃแƒšแƒ. แƒแƒšแƒ‘แƒแƒ— แƒกแƒแƒ˜แƒœแƒขแƒ”แƒ แƒ”แƒกแƒ แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ.

แƒ›แƒแƒ’แƒ แƒแƒ› แƒ”แƒก แƒกแƒฃแƒš แƒกแƒฎแƒ•แƒ แƒแƒ›แƒ‘แƒแƒ•แƒ˜แƒ...

แƒฌแƒงแƒแƒ แƒ: www.habr.com

แƒแƒฎแƒแƒšแƒ˜ แƒ™แƒแƒ›แƒ”แƒœแƒขแƒแƒ แƒ˜แƒก แƒ“แƒแƒ›แƒแƒขแƒ”แƒ‘แƒ