hacking postgresql. Обзор исходного кода

42
www.postgrespro.ru ОБЗОР ИСХОДНОГО КОДА Hacking PostgreSQL 17.03.2016

Upload: anastasia-lubennikova

Post on 23-Jan-2017

670 views

Category:

Data & Analytics


3 download

TRANSCRIPT

Page 1: Hacking PostgreSQL. Обзор исходного кода

www.postgrespro.ru

ОБЗОР ИСХОДНОГО КОДА

Hacking PostgreSQL

17.03.2016

Page 2: Hacking PostgreSQL. Обзор исходного кода

2

Содержание

1. Обзор source-tree1. Утилиты и скрипты

2. Backend flowchart

2. Пример

Page 3: Hacking PostgreSQL. Обзор исходного кода

3

postgres/

contrib – модули расширенийdoc – документация (SGML)src – ядро PostgreSQL...src/backend – сервер PostgreSQL ("Back-End")src/bin – psql, pg_dump, initdb, и т.д. ("Front-End")src/common – код, общий для front & backsrc/include – .h файлыsrc/interfaces – libpq, ecpgsrc/pl – процедурные языки (plpgsql, plperl, plpython, tcl)src/port – разные функции для портируемостиsrc/tools – инструменты для разработчиков (pgindent, и т.д.)

Page 4: Hacking PostgreSQL. Обзор исходного кода

4

src/binСерверные утилиты

initdb – инициализация нового кластера баз данных PostgreSQLpg_ctl – инициализация, запуск, останов и управление серверомpg_controldata – вывод свойств, установленных командой initdbpg_upgrade – обновление мажорной версии PostrgeSQLpg_archivecleanup – очистка архивных WAL файловpg_resetxlog – очистка журнала упреждающей записи и другой управляющей информацию кластера PostgreSQLpg_xlogdump – вывод WAL файлов в удобном для чтения форматеpg_test_timing – измерение timing оверхедаpg_rewind – синхронизация директорий PGDATA. Типичный сценарий – восстановить упавший мастер как реплику нового мастера.pg_test_fsync – определяет самый быстрый метод wal_sync_method для конкретной системы

Page 5: Hacking PostgreSQL. Обзор исходного кода

5

src/binКлиентские утилиты

psql – интерактивный терминалpgeventpg_dump – выгрузить базу данных PostgreSQL в формате скрипта в файл или архивpgbench – выполнение бенчмарковpg_basebackup – создать резервную копию кластера PostgreSQLpg_config – информация по конфигурационным параметрам развёрнутого кластера

BINDIR = /home/anastasia/projects/postgresql_bin/binCONFIGURE = '­­enable­debug' 'CFLAGS=­O0' '­­enable­depend' '­­enable­cassert' '­­prefix=/home/anastasia/projects/postgresql_bin/'

Page 6: Hacking PostgreSQL. Обзор исходного кода

6

src/bin/scriptsКлиентские скрипты

clusterdb -- кластеризовать базу данныхcreatedb -- создать базу данных createlang -- установить процедурный язык createuser -- создать новую учётную запись dropdb -- удалить базу данных droplang -- удалить процедурный язык dropuser -- удалить учётную запись пользователя

pg_isready -- проверить соединение с сервером reindexdb -- переиндексировать базу данных vacuumdb -- выполнить очистку и анализ базы данных

Page 7: Hacking PostgreSQL. Обзор исходного кода

7

src/backend

Page 8: Hacking PostgreSQL. Обзор исходного кода

8

src/backend

access - Методы доступа для разных структур данных (heap, btree indexes, gist, gin, brin…).bootstrap - режим первоначальной загрузкиcatalog - определения таблиц системного каталогасommands - DDL и служебные команды (ALTER, CREATE TABLE, VACUUM, ...)executor - выполнение запросовforeign - Foreign Data Wrappers, user mappings, etclib - разные функции “общего назначения”libpq - клиент-серверный протоколmain - основной процесс, передающий управление нужной подсистемеnodes - обобщенная структура “Node” и функции из сравнения, копирования и т.д.optimizer - оптимизатор запросов, реализует систему оценок стоимости и генерирует планparser - лексер и парсер, разбор текста запросовport - специфические функции для портированияpostmaster - основной процесс PostgreSQLregex - Henry Spencer's regex library, also used by TCL, maintained more-or-less by PG nowreplication – поддержка репликации, пересылка WAL-логов, чтение и т.д.rewrite - перезапись запросов с использованием правил (RULE)snowball - Snowball stemming, used with full-text searchstorage - уровень хранилища, ввод/вывод, поддержка LO.tcop - "Traffic Cop"- получение запросов и их обработкаtsearch - полнотекстовый поискutils - различные компоненты сервера, (кэш, управление памятью и т.д.)

