]> Untitled Git - articles.git/commitdiff
Поправил немного, добавил забытый раздел
authorNikolay Shaplov <dhyan@nataraj.su>
Mon, 6 Jul 2026 13:19:14 +0000 (16:19 +0300)
committerNikolay Shaplov <dhyan@nataraj.su>
Mon, 6 Jul 2026 13:19:14 +0000 (16:19 +0300)
SDL/2025-04 Taint-анализ Ñ\81Ñ\80едÑ\81Ñ\82вами Natch. Ð\97накомÑ\81Ñ\82во Ñ\81 инÑ\81Ñ\82Ñ\80Ñ\83менÑ\82ом на небаналÑ\8cнÑ\8bÑ\85 пÑ\80имеÑ\80аÑ\85/3. PostgreSQL.imgs/callstack_out.png [new file with mode: 0644]
SDL/2025-04 Taint-анализ Ñ\81Ñ\80едÑ\81Ñ\82вами Natch. Ð\97накомÑ\81Ñ\82во Ñ\81 инÑ\81Ñ\82Ñ\80Ñ\83менÑ\82ом на небаналÑ\8cнÑ\8bÑ\85 пÑ\80имеÑ\80аÑ\85/3. PostgreSQL.md

diff --git a/SDL/2025-04 Taint-анализ Ñ\81Ñ\80едÑ\81Ñ\82вами Natch. Ð\97накомÑ\81Ñ\82во Ñ\81 инÑ\81Ñ\82Ñ\80Ñ\83менÑ\82ом на небаналÑ\8cнÑ\8bÑ\85 пÑ\80имеÑ\80аÑ\85/3. PostgreSQL.imgs/callstack_out.png b/SDL/2025-04 Taint-анализ Ñ\81Ñ\80едÑ\81Ñ\82вами Natch. Ð\97накомÑ\81Ñ\82во Ñ\81 инÑ\81Ñ\82Ñ\80Ñ\83менÑ\82ом на небаналÑ\8cнÑ\8bÑ\85 пÑ\80имеÑ\80аÑ\85/3. PostgreSQL.imgs/callstack_out.png
new file mode 100644 (file)
index 0000000..04d84e5
Binary files /dev/null and "b/SDL/2025-04 Taint-\320\260\320\275\320\260\320\273\320\270\320\267 \321\201\321\200\320\265\320\264\321\201\321\202\320\262\320\260\320\274\320\270 Natch. \320\227\320\275\320\260\320\272\320\276\320\274\321\201\321\202\320\262\320\276 \321\201 \320\270\320\275\321\201\321\202\321\200\321\203\320\274\320\265\320\275\321\202\320\276\320\274 \320\275\320\260 \320\275\320\265\320\261\320\260\320\275\320\260\320\273\321\214\320\275\321\213\321\205 \320\277\321\200\320\270\320\274\320\265\321\200\320\260\321\205/3. PostgreSQL.imgs/callstack_out.png" differ
index 4c199cb584b2eb7615f27907eb0948a29a7e57ac..2274768b310bdea345dd0b22a886ac9172d7144f 100644 (file)
@@ -1,17 +1,18 @@
 ## PostgreSQL
 
 PostgreSQL -- мощная современная СУБД со свободным и открытым исходным кодом.
-В отличие от предыдущих двух исследуемых проектов то как устроен внутри себя PostgreSQL я знаю не по наслышке.
-Поэтому у нас будет возможность сравнить результаты которые покажет Natch с фактическим знанием о том как распространяются данные через подсистемы проекта
+В отличие от предыдущих двух исследуемых проектов, то, как устроен внутри себя PostgreSQL, я знаю не понаслышке.
+Поэтому у нас будет возможность сравнить результаты которые покажет Natch с фактическим знанием о том, как распространяются данные через подсистемы проекта.
+
 В PostgreSQL поддерживаются различные сложные, составные, типы данных.
 В рамках данного исследования предлагается взять строковое представление одного их таких типов данных и проследить как строковые константы из этого типа перейдут из текстового представление в представление внутреннее и как это внутреннее представление будет сохранено на диск.
 
 ### План эксперимента
 
-* Соберем PostgreSQL с отладочной информацией
-* В качестве исследуемого типа данных, выберем тип данных `[tsvector](https://www.postgresql.org/docs/current/datatype-textsearch.html)`, так как он с одной стороны содержит в себе набор отдельных строковых констант, за которыми будет удобно наблюдать в режиме помеченных данных, а с другой стороны тип данных сам по себе не является излишне сложным.
-* Сохраним строковое представление константы типа `tsvector` в отдельный файл. Данные из этого файла в нашем эксперименте Natch будет отслеживать как "помеченные"
-* Напишем несложный скрипт заворачивающий строку из вышеупомянутого файла в SQL-запрос осуществляющий вставку константы типа `tsvector` в ранее созданную таблицу
+* Соберем PostgreSQL с отладочной информацией;
+* В качестве исследуемого типа данных, выберем тип данных [`tsvector`](https://www.postgresql.org/docs/current/datatype-textsearch.html), так как он с одной стороны содержит в себе набор отдельных строковых констант, за которыми будет удобно наблюдать в режиме помеченных данных, а с другой стороны тип данных сам по себе не является излишне сложным;
+* Для проведения эксперимента сохраним строковое представление константы типа `tsvector` в отдельный файл. Данные из этого файла в нашем эксперименте Natch будет отслеживать как "помеченные";
+* Напишем несложный скрипт заворачивающий строку из вышеупомянутого файла в SQL-запрос осуществляющий вставку константы типа `tsvector` в ранее созданную таблицу;
 * Под контролем Natch, запустим вышеупомянутый скрипт, осуществим вставку, после чего дадим команду `CHECKPOINT`, чтобы принудить postgres сбросить все закешированные страницы хранилища на диск.
 
 ### Сборка и установка
@@ -36,9 +37,11 @@ $ sudo apt-get install libicu-dev bison flex libreadline-dev zlib1g-dev
 
 #### Получение исходников
 
+Для проведения эксперимента используем текущую стабильную ветку PostgreSQL 17.
 ```bash
 $ git clone  https://git.postgresql.org/git/postgresql.git -b REL_17_STABLE ~/postgres/REL_17_STABLE
 ```
+На момент проведения эксперимента, последний минорный релиз ветки был 17.4, векта находилась на коммите `03faf38`.
 
 
 #### Сборка и установка
@@ -191,7 +194,7 @@ DELETE FROM test;
   - Переходим в каталог с нашей скриптовой обвязкой: `cd ~/postgres/.install/REL_17_STABLE-scripts`;
   - Запускаем нашу сборку PostgreSQL: `./restart.sh`;
 - В консоли Natch делаем первый снапшот (см. штатный tutorial);
-  - Запускаем команду вставки помеченных данных в базу: `echo INSERT INTO test VALUES \( \'`cat IN`\'::tsvector\) | ./psql_con.sh`
+  - Запускаем команду вставки помеченных данных в базу: ``echo INSERT INTO test VALUES \( \'`cat IN`\'::tsvector\) | ./psql_con.sh``
   - Запускаем утилиту `psql` в командно-строчном режиме: `./psql.sh`;
     - Даем в ней команду `CHECKPOINT;` для гарантированного сброса страничного кеша на диск;
     - Получаем содержимое таблицы `test` выполнив запрос: `SELECT * FROM test;`;
@@ -232,12 +235,12 @@ DELETE FROM test;
 
 В процессе получения запроса вставки принимает участие и процесс `postgresql`
 
-![...](3. PostgreSQL.imgs/in_postgres_resoruces.png)
+![...](3. PostgreSQL.imgs/in_postgres_resources.png)
 
 На картинке выше мы видим что процесс обменивается помеченными данными через unix сокет (спойлер: он их чиатет) и кроме этого производит запись этих данных на диск (об этом ниже).
 
 Данные принимаемые процессом `postgres` полностью (что неудивительно) совпадают с данными которые отправлял процесс `psql`, с точностью до направления движения данных.
-То что `psql` писал `postgres` читает.
+То что `psql` писал, `postgres` читает.
 
 ![...](3. PostgreSQL.imgs/in_postgres_unix-read.png)
 
@@ -264,7 +267,7 @@ DELETE FROM test;
 
 ##### Вывод `postgres`
 
-В процессе `postgres` обмен данными через unix-сокет ожидаемо происходит полностью аналогично с `pslq`, с точностью до направления:
+В процессе `postgres` обмен данными через unix-сокет ожидаемо происходит полностью аналогично с `pslq`, с точностью до направления движения данных:
 
 ![...](3. PostgreSQL.imgs/out_postgres_resources.png)
 
@@ -273,7 +276,8 @@ DELETE FROM test;
 #### Запись на диск
 
 С точки зрения операций чтения/записи помеченные данные должны быть записаны на диск дважды.
-Первый раз в момент фиксации изменений, вносимая правка должна быть записана в т.н. Write Ahead Log (WAL), файл содержащий все последние изменения данных в базе, по которому в случае аварии данные базы могут быть восстановлены до актуального состояние.
+Первый раз в момент фиксации изменений, вносимая правка должна быть записана в т.н. Write Ahead Log (WAL).
+WAL -- файл содержащий все последние изменения данных в базе, по которому в случае аварии данные базы могут быть восстановлены до актуального состояние.
 Второй раз, данные будут записаны в хранилище в котором они будут храниться на постоянной основе.
 Гарантированной записи в хранилище мы и добивались передавая базе данных команду `CHECKPOINT`.
 
@@ -282,7 +286,7 @@ DELETE FROM test;
 Запись WAL  происходит в процессе выполнения транзакции.
 Поэтому запись в WAL мы уже видели в том процессе `postgres` который принимал запрос на вставку помеченных данных:
 
-![...](3. PostgreSQL.imgs/in_postgres_resoruces.png)
+![...](3. PostgreSQL.imgs/in_postgres_resources.png)
 
 Можем теперь посмотреть на то, какие данные были в него записаны, и как в этом случае выглядят наши помеченные данные:
 
@@ -332,7 +336,7 @@ DELETE FROM test;
 
 ![...](3. PostgreSQL.imgs/callstack_in_1.png)
 
-На этом скриншоте мы видим как помеченные данные попадают в backed вместе с запросом, проходят предварительную проверку и после чего производится синтаксический разбор самих помеченных данных.
+На этом скриншоте мы видим как помеченные данные попадают в backed вместе с запросом, проходят предварительную проверку и после чего производится синтаксический разбор запроса.
 Сами помеченные данные при этом никак отдельно не обрабатываются, только туда-сюда копируются и принимают участие в других групповых операциях.
 
 За синтаксическим разбором следует разбор константных аргументов входящих в состав запроса.
@@ -354,7 +358,21 @@ DELETE FROM test;
 Тут тоже помеченные данные просто копируются из одного места в другое
 
 И в третьей, последней подветке происходит запись произведенных изменений в WAL-лог (`XLogInsert`).
-Помеченные данные принимают участие в вычислении контрольной суммы, и копируются вместе со всей остальной дельтой произошедшей во время транзакции.
+Помеченные данные принимают участие в вычислении контрольной суммы, и копируются вместе со всей остальнойдельтой изменений произошедших во время транзакции.
+
+##### Стек вызовов процесса `postgres`, вывод
+
+Вывод помеченных данных из базы данных обратно в терминал производится в отдельном backend-процессе (мы для вывода установили нов:ое соединение и оно обслуживается новым процессом)
+
+![...](3. PostgreSQL.imgs/callstack_out.png)
+
+Согласно дереву вызовов чтение из БД устроено заметно проще чем запись.
+На скриншоте мы наблюдаем ту же последовательность обработки входящего запроса, что была выше, только в этом случае при обработке этого запроса работы с помеченным данными не происходит (помеченные данные уже в хранилище БД, а не в запросе).
+Помеченные данные появляются в нашем графе вызовов только в момент их приведение к человекочитаемому виду в функции `tsvectorout`.
+Далее за преобразованием следует отправка полученного результата в сокет, на стандартный вывод.
+
+Глядя на это дерево вызовов, стоит отметить крайне эффективное использование данных их страничного кэша.
+Ни на одном этапе выполнения запроса выводимые данные во внутреннем представлении никуда не копируются, `tsvectorout` судя по всему принимает на вход значение прямо из страничного кэша, без каких либо предварительных перемещений данных в памяти.
 
 ### Итог