From: Nikolay Shaplov Date: Mon, 6 Jul 2026 13:19:14 +0000 (+0300) Subject: Поправил немного, добавил забытый раздел X-Git-Url: http://gitweb.nataraj.world/?a=commitdiff_plain;h=c6e2437e91f18dce161b40cc7863b2e3a2ace89f;p=articles.git Поправил немного, добавил забытый раздел --- diff --git "a/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" "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" new file mode 100644 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 diff --git "a/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.md" "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.md" index 4c199cb..2274768 100644 --- "a/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.md" +++ "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.md" @@ -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` судя по всему принимает на вход значение прямо из страничного кэша, без каких либо предварительных перемещений данных в памяти. ### Итог