Page 9: Hacking PostgreSQL. Обзор исходного кода

9

Page 10: Hacking PostgreSQL. Обзор исходного кода

10

Инициализация

bootstrapСоздание исходных баз через initdb. mainВыполняет первоначальный запуск некоторых подсистем (например error management и memory management), устанавливает информацию о локали. Проверяет различные флаги и передает управление процессу postmaster или postgres. postmasterКонтролирует запуск и остановку сервера postgres. Создает разделяемую память, а затем в цикле ждет запросов на подключение. Сразу после получения такого запроса порождает backend процесс postgres и передает управление ему.libpqBackend операции библиотеки libpq для взаимодействия с процессом клиента.

Page 11: Hacking PostgreSQL. Обзор исходного кода

11

initdb

src/bin/initdb/initdb.c – создание инстанса PostgreSQL.

Создание таблиц template0, template1 и postgres.

template0 – не изменяется после initdb

template1 – может содержать локальные данные

Page 12: Hacking PostgreSQL. Обзор исходного кода

12

bootstrap

BKI – Backend Interface.

src/backend/bootstrap/bootstrap.c – функции для работы в режиме инициализации кластера

pg_class, pg_attributes, pg_proc, pg_type – основные таблицы каталога.

src/include/catalog/genbki.pl – скрипт на Perl, который генерирует файл postgres.bki (и несколько других) из заголовочных файлов особого формата src/include/catalog/pg_*.

src/backend/catalog/postgres.bki – создание таблиц каталога, индексов и TOAST таблиц.

Page 13: Hacking PostgreSQL. Обзор исходного кода

13

src/backend/postmaster

autovacuum.c bgworker.cbgwriter.c checkpointer.cfork_process.cpgarch.cpgstat.cpostmaster.cstartup.c – выполняет запуск сервера и восстановление (recovery). syslogger.cwalwriter.c

Page 14: Hacking PostgreSQL. Обзор исходного кода

14

Глобальные переменные

src/backend/utils/init/globals.c – объявления глобальных переменных

src/backend/utils/init/postinit.c – функции для инициализации

Page 15: Hacking PostgreSQL. Обзор исходного кода

15

Клиент-серверный протокол

src/backend/libpq

● TCP/IP протокол● Документация● Версия 2.0 начиная с 6.4, в 1999● Версия 3.0 начиная с 7.4, в 2003● Новые возможности 3.0:

– расширенный протокол запросов– улучшения COPY

Page 16: Hacking PostgreSQL. Обзор исходного кода

16

Формат сообщений

Page 17: Hacking PostgreSQL. Обзор исходного кода

17

Формат передаваемых данных

src/backend/libpq/pqformat.c

● Бинарный или текстовый форматы● Для разных типов данных разный формат.● Не документирован (кроме кода).● int8send, int8recv● json_send, jsonb_send

Page 18: Hacking PostgreSQL. Обзор исходного кода

18

Простой запрос

Page 19: Hacking PostgreSQL. Обзор исходного кода

19

Асинхронные операции

NoticeResponce – уведомления от сервераParameterStatus – уведомления об изменении параметровNotificationResponse – сообщения, переданные через NOTIFY, если клиент выполняет команду LISTEN

Page 20: Hacking PostgreSQL. Обзор исходного кода

20

Отмена запроса

Page 21: Hacking PostgreSQL. Обзор исходного кода

21

Прерывания

src/include/miscadmin.h

#define CHECK_FOR_INTERRUPTS() \do { \

if (InterruptPending) \ProcessInterrupts(); \

} while(0)

Page 22: Hacking PostgreSQL. Обзор исходного кода

22

Подробнее

● Презентация "Postgres on the wire"● Документация "Клиент-серверный протокол"

Page 23: Hacking PostgreSQL. Обзор исходного кода

23

src/backend/parser

Page 24: Hacking PostgreSQL. Обзор исходного кода

24

src/backend/parser/README

parser.c things start herescan.l break query into tokensscansup.c handle escapes in input stringskwlookup.c turn keywords into specific tokenskeywords.c table of standard keywords (passed to kwlookup.c)gram.y parse the tokens and produce a "raw" parse treeanalyze.c top level of parse analysis for optimizable queriesparse_agg.c handle aggregates, like SUM(col1), AVG(col2), ...parse_clause.c handle clauses like WHERE, ORDER BY, GROUP BY, ...parse_coerce.c handle coercing expressions to different data typesparse_collate.c assign collation information in completed expressionsparse_cte.c handle Common Table Expressions (WITH clauses)parse_expr.c handle expressions like col, col + 3, x = 3 or x = 4parse_func.c handle functions, table.column and column identifiersparse_node.c create nodes for various structuresparse_oper.c handle operators in expressionsparse_param.c handle Params (for the cases used in the core backend)parse_relation.c support routines for tables and column handlingparse_target.c handle the result list of the queryparse_type.c support routines for data type handlingparse_utilcmd.c parse analysis for utility commands (done at execution time)

Page 25: Hacking PostgreSQL. Обзор исходного кода

25

src/backend/parser/scan.l

digit [0-9]integer {digit}+decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*))

{integer} {SET_YYLLOC();return process_integer_literal(yytext, yylval);

}{decimal} {

SET_YYLLOC();yylval->str = pstrdup(yytext);return FCONST;

}

Page 26: Hacking PostgreSQL. Обзор исходного кода

26

src/backend/parser/gram.y

CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'OptInherit OptWith OnCommitOption OptTableSpace

{CreateStmt *n = makeNode(CreateStmt);$4->relpersistence = $2;n->relation = $4;n->tableElts = $6;n->inhRelations = $8;n->ofTypename = NULL;n->constraints = NIL;n->options = $9;n->oncommit = $10;n->tablespacename = $11;n->if_not_exists = false;$$ = (Node *)n;

}

Page 27: Hacking PostgreSQL. Обзор исходного кода

27

DDL vs DML

Page 28: Hacking PostgreSQL. Обзор исходного кода

28

DML

Page 29: Hacking PostgreSQL. Обзор исходного кода

29

src/backend/nodes

Page 30: Hacking PostgreSQL. Обзор исходного кода

30

Пример. CREATE TABLE

CREATE TABLE tbl (a int, b int, PRIMARY KEY (a) INCLUDING (b)

);

Page 31: Hacking PostgreSQL. Обзор исходного кода

31

gram.y

CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'OptInherit OptWith OnCommitOption OptTableSpace

{CreateStmt *n = makeNode(CreateStmt);$4->relpersistence = $2;n->relation = $4;n->tableElts = $6;n->inhRelations = $8;n->ofTypename = NULL;n->constraints = NIL;n->options = $9;n->oncommit = $10;n->tablespacename = $11;n->if_not_exists = false;$$ = (Node *)n;

}

Page 32: Hacking PostgreSQL. Обзор исходного кода

32

gram.y

| PRIMARY KEY '(' columnList ')' opt_c_including opt_definitionOptConsTableSpace ConstraintAttributeSpec

{Constraint *n = makeNode(Constraint);n->contype = CONSTR_PRIMARY;n->location = @1;n->keys = $4;n->including = $6;n->options = $7;n->indexname = NULL;n->indexspace = $8;processCASbits($9, @9, "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, NULL, yyscanner);$$ = (Node *)n;

}

opt_c_including: INCLUDING optcincluding { $$ = $2; } | /* EMPTY */ { $$ = NIL; }

;optcincluding : '(' columnList ')' { $$ = $2; }

;

Page 33: Hacking PostgreSQL. Обзор исходного кода

33

src/include/nodes/parsenodes.h

typedef struct Query{NodeTag type;CmdType commandType; /* select|insert|update|delete|utility */QuerySource querySource; /* where did I come from? */uint32 queryId; /* query identifier (can be set by plugins) */bool canSetTag; /* do I set the command result tag? */Node *utilityStmt; /* non-null if this is DECLARE CURSOR or a * non-optimizable statement */int resultRelation; /* rtable index of target relation for * INSERT/UPDATE/DELETE; 0 for SELECT */bool hasAggs; /* has aggregates in tlist or havingQual */bool hasWindowFuncs; /* has window functions in tlist */bool hasSubLinks; /* has subquery SubLink */bool hasDistinctOn; /* distinctClause is from DISTINCT ON */bool hasRecursive; /* WITH RECURSIVE was specified */bool hasModifyingCTE; /* has INSERT/UPDATE/DELETE in WITH */bool hasForUpdate; /* FOR [KEY] UPDATE/SHARE was specified */bool hasRowSecurity; /* row security applied? */

Page 34: Hacking PostgreSQL. Обзор исходного кода

34

Query

List *cteList; /* WITH list (of CommonTableExpr's) */List *rtable; /* list of range table entries */FromExpr *jointree; /* table join tree (FROM and WHERE clauses) */List *targetList; /* target list (of TargetEntry) */OnConflictExpr *onConflict; /* ON CONFLICT DO [NOTHING | UPDATE] */List *returningList; /* return-values list (of TargetEntry) */List *groupClause; /* a list of SortGroupClause's */List *groupingSets; /* a list of GroupingSet's if present */Node *havingQual; /* qualifications applied to groups */List *windowClause; /* a list of WindowClause's */List *distinctClause; /* a list of SortGroupClause's */List *sortClause; /* a list of SortGroupClause's */Node *limitOffset; /* # of result tuples to skip (int8 expr) */Node *limitCount; /* # of result tuples to return (int8 expr) */List *rowMarks; /* a list of RowMarkClause's */Node *setOperations; /* set-operation tree if this is top level of * a UNION/INTERSECT/EXCEPT query */List *constraintDeps; /* a list of pg_constraint OIDs that the query * depends on to be semantically valid */

...} Query;

Page 35: Hacking PostgreSQL. Обзор исходного кода

35

CreateStmt

typedef struct CreateStmt{NodeTag type;RangeVar *relation; /* relation to create */List *tableElts; /* column definitions (list of ColumnDef) */List *inhRelations; /* relations to inherit from (list of * inhRelation) */TypeName *ofTypename; /* OF typename */List *constraints; /* constraints (list of Constraint nodes) */List *options; /* options from WITH clause */OnCommitAction oncommit; /* what do we do at COMMIT? */char *tablespacename; /* table space to use, or NULL */bool if_not_exists; /* just do nothing if it already exists? */} CreateStmt;

Page 36: Hacking PostgreSQL. Обзор исходного кода

36

Constraint

typedef struct Constraint{

NodeTag type;ConstrType contype; /* see above */

/* Fields used for most/all constraint types: */char *conname; /* Constraint name, or NULL if unnamed */bool deferrable; /* DEFERRABLE? */bool initdeferred; /* INITIALLY DEFERRED? */int location; /* token location, or -1 if unknown */

/* Fields used for unique constraints (UNIQUE and PRIMARY KEY): */List *keys; /* String nodes naming referenced key column(s) */List *including; /* String nodes naming referenced nonkey

* column(s) */...

}

Page 37: Hacking PostgreSQL. Обзор исходного кода

37

tcop/utility.c

ProcessUtilitySlow {switch (nodeTag(parsetree)) {case T_CreateStmt:

/* Run parse analysis ... */stmts = transformCreateStmt((CreateStmt *) parsetree,

queryString);foreach(l, stmts) {

if (IsA(stmt, CreateStmt)) { /* Create the table itself */

address = DefineRelation((CreateStmt *) stmt,RELKIND_RELATION, InvalidOid, NULL);

}else {/* * Recurse for anything else. */ProcessUtility(...)

}}

Page 38: Hacking PostgreSQL. Обзор исходного кода

38

parse_utilcmd.c

transformCreateStmt {

transformTableConstraint {switch (constraint→contype){

case CONSTR_PRIMARY:cxt->ixconstraints = lappend(cxt->ixconstraints, constraint);Break;

}}

transformIndexConstraints {foreach(lc, cxt->ixconstraints){

Constraint *constraint = (Constraint *) lfirst(lc);index = transformIndexConstraint(constraint, cxt);indexlist = lappend(indexlist, index);

}}

}

Page 39: Hacking PostgreSQL. Обзор исходного кода

39

parse_utilcmd.c

transformIndexConstraint {foreach(lc, constraint->including){

.../* add it to the index definition*/iparam = makeNode(IndexElem);iparam->name = pstrdup(key);iparam->expr = NULL;iparam->indexcolname = NULL;iparam->collation = NIL;iparam->opclass = NIL;index->indexIncludingParams = lappend(index->indexIncludingParams, iparam);

}}

Page 40: Hacking PostgreSQL. Обзор исходного кода

40

indexcmds.c

ObjectAddressDefineIndex(Oid relationId, IndexStmt *stmt, …) {

indexRelationId = index_create(rel, indexRelationName,indexRelationId, stmt→oldNode,indexInfo, indexColNames,accessMethodId, tablespaceId,collationObjectId, classObjectId,coloptions, reloptions, stmt->primary,stmt->isconstraint,stmt->deferrable, stmt->initdeferred,allowSystemTableMods,skip_build || stmt->concurrent,stmt->concurrent, !check_rights,stmt→if_not_exists);

}

Page 41: Hacking PostgreSQL. Обзор исходного кода

41

Продолжение следует...

В следующий раз:– Физическое представление данных– Методы доступа– Внутренняя структура tuple

Page 42: Hacking PostgreSQL. Обзор исходного кода

www.postgrespro.ru

СПАСИБО ЗА ВНИМАНИЕ! ВОПРОСЫ?

Hacking PostgreSQL

17.03.2016

[email protected]