αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡αž€αŸ†αžŽαžαŸ‹αž αŸαžαž» PostgreSQL αž–αžΈαž–αž–αž€ AWS

ឬ tetrisology αž’αž“αž»αžœαžαŸ’αžαžαž·αž…αžαž½αž…αŸ”
αž’αŸ’αžœαžΈβ€‹αžŠαŸ‚αž›β€‹αžαŸ’αž˜αžΈβ€‹αž‚αžΊβ€‹αž›αŸ’αž’β€‹αž”αŸ†αž—αŸ’αž›αŸαž…β€‹αž…αŸ„αž›β€‹αžšαž”αžŸαŸ‹β€‹αž…αžΆαžŸαŸ‹β€‹αŸ”
Epigraphs αŸ”
αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡αž€αŸ†αžŽαžαŸ‹αž αŸαžαž» PostgreSQL αž–αžΈαž–αž–αž€ AWS

αž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž”αž‰αŸ’αž αžΆ

αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž‘αžΆαž‰αž™αž€αž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αž αŸαžαž» PostgreSQL αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž–αžΈ AWS cloud αž‡αžΆαž‘αŸ€αž„αž‘αžΆαžαŸ‹αž‘αŸ…αž€αžΆαž“αŸ‹αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“ Linux αž€αŸ’αž“αž»αž„αžαŸ†αž”αž“αŸ‹αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ” αž˜αž·αž“β€‹αž˜αŸ‚αž“β€‹αž“αŸ…β€‹αž€αŸ’αž“αž»αž„β€‹αž–αŸαž›β€‹αž–αž·αžβ€‹αž”αŸ’αžšαžΆαž€αžŠβ€‹αž‘αŸ αž”αŸ‰αž»αž“αŸ’αžαŸ‚β€‹αžŸαžΌαž˜β€‹αž“αž·αž™αžΆαž™β€‹αžαžΆβ€‹αž“αžΉαž„β€‹αž˜αžΆαž“β€‹αž€αžΆαžšβ€‹αž–αž“αŸ’αž™αžΆαžšβ€‹αž–αŸαž›β€‹αž”αž“αŸ’αžαž·αž…αŸ”
αžšαž™αŸˆαž–αŸαž›αž‘αžΆαž‰αž™αž€αž€αžΆαžšαž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αž‚αžΊ 5 αž“αžΆαž‘αžΈαŸ”
αž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αž€αŸ’αž“αž»αž„ AWS αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αžœαž·αž›αžšαŸ€αž„αžšαžΆαž›αŸ‹αž˜αŸ‰αŸ„αž„αŸ”

αž§αž”αž€αžšαžŽαŸαžŠαŸ‚αž›αž”αžΆαž“αž”αŸ’αžšαžΎ

αžŠαžΎαž˜αŸ’αž”αžΈαž‘αžΆαž‰αž™αž€αž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αž‘αŸ…αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“ αžŸαŸ’αž‚αŸ’αžšαžΈαž” bash αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαžŠαŸ‚αž›αž αŸ… AWS API "aws rds download-db-log-file-portion"αŸ”

αž”αŸ‰αžΆαžšαŸ‰αžΆαž˜αŸ‰αŸ‚αžαŸ’αžšαŸ–

  • -db-instance-identifier: AWS instance name;
  • --log-file-name: αžˆαŸ’αž˜αŸ„αŸ‡αž“αŸƒαž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αžŠαŸ‚αž›αž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“
  • --max-itemαŸ– αž…αŸ†αž“αž½αž“αžŸαžšαž»αž”αž“αŸƒαž’αžΆαžαž»αžŠαŸ‚αž›αž”αžΆαž“αžαŸ’αžšαž‘αž”αŸ‹αž˜αž€αžœαž·αž‰αž“αŸ…αž€αŸ’αž“αž»αž„αž›αž‘αŸ’αž’αž•αž›αž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαŸ”αž‘αŸ†αž αŸ†αž•αŸ’αž“αŸ‚αž€αž“αŸƒαž―αž€αžŸαžΆαžšαžŠαŸ‚αž›αž”αžΆαž“αž‘αžΆαž‰αž™αž€αŸ”
  • --starting-tokenαŸ– αž“αž·αž˜αž·αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜

αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž–αž·αžŸαŸαžŸαž“αŸαŸ‡ αž—αžΆαžšαž€αž·αž…αŸ’αž…αž“αŸƒαž€αžΆαžšαž•αŸ’αž‘αž»αž€αž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αž”αžΆαž“αž€αžΎαžαž‘αžΎαž„αž€αŸ†αž‘αž»αž„αž–αŸαž›αž’αŸ’αžœαžΎαž€αžΆαžšαž›αžΎ αžαžΆαž˜αžŠαžΆαž“αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαžŸαŸ†αžŽαž½αžš PostgreSQL αŸ”

αž αžΎαž™αžœαžΆαžŸαžΆαž˜αž‰αŸ’αž‰ - αž€αž·αž…αŸ’αž…αž€αžΆαžšαž‚αž½αžšαž±αŸ’αž™αž…αžΆαž”αŸ‹αž’αžΆαžšαž˜αŸ’αž˜αžŽαŸαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž”αžŽαŸ’αžαž»αŸ‡αž”αžŽαŸ’αžαžΆαž› αž“αž·αž„αž—αžΆαž–αžαž»αžŸαž‚αŸ’αž“αžΆαž€αŸ’αž“αž»αž„αž’αŸ†αž‘αž»αž„αž–αŸαž›αž˜αŸ‰αŸ„αž„αž’αŸ’αžœαžΎαž€αžΆαžšαŸ”
αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αžŸαž“αŸ’αž˜αžαžαžΆαž”αž‰αŸ’αž αžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžšαž½αž…αž αžΎαž™αžŠαŸ„αž™αžŸαžΆαžšαžαŸ‚αž‡αžΈαžœαž·αžαž”αŸ’αžšαž…αžΆαŸ†αžαŸ’αž„αŸƒαŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚ Google αžšαž αŸαžŸβ€‹αž˜αž·αž“β€‹αž”αžΆαž“β€‹αžŽαŸ‚αž“αžΆαŸ†β€‹αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™β€‹αžŽαžΆαž˜αž½αž™β€‹αž‘αžΎαž™ αž αžΎαž™β€‹αžαŸ’αž‰αž»αŸ†β€‹αž˜αž·αž“β€‹αž˜αžΆαž“β€‹αž”αŸ†αžŽαž„β€‹αž…αž„αŸ‹β€‹αžŸαŸ’αžœαŸ‚αž„β€‹αžšαž€β€‹αž±αŸ’αž™β€‹αž”αžΆαž“β€‹αžŸαŸŠαžΈβ€‹αž‡αž˜αŸ’αžšαŸ…β€‹αž”αž“αŸ’αžαŸ‚αž˜β€‹αž‘αŸ€αžβ€‹αž‘αŸαŸ” αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αžœαžΆαž‡αžΆαž€αžΆαžšαž αžΆαžαŸ‹αž”αŸ’αžšαžΆαžŽαžŠαŸαž›αŸ’αž’αŸ”

αž€αžΆαžšαžšαŸ€αž”αž…αŸ†αž‡αžΆαž•αŸ’αž›αžΌαžœαž€αžΆαžšαž“αŸƒαž—αžΆαžšαž€αž·αž…αŸ’αž…

αž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αž…αž»αž„αž€αŸ’αžšαŸ„αž™αž˜αžΆαž“αž”αž“αŸ’αž‘αžΆαžαŸ‹αž‡αžΆαž…αŸ’αžšαžΎαž“αž“αŸƒαž”αŸ’αžšαžœαŸ‚αž„αž’αžαŸαžšαŸ” αžαžΆαž˜αž€αŸ’αžšαžΆαž αŸ’αžœαž·αž€ αž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αžαŸ†αžŽαžΆαž„αž’αŸ’αžœαžΈαž˜αž½αž™αžŠαžΌαž…αž“αŸαŸ‡αŸ–
αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡αž€αŸ†αžŽαžαŸ‹αž αŸαžαž» PostgreSQL αž–αžΈαž–αž–αž€ AWS

αžαžΎαžœαžΆαžšαŸ†αž›αžΉαž€αž’αŸ’αž“αž€αž’αŸ†αž–αžΈαž’αŸ’αžœαžΈαž˜αž½αž™αž αžΎαž™αž¬αž“αŸ…? តើ Tetris αž‘αžΆαž€αŸ‹αž‘αž„αž’αŸ’αžœαžΈαž‡αžΆαž˜αž½αž™αžœαžΆ? αž αžΎαž™αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž’αŸ’αžœαžΈαžŠαŸ‚αž›αžœαžΆαžαŸ’αžšαžΌαžœαž’αŸ’αžœαžΎαž‡αžΆαž˜αž½αž™αžœαžΆαŸ”
αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž™αžΎαž„αžŸαŸ’αžšαž˜αŸƒαž˜αžΎαž›αž‡αž˜αŸ’αžšαžΎαžŸαžŠαŸ‚αž›αž’αžΆαž…αž€αžΎαžαž˜αžΆαž“αž“αŸ…αž–αŸαž›αž•αŸ’αž‘αž»αž€αž―αž€αžŸαžΆαžšαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž‡αžΆαž€αŸ’αžšαžΆαž αŸ’αžœαž·αž€ (αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž—αžΆαž–αžŸαžΆαž˜αž‰αŸ’αž‰ αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαž“αŸαŸ‡αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž”αž“αŸ’αž‘αžΆαžαŸ‹αž˜αžΆαž“αž”αŸ’αžšαžœαŸ‚αž„αžŠαžΌαž…αž‚αŸ’αž“αžΆ) αž™αžΎαž„αž‘αž‘αž½αž›αž”αžΆαž“ αž”αŸ†αžŽαŸ‚αž€ Tetris αžŸαŸ’αžαž„αŸ‹αžŠαžΆαžšαŸ–

1) αž―αž€αžŸαžΆαžšαžαŸ’αžšαžΌαžœαž”αžΆαž“αž‘αžΆαž‰αž™αž€αž‘αžΆαŸ†αž„αžŸαŸ’αžšαž»αž„ αž αžΎαž™αž‡αžΆαž―αž€αžŸαžΆαžšαž…αž»αž„αž€αŸ’αžšαŸ„αž™αŸ” αž‘αŸ†αž αŸ†αž•αŸ’αž“αŸ‚αž€αž‚αžΊαž’αŸ†αž‡αžΆαž„αž‘αŸ†αž αŸ†αž―αž€αžŸαžΆαžšαž…αž»αž„αž€αŸ’αžšαŸ„αž™αŸ–
αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡αž€αŸ†αžŽαžαŸ‹αž αŸαžαž» PostgreSQL αž–αžΈαž–αž–αž€ AWS

2) αž―αž€αžŸαžΆαžšαž”αž“αŸ’αžαŸ” αž‘αŸ†αž αŸ†αž€αŸ†αžŽαžΆαžαŸ‹αž‚αžΊαžαžΌαž…αž‡αžΆαž„αž‘αŸ†αž αŸ†αž―αž€αžŸαžΆαžšαž…αž»αž„αž€αŸ’αžšαŸ„αž™αŸ–
αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡αž€αŸ†αžŽαžαŸ‹αž αŸαžαž» PostgreSQL αž–αžΈαž–αž–αž€ AWS

3) αž―αž€αžŸαžΆαžšαž‚αžΊαž‡αžΆαž€αžΆαžšαž”αž“αŸ’αžαž“αŸƒαž―αž€αžŸαžΆαžšαž˜αž»αž“ αž“αž·αž„αž˜αžΆαž“αž€αžΆαžšαž”αž“αŸ’αžαŸ” αž‘αŸ†αž αŸ†αž€αŸ†αžŽαžΆαžαŸ‹αž‚αžΊαžαžΌαž…αž‡αžΆαž„αž‘αŸ†αž αŸ†αžŠαŸ‚αž›αž“αŸ…αžŸαž›αŸ‹αž“αŸƒαž―αž€αžŸαžΆαžšαž…αž»αž„αž€αŸ’αžšαŸ„αž™αŸ–
αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡αž€αŸ†αžŽαžαŸ‹αž αŸαžαž» PostgreSQL αž–αžΈαž–αž–αž€ AWS

4) αž―αž€αžŸαžΆαžšαž‚αžΊαž‡αžΆαž€αžΆαžšαž”αž“αŸ’αžαž“αŸƒαž―αž€αžŸαžΆαžšαž˜αž»αž“ αž“αž·αž„αž‡αžΆαž―αž€αžŸαžΆαžšαž…αž»αž„αž€αŸ’αžšαŸ„αž™αŸ” αž‘αŸ†αž αŸ†αž€αŸ†αžŽαžΆαžαŸ‹αž˜αžΆαž“αž‘αŸ†αž αŸ†αž’αŸ†αž‡αžΆαž„αž‘αŸ†αž αŸ†αžŠαŸ‚αž›αž“αŸ…αžŸαž›αŸ‹αž“αŸƒαž―αž€αžŸαžΆαžšαž…αž»αž„αž€αŸ’αžšαŸ„αž™αŸ–
αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡αž€αŸ†αžŽαžαŸ‹αž αŸαžαž» PostgreSQL αž–αžΈαž–αž–αž€ AWS

αž—αžΆαžšαž€αž·αž…αŸ’αž…αž‚αžΊαž”αŸ’αžšαž˜αžΌαž›αž•αŸ’αžαž»αŸ†αž…αžαž»αž€αŸ„αžŽαž€αŸ‚αž„αž¬αž›αŸαž„ Tetris αž“αŸ…αž›αžΎαž€αž˜αŸ’αžšαž·αžαžαŸ’αž˜αžΈαž˜αž½αž™αŸ”
αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡αž€αŸ†αžŽαžαŸ‹αž αŸαžαž» 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- эмпиричСским ΠΏΡƒΡ‚Π΅ΠΌ, ΠΏΠΎΠ΄ΠΎΠ±Ρ€Π°Π½Π½Ρ‹ΠΉ Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΏΠΎΡ€Ρ†ΠΈΠΈ.

αž’αžαŸ’αžαž”αž‘αžŸαŸ’αž‚αŸ’αžšαžΈαž”αž–αŸαž‰

αž‘αžΆαž‰αž™αž€_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

αž™αžΎαž„αž‘αž‘αž½αž›αž”αžΆαž“αžαž˜αŸ’αž›αŸƒαž“αŸƒαžŸαŸ’αž›αžΆαž€αžŸαž‰αŸ’αž‰αžΆαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž–αžΈαž―αž€αžŸαžΆαžšαžŠαŸ‚αž›αž”αžΆαž“αž‘αžΆαž‰αž™αž€αŸ–

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

αžαž˜αŸ’αž›αŸƒαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž”αž“αŸ’αžŸαŸ†αž‘αž‘αŸαž”αž˜αŸ’αžšαžΎαž‡αžΆαžŸαž‰αŸ’αž‰αžΆαž“αŸƒαž€αžΆαžšαž”αž‰αŸ’αž…αž”αŸ‹αž“αŸƒαž€αžΆαžšαž‘αžΆαž‰αž™αž€αŸ”

αž“αŸ…αž€αŸ’αž“αž»αž„αžšαž„αŸ’αžœαž·αž›αž‡αž»αŸ† αž™αžΎαž„αžšαžΆαž”αŸ‹αž•αŸ’αž“αŸ‚αž€αž“αŸƒαž―αž€αžŸαžΆαžš αžŠαŸ„αž™αž—αŸ’αž‡αžΆαž”αŸ‹αž”αž“αŸ’αž‘αžΆαžαŸ‹αž“αŸ…αžαžΆαž˜αž•αŸ’αž›αžΌαžœ αž“αž·αž„αž”αž„αŸ’αž€αžΎαž“αž‘αŸ†αž αŸ†αž“αŸƒαž•αŸ’αž“αŸ‚αž€αŸ–
αžšαž„αŸ’αžœαž·αž›αž‡αž»αŸ†αžŸαŸ†αžαžΆαž“αŸ‹

# 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 - αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž•αŸ‚αž“αž€αžΆαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αžŸαŸ†αžŽαž½αžš

αž“αŸ…αž…αŸ†αžŽαž»αž…αž“αŸαŸ‡ αž€αžΆαžšαž‡αŸ†αž‘αžΆαžŸαŸ‹-αž€αžΆαžšαž”αŸ†αž—αŸ’αž›αžΊ-αž€αžΆαžšαž”αž‰αŸ’αž…αŸαž‰αž˜αžαž·αž’αžΆαž…αž“αžΉαž„αž€αžΎαžαž‘αžΎαž„αŸ– "αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž˜αžΆαž“αž€αžΆαžšαž–αž“αŸ’αž™αž›αŸ‹αžŠαŸ„αž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αžšαž½αž…αž αžΎαž™" αž”αžΆαž‘ / αž…αžΆαžŸ αžœαžΆαž“αŸ…αž‘αžΈαž“αŸ„αŸ‡ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αžαžΎαž˜αžΆαž“αž’αŸ’αžœαžΈαž€αžΎαžαž‘αžΎαž„αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž•αŸ‚αž“αž€αžΆαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αž αŸαžαž»αžŠαžΌαž…αž‚αŸ’αž“αžΆ αž αžΎαž™αžŠαžΎαž˜αŸ’αž”αžΈαžšαž€αŸ’αžŸαžΆαž‘αž»αž€αžœαžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžœαž·αž—αžΆαž‚αž”αž“αŸ’αžαŸ‚αž˜ αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž‰αŸ‚αž€αž―αž€αžŸαžΆαžšαž€αŸ†αžŽαžαŸ‹αž αŸαžαž»?

αž’αŸ’αžœαžΈαžŠαŸ‚αž›αžαŸ’αž‰αž»αŸ†αžαŸ’αžšαžΌαžœαž€αžΆαžšαž‚αžΊαŸ–
αž‘αžΈαž˜αž½αž™αŸ– αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž•αŸ‚αž“αž€αžΆαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αŸ’αž“αž»αž„αžαžΆαžšαžΆαž„αžŸαŸαžœαžΆαž“αŸƒαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αŸ”
αž‘αžΈαž–αžΈαžšαŸ– αžŠαžΎαž˜αŸ’αž”αžΈαž’αžΆαž…αž”αŸ’αžšαŸ€αž”αž’αŸ€αž”αž•αŸ‚αž“αž€αžΆαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž‡αžΆαž˜αž½αž™αž‚αŸ’αž“αžΆ αžŠαžΎαž˜αŸ’αž”αžΈαž˜αžΎαž›αžƒαžΎαž‰αž—αŸ’αž›αžΆαž˜αŸ—αžαžΆαž•αŸ‚αž“αž€αžΆαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αžŸαŸ†αžŽαž½αžšαž”αžΆαž“αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαŸ”

αž˜αžΆαž“αžŸαŸ†αžŽαžΎαž‡αžΆαž˜αž½αž™αž”αŸ‰αžΆαžšαŸ‰αžΆαž˜αŸ‰αŸ‚αžαŸ’αžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αŸ” αž€αžΆαžšαž‘αž‘αž½αž›αž”αžΆαž“ αž“αž·αž„αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž•αŸ‚αž“αž€αžΆαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αžšαž”αžŸαŸ‹αžœαžΆαžŠαŸ„αž™αž”αŸ’αžšαžΎ EXPLAIN αž‚αžΊαž‡αžΆαž€αž·αž…αŸ’αž…αž€αžΆαžšαž”αž‹αž˜αŸ”
αž‡αžΆαž„αž“αŸαŸ‡αž‘αŸ…αž‘αŸ€αž αžŠαŸ„αž™αž”αŸ’αžšαžΎαž€αž“αŸ’αžŸαŸ„αž˜ EXPLAIN (COSTS FALSE) αž’αŸ’αž“αž€αž’αžΆαž…αž‘αž‘αž½αž›αž”αžΆαž“αž‚αŸ’αžšαŸ„αž„αž“αŸƒαž•αŸ‚αž“αž€αžΆαžš αžŠαŸ‚αž›αž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αŸ’αžšαžΎαžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž”αžΆαž“αžαž˜αŸ’αž›αŸƒ hash αž“αŸƒαž•αŸ‚αž“αž€αžΆαžš αžŠαŸ‚αž›αž“αžΉαž„αž‡αž½αž™αž€αŸ’αž“αž»αž„αž€αžΆαžšαžœαž·αž—αžΆαž‚αž‡αžΆαž”αž“αŸ’αžαž”αž“αŸ’αž‘αžΆαž”αŸ‹αž“αŸƒαž”αŸ’αžšαžœαžαŸ’αžαž·αž“αŸƒαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž“αŸ…αž€αŸ’αž“αž»αž„αž•αŸ‚αž“αž€αžΆαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αŸ”
αž‘αž‘αž½αž›αž”αžΆαž“αž‚αŸ†αžšαžΌαž•αŸ‚αž“αž€αžΆαžšαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·

  --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 - αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž αžΆαž˜αžƒαžΆαžαŸ‹αŸ”
αžŸαŸ’αžœαŸ‚αž„αžšαž€αžŸαŸ†αžŽαž½αžšαž“αŸƒαžŸαŸ†αžŽαžΎ αž“αž·αž„αž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αž’αžΆαžαž»αž“αŸ…αž€αŸ’αž“αž»αž„αžαžΆαžšαžΆαž„ 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

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