SlideShare a Scribd company logo
www.postgrespro.ru
Физическое Представление данных
Hacking PostgreSQL
24.03.2016
2
Содержание
1.OID
2.PGDATA
3.Storage manager
4.Heap
5.Forks
6.Page
3
Ответ на вопрос
Вопрос:
Где найти номера стратегий для написания
класса операторов?
Ответ:
src/include/access/stratnum.h
4
Relation – объект базы данных
src/include/catalog/pg_class.h
#define RELKIND_RELATION 'r' /* ordinary table */
#define RELKIND_INDEX 'i' /* secondary index */
#define RELKIND_SEQUENCE 'S' /* sequence object */
#define RELKIND_TOASTVALUE 't' /* for out-of-line values */
#define RELKIND_VIEW 'v' /* view */
#define RELKIND_COMPOSITE_TYPE 'c' /* composite type */
#define RELKIND_FOREIGN_TABLE 'f' /* foreign table */
#define RELKIND_MATVIEW 'm' /* materialized view */
5
OID
src/include/postgres_ext.h
/* Object ID is a fundamental type in Postgres. */
typedef unsigned int Oid;
#define InvalidOid ((Oid) 0)
src/include/access/transam.h
#define FirstBootstrapObjectId 10000
#define FirstNormalObjectId 16384
6
Генератор OID
src/backend/catalog/catalog.c
Oid GetNewOid (Relation relation)
Oid GetNewRelFileNode (Oid reltablespace,
Relation pg_class,
char relpersistence)
src/backend/access/transam/varsup.c
Oid GetNewObjectId()
7
Выбор OID
src/include/catalog/unused_oids
src/include/catalog/duplicate_oids
8
Приведение типов
SELECT oid, relname FROM pg_class LIMIT 1;
oid | relname
------+--------------
2619 | pg_statistic
SELECT * FROM pg_attribute WHERE attrelid = 'pg_statistic'::regclass;
SELECT * FROM pg_attribute WHERE attrelid =
(SELECT oid FROM pg_class WHERE relname = 'pg_statistic');
SELECT 'pg_statistic'::regclass::oid;
oid
------
2619
SELECT 2619::regclass;
regclass
--------------
pg_statistic
9
Вопросы и источники
●
Что происходит при OID wraparond?
●
Сказывается ли это на производительности?
●
Могут ли закончиться OID?
●
В каком случае, и что тогда произойдет?
●
Документация про OID
●
[HACKERS] 32bit OID wrap around conceerns
10
$PGDATA
PGDATA="/home/anastasia/projects/postgresql_data"
ls -CF
base/ pg_multixact/ pg_tblspc/
global/ pg_notify/ pg_twophase/
pg_clog/ pg_replslot/ PG_VERSION
pg_commit_ts/ pg_serial/ pg_xlog/
pg_dynshmem/ pg_snapshots/ postgresql.auto.conf
pg_hba.conf pg_stat/ postgresql.conf
pg_ident.conf pg_stat_tmp/ postmaster.opts
pg_logical/ pg_subtrans/
11
$PGDATA/global
ls -CF
1136 1233 2396_vm 2846_vm 4060
1136_fsm 1260 2397 2847 4060_vm
1136_vm 1260_fsm 2671 2964 4061
1137 1260_vm 2672 2964_vm 6000
1213 1261 2676 2965 6000_vm
1213_fsm 1261_vm 2677 2966 6001
1213_vm 1262 2694 2966_vm 6002
1214 1262_fsm 2695 2967 pg_control
1214_fsm 1262_vm 2697 3592 pg_filenode.map
1214_vm 2396 2698 3592_vm pg_internal.init
1232 2396_fsm 2846 3593
12
Файлы в pg_global
postgres=# SELECT oid, spcname FROM pg_tablespace ;
oid | spcname
------+------------
1663 | pg_default
1664 | pg_global
postgres=# SELECT oid, relfilenode, relname FROM pg_class
WHERE reltablespace = 1664 ORDER BY oid;
oid | relfilenode | relname
------+-------------+-----------------------------------------
1136 | 0 | pg_pltemplate
1137 | 0 | pg_pltemplate_name_index
1213 | 0 | pg_tablespace
1214 | 0 | pg_shdepend
1232 | 0 | pg_shdepend_depender_index
1233 | 0 | pg_shdepend_reference_index
1260 | 0 | pg_authid
1261 | 0 | pg_auth_members
1262 | 0 | pg_database
2396 | 0 | pg_shdescription
2397 | 0 | pg_shdescription_o_c_index
2671 | 0 | pg_database_datname_index
13
Файлы в pg_global (2)
postgres=# SELECT oid, relfilenode, relname FROM pg_class
WHERE reltablespace = 1664 ORDER BY oid;
oid | relfilenode | relname
------+-------------+-----------------------------------------
2676 | 0 | pg_authid_rolname_index
2677 | 0 | pg_authid_oid_index
2694 | 0 | pg_auth_members_role_member_index
2695 | 0 | pg_auth_members_member_role_index
2697 | 0 | pg_tablespace_oid_index
2698 | 0 | pg_tablespace_spcname_index
2846 | 0 | pg_toast_2396
2847 | 0 | pg_toast_2396_index
2964 | 0 | pg_db_role_setting
2965 | 0 | pg_db_role_setting_databaseid_rol_index
2966 | 0 | pg_toast_2964
2967 | 0 | pg_toast_2964_index
3592 | 0 | pg_shseclabel
3593 | 0 | pg_shseclabel_object_index
4060 | 0 | pg_toast_3592
4061 | 0 | pg_toast_3592_index
6000 | 0 | pg_replication_origin
6001 | 0 | pg_replication_origin_roiident_index
14
Tablespaces
src/include/catalog/pg_tablespace.h
Документация
pg_tblspc/
●
содержит ссылки на директории
●
view pg_tablespace содержит имена объектов и их идентификаторы
●
НЕ является независимой частью кластера!
15
$PGDATA/base
ls -CF
1/ 12423/ 12424/ 16501/ pgsql_tmp/
contrib/oid2name
$oid2name
All databases:
Oid Database Name Tablespace
----------------------------------
16501 db pg_default
12424 postgres pg_default
12423 template0 pg_default
1 template1 pg_default
16
pg_relation_filepath
src/backend/utils/adt/dbsize.c
db=# df pg*relation*
List of functions
Schema | Name | Result data type | Argument data types | Type
------------+--------------------------+------------------+---------------------+--------
pg_catalog | pg_filenode_relation | regclass | oid, oid | normal
pg_catalog | pg_relation_filenode | oid | regclass | normal
pg_catalog | pg_relation_filepath | text | regclass | normal
pg_catalog | pg_relation_is_updatable | integer | regclass, boolean | normal
pg_catalog | pg_relation_size | bigint | regclass | normal
pg_catalog | pg_relation_size | bigint | regclass, text | normal
pg_catalog | pg_total_relation_size | bigint | regclass | normal
db=# SELECT pg_relation_filepath('tbl');
pg_relation_filepath
----------------------
base/16497/16498
db=# SELECT pg_filenode_relation(0, 16498);
pg_filenode_relation
----------------------
tbl
17
$PGDATA/base/16501
db=# CREATE TABLE tbl (a int, b int);
db=# SELECT oid, relname, relfilenode
FROM pg_class WHERE relname='tbl';
oid | relname | relfilenode
-------+---------+-------------
16502 | tbl | 16502
~/projects/postgresql_data/base/16501$ ls 16502*
16502
~/projects/postgresql_data/base/16501$ wc -c 16502
/*абсолютно пустой файл*/
db=# INSERT INTO tbl VALUES (1,1);
~/projects/postgresql_data/base/16501$ wc -c 16502
/*снова абсолютно пустой файл*/
18
pg_buffercache
db=# CREATE EXTENSION pg_buffercache;
db=# SELECT * FROM pg_buffercache WHERE relfilenode ='tbl'::regclass ;
-[ RECORD 1 ]----+------
bufferid | 454
relfilenode | 16502
reltablespace | 1663
reldatabase | 16501
relforknumber | 0
relblocknumber | 0
isdirty | t
usagecount | 2
pinning_backends | 0
db=# CHECKPOINT;
db=# SELECT * FROM pg_buffercache WHERE relfilenode ='tbl'::regclass ;
-[ RECORD 1 ]----+------
bufferid | 454
relfilenode | 16502
reltablespace | 1663
reldatabase | 16501
relforknumber | 0
relblocknumber | 0
isdirty | f
usagecount | 2
pinning_backends | 0
19
pageinspect
~/projects/postgresql_data/base/16501$ wc -c 16502
/*В файле появились данные!*/
db=# CREATE EXTENSION pageinspect;
db=# select * from heap_page_items(get_raw_page('tbl',0));
-[ RECORD 1 ]-------------------
lp | 1
lp_off | 8160
lp_flags | 1
lp_len | 32
t_xmin | 720
t_xmax | 0
t_field3 | 0
t_ctid | (0,1)
t_infomask2 | 2
t_infomask | 2048
t_hoff | 24
t_bits |
t_oid |
t_data | x0100000001000000
20
oid vs relfilenode
db=# SELECT oid, relname,relfilenode FROM pg_class
WHERE relname='tbl';
oid | relname | relfilenode
-------+---------+-------------
16502 | tbl | 16502
db=# TRUNCATE tbl ;
db=# SELECT oid, relname,relfilenode FROM pg_class
WHERE relname='tbl';
oid | relname | relfilenode
-------+---------+-------------
16502 | tbl | 16531
21
RelFileNode
src/include/storage/relfilenode.h
typedef struct RelFileNode
{
Oid spcNode; /* tablespace */
Oid dbNode; /* database */
Oid relNode; /* relation */
} RelFileNode;
typedef struct RelFileNodeBackend
{
RelFileNode node;
BackendId backend;
} RelFileNodeBackend;
22
Storage manager
23
Storage manager
src/backend/storage/smgr/README
src/backend/storage/smgr.c
src/backend/storage/md.c
24
Страница(блок) – единица I/O
src/include/storage/bufpage.h
src/backend/access/nbtree/nbtpage.c
Разные методы доступа
отличаются структурой данных
на странице
25
Сегмент (файл) - набор блоков
src/include/storage/block.h
typedef uint32 BlockNumber;
#define InvalidBlockNumber ((BlockNumber) 0xFFFFFFFF)
#define MaxBlockNumber (BlockNumber) 0xFFFFFFFE)
typedef struct BlockIdData
{
uint16 bi_hi;
uint16 bi_lo;
} BlockIdData;
/* block identifier */
typedef BlockIdData *BlockId;
26
Relation – набор сегментов
+ системные данные (forks)
27
Forks
src/include/common/relpath.h
typedef enum ForkNumber
{
InvalidForkNumber = -1,
MAIN_FORKNUM = 0,
FSM_FORKNUM,
VISIBILITYMAP_FORKNUM,
INIT_FORKNUM
} ForkNumber;
src/common/relpath.c
const char *const forkNames[] = {
"main", /* MAIN_FORKNUM */
"fsm", /* FSM_FORKNUM */
"vm", /* VISIBILITYMAP_FORKNUM */
"init" /* INIT_FORKNUM */
};
28
MAIN
src/include/catalog/storage.h
src/backend/catalog/storage.c
src/include/storage/buf.h
src/include/storage/bufmgr.h
void
RelationCreateStorage(RelFileNode rnode, char relpersistence)
Buffer ReadBuffer (Relation reln, BlockNumber blockNum)
29
FreeSpaceMap
30
FreeSpaceMap
src/backend/storage/freespace/README
src/backend/storage/freespace/freespace.c
BlockNumber
GetPageWithFreeSpace(Relation rel, Size spaceNeeded)
31
VisibilityMap
src/backend/access/heap/visibilitymap.c
2 бита на страницу:
●
All visible
●
All frozen
32
_init
http://www.postgresql.org/docs/devel/static/storage-init.html
Для unlogged Relations
33
Страница
src/include/storage/bufpage.h
* +----------------+---------------------------------+
* | PageHeaderData | linp1 linp2 linp3 ... |
* +-----------+----+---------------------------------+
* | ... linpN | |
* +-----------+--------------------------------------+
* | ^ pd_lower |
* | |
* | v pd_upper |
* +-------------+------------------------------------+
* | | tupleN ... |
* +-------------+------------------+-----------------+
* | ... tuple3 tuple2 tuple1 | "special space" |
* +--------------------------------+-----------------+
34
PageHeaderData
src/include/storage/bufpage.h
typedef struct PageHeaderData
{
/* XXX LSN is member of *any* block, not only page-organized ones */
PageXLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog
* record for last change to this page */
uint16 pd_checksum; /* checksum */
uint16 pd_flags; /* flag bits, see below */
LocationIndex pd_lower; /* offset to start of free space */
LocationIndex pd_upper; /* offset to end of free space */
LocationIndex pd_special; /* offset to start of special space */
uint16 pd_pagesize_version;
TransactionId pd_prune_xid; /* oldest prunable XID, or zero if none */
ItemIdData pd_linp[FLEXIBLE_ARRAY_MEMBER]; /* line pointer array */
} PageHeaderData;
35
PageAddItem
src/include/storage/bufpage.h
src/backend/storage/page/bufpage.c
OffsetNumber PageAddItem(Page page,
Item item,
Size size,
OffsetNumber offsetNumber,
bool overwrite,
bool is_heap)
36
Домашнее задание. Подумать.
●
Что происходит при OID wraparond?
●
Могут ли закончиться OID?
37
Домашнее задание.
●
Простое
●
Регрессионные тесты для pageinspect
●
Перенести функции gevel в pageinspect
●
Контриб, который воспроизводимо ломает данные в
файле таблицы/индекса (чисто в академических
целях). Может быть функция в pageinspect.
●
Сложное
●
Обновление default значений
●
Чтение данных из битых файлов
38
Источники
●
http://www.interdb.jp/pg/pgsql01.html
●
http://www.slideshare.net/FedericoCampoli/10-things-pos
●
https://momjian.us/main/presentations/internals.html
●
https://wiki.postgresql.org/images/8/81/FSM_and_Visibilit
39
Ребята, помогите Насте
успеть к Feature Freeze
● https://commitfest.postgresql.org/9/433/
● https://commitfest.postgresql.org/9/494/
40
Отмена лекций
Занятий
31.03 и 07.04
не будет
www.postgrespro.ru
Спасибо за внимание!
Вопросы?
Hacking PostgreSQL
24.03.2016
hacking@postgrespro.ru

More Related Content

What's hot

Отладка и устранение проблем в PostgreSQL Streaming Replication.
Отладка и устранение проблем в PostgreSQL Streaming Replication.Отладка и устранение проблем в PostgreSQL Streaming Replication.
Отладка и устранение проблем в PostgreSQL Streaming Replication.
Alexey Lesovsky
 
Александр Крашенинников "Hadoop High Availability: опыт Badoo"
Александр Крашенинников "Hadoop High Availability: опыт Badoo"Александр Крашенинников "Hadoop High Availability: опыт Badoo"
Александр Крашенинников "Hadoop High Availability: опыт Badoo"
IT Event
 
5 способов деплоя PHP-кода в условиях хайлоада / Юрий Насретдинов (Badoo)
5 способов деплоя PHP-кода в условиях хайлоада / Юрий Насретдинов (Badoo)5 способов деплоя PHP-кода в условиях хайлоада / Юрий Насретдинов (Badoo)
5 способов деплоя PHP-кода в условиях хайлоада / Юрий Насретдинов (Badoo)
Ontico
 
PostgreSQL: практические примеры оптимизации SQL-запросов / Иван Фролков (Po...
PostgreSQL: практические примеры оптимизации SQL-запросов /  Иван Фролков (Po...PostgreSQL: практические примеры оптимизации SQL-запросов /  Иван Фролков (Po...
PostgreSQL: практические примеры оптимизации SQL-запросов / Иван Фролков (Po...
Ontico
 
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Fwdays
 
Быстрое развёртывание шаблонов и статики в Mail.ru, Николай Кондратов
Быстрое развёртывание шаблонов и статики в Mail.ru, Николай КондратовБыстрое развёртывание шаблонов и статики в Mail.ru, Николай Кондратов
Быстрое развёртывание шаблонов и статики в Mail.ru, Николай КондратовFuenteovejuna
 
pgday17. How shared memory works in modern PostgreSQL
pgday17. How shared memory works in modern PostgreSQLpgday17. How shared memory works in modern PostgreSQL
pgday17. How shared memory works in modern PostgreSQL
Dmitry Kremer
 
Программирование Linux
Программирование LinuxПрограммирование Linux
Программирование LinuxAnthony Shoumikhin
 
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScriptСтажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
SmartTools
 
Web осень 2013 лекция 1
Web осень 2013 лекция 1Web осень 2013 лекция 1
Web осень 2013 лекция 1Technopark
 
Доклад Антона Поварова на Tarantool Meetup. "Tarantool в Badoo: хранение исто...
Доклад Антона Поварова на Tarantool Meetup. "Tarantool в Badoo: хранение исто...Доклад Антона Поварова на Tarantool Meetup. "Tarantool в Badoo: хранение исто...
Доклад Антона Поварова на Tarantool Meetup. "Tarantool в Badoo: хранение исто...
Badoo Development
 
Web осень 2013 лекция 3
Web осень 2013 лекция 3Web осень 2013 лекция 3
Web осень 2013 лекция 3Technopark
 
Разработка real-time приложений с RethinkDB / Илья Вербицкий (Независимый кон...
Разработка real-time приложений с RethinkDB / Илья Вербицкий (Независимый кон...Разработка real-time приложений с RethinkDB / Илья Вербицкий (Независимый кон...
Разработка real-time приложений с RethinkDB / Илья Вербицкий (Независимый кон...
Ontico
 
Romanova techforum bash
Romanova techforum bashRomanova techforum bash
Romanova techforum bashkuchinskaya
 
Reform: путь к лучшему ORM
Reform: путь к лучшему ORMReform: путь к лучшему ORM
Reform: путь к лучшему ORM
Badoo Development
 
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...Ontico
 
Web весна 2013 лекция 3
Web весна 2013 лекция 3Web весна 2013 лекция 3
Web весна 2013 лекция 3Technopark
 
Компиляция скриптов PHP. Алексей Романенко
Компиляция скриптов PHP. Алексей РоманенкоКомпиляция скриптов PHP. Алексей Романенко
Компиляция скриптов PHP. Алексей РоманенкоFuenteovejuna
 
Web осень 2012 лекция 3
Web осень 2012 лекция 3Web осень 2012 лекция 3
Web осень 2012 лекция 3Technopark
 
О.В.Сухорослов "MapReduce: инструменты и практические примеры"
О.В.Сухорослов "MapReduce: инструменты и практические примеры"О.В.Сухорослов "MapReduce: инструменты и практические примеры"
О.В.Сухорослов "MapReduce: инструменты и практические примеры"
Yandex
 

What's hot (20)

Отладка и устранение проблем в PostgreSQL Streaming Replication.
Отладка и устранение проблем в PostgreSQL Streaming Replication.Отладка и устранение проблем в PostgreSQL Streaming Replication.
Отладка и устранение проблем в PostgreSQL Streaming Replication.
 
Александр Крашенинников "Hadoop High Availability: опыт Badoo"
Александр Крашенинников "Hadoop High Availability: опыт Badoo"Александр Крашенинников "Hadoop High Availability: опыт Badoo"
Александр Крашенинников "Hadoop High Availability: опыт Badoo"
 
5 способов деплоя PHP-кода в условиях хайлоада / Юрий Насретдинов (Badoo)
5 способов деплоя PHP-кода в условиях хайлоада / Юрий Насретдинов (Badoo)5 способов деплоя PHP-кода в условиях хайлоада / Юрий Насретдинов (Badoo)
5 способов деплоя PHP-кода в условиях хайлоада / Юрий Насретдинов (Badoo)
 
PostgreSQL: практические примеры оптимизации SQL-запросов / Иван Фролков (Po...
PostgreSQL: практические примеры оптимизации SQL-запросов /  Иван Фролков (Po...PostgreSQL: практические примеры оптимизации SQL-запросов /  Иван Фролков (Po...
PostgreSQL: практические примеры оптимизации SQL-запросов / Иван Фролков (Po...
 
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
Aleksei Milovidov "Let's optimize one aggregate function in ClickHouse"
 
Быстрое развёртывание шаблонов и статики в Mail.ru, Николай Кондратов
Быстрое развёртывание шаблонов и статики в Mail.ru, Николай КондратовБыстрое развёртывание шаблонов и статики в Mail.ru, Николай Кондратов
Быстрое развёртывание шаблонов и статики в Mail.ru, Николай Кондратов
 
pgday17. How shared memory works in modern PostgreSQL
pgday17. How shared memory works in modern PostgreSQLpgday17. How shared memory works in modern PostgreSQL
pgday17. How shared memory works in modern PostgreSQL
 
Программирование Linux
Программирование LinuxПрограммирование Linux
Программирование Linux
 
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScriptСтажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
 
Web осень 2013 лекция 1
Web осень 2013 лекция 1Web осень 2013 лекция 1
Web осень 2013 лекция 1
 
Доклад Антона Поварова на Tarantool Meetup. "Tarantool в Badoo: хранение исто...
Доклад Антона Поварова на Tarantool Meetup. "Tarantool в Badoo: хранение исто...Доклад Антона Поварова на Tarantool Meetup. "Tarantool в Badoo: хранение исто...
Доклад Антона Поварова на Tarantool Meetup. "Tarantool в Badoo: хранение исто...
 
Web осень 2013 лекция 3
Web осень 2013 лекция 3Web осень 2013 лекция 3
Web осень 2013 лекция 3
 
Разработка real-time приложений с RethinkDB / Илья Вербицкий (Независимый кон...
Разработка real-time приложений с RethinkDB / Илья Вербицкий (Независимый кон...Разработка real-time приложений с RethinkDB / Илья Вербицкий (Независимый кон...
Разработка real-time приложений с RethinkDB / Илья Вербицкий (Независимый кон...
 
Romanova techforum bash
Romanova techforum bashRomanova techforum bash
Romanova techforum bash
 
Reform: путь к лучшему ORM
Reform: путь к лучшему ORMReform: путь к лучшему ORM
Reform: путь к лучшему ORM
 
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
12 вариантов использования Redis — в Tarantool (Александр Календарев, Констан...
 
Web весна 2013 лекция 3
Web весна 2013 лекция 3Web весна 2013 лекция 3
Web весна 2013 лекция 3
 
Компиляция скриптов PHP. Алексей Романенко
Компиляция скриптов PHP. Алексей РоманенкоКомпиляция скриптов PHP. Алексей Романенко
Компиляция скриптов PHP. Алексей Романенко
 
Web осень 2012 лекция 3
Web осень 2012 лекция 3Web осень 2012 лекция 3
Web осень 2012 лекция 3
 
О.В.Сухорослов "MapReduce: инструменты и практические примеры"
О.В.Сухорослов "MapReduce: инструменты и практические примеры"О.В.Сухорослов "MapReduce: инструменты и практические примеры"
О.В.Сухорослов "MapReduce: инструменты и практические примеры"
 

Viewers also liked

Hacking PostgreSQL. Обзор архитектуры.
Hacking PostgreSQL. Обзор архитектуры.Hacking PostgreSQL. Обзор архитектуры.
Hacking PostgreSQL. Обзор архитектуры.
Anastasia Lubennikova
 
Historia de los_satelites_de_comunicaciones._bit_134._5c6c417a
Historia de los_satelites_de_comunicaciones._bit_134._5c6c417aHistoria de los_satelites_de_comunicaciones._bit_134._5c6c417a
Historia de los_satelites_de_comunicaciones._bit_134._5c6c417a
Jesus Ayerve Tuiro
 
Kpi for project management
Kpi for project managementKpi for project management
Kpi for project managementchamberthomas
 
2011-2012 AmLit Syllabus
2011-2012 AmLit Syllabus2011-2012 AmLit Syllabus
2011-2012 AmLit Syllabusslr1541
 
Toyato cars
Toyato carsToyato cars
Toyato cars
kaustubr08
 
Kumpulan pantun by:ririnrosalinda abdinegara
Kumpulan pantun by:ririnrosalinda abdinegara Kumpulan pantun by:ririnrosalinda abdinegara
Kumpulan pantun by:ririnrosalinda abdinegara
ririnrosalinda
 
Destroying Router Security
Destroying Router SecurityDestroying Router Security
Destroying Router Security
Iván Sanz de Castro
 
SalesRev - Boost Your Conversions and Generate More Business Without Spending...
SalesRev - Boost Your Conversions and Generate More Business Without Spending...SalesRev - Boost Your Conversions and Generate More Business Without Spending...
SalesRev - Boost Your Conversions and Generate More Business Without Spending...
Keith McGibbon
 
Survival Packet
Survival PacketSurvival Packet
Survival Packetslr1541
 
2009-2010 10 Syllabus
2009-2010 10 Syllabus2009-2010 10 Syllabus
2009-2010 10 Syllabusslr1541
 
P (1)ele escolheu você
P (1)ele escolheu vocêP (1)ele escolheu você
P (1)ele escolheu você
Josinei Tavares
 
Kpi google analytics
Kpi google analyticsKpi google analytics
Kpi google analyticschamberthomas
 
2008-2009 AP Syllabus
2008-2009 AP Syllabus2008-2009 AP Syllabus
2008-2009 AP Syllabusslr1541
 
Making Awesome Experiences with Biosensors
Making Awesome Experiences with BiosensorsMaking Awesome Experiences with Biosensors
Making Awesome Experiences with Biosensors
SophiKravitz
 
Page compression. PGCON_2016
Page compression. PGCON_2016Page compression. PGCON_2016
Page compression. PGCON_2016
Anastasia Lubennikova
 
Instructivo hidrología unamba
Instructivo hidrología unambaInstructivo hidrología unamba
Instructivo hidrología unamba
Jesus Ayerve Tuiro
 

Viewers also liked (20)

Hacking PostgreSQL. Обзор архитектуры.
Hacking PostgreSQL. Обзор архитектуры.Hacking PostgreSQL. Обзор архитектуры.
Hacking PostgreSQL. Обзор архитектуры.
 
Historia de los_satelites_de_comunicaciones._bit_134._5c6c417a
Historia de los_satelites_de_comunicaciones._bit_134._5c6c417aHistoria de los_satelites_de_comunicaciones._bit_134._5c6c417a
Historia de los_satelites_de_comunicaciones._bit_134._5c6c417a
 
Kpi for project management
Kpi for project managementKpi for project management
Kpi for project management
 
2011-2012 AmLit Syllabus
2011-2012 AmLit Syllabus2011-2012 AmLit Syllabus
2011-2012 AmLit Syllabus
 
Toyato cars
Toyato carsToyato cars
Toyato cars
 
Kpi process
Kpi processKpi process
Kpi process
 
Kumpulan pantun by:ririnrosalinda abdinegara
Kumpulan pantun by:ririnrosalinda abdinegara Kumpulan pantun by:ririnrosalinda abdinegara
Kumpulan pantun by:ririnrosalinda abdinegara
 
Destroying Router Security
Destroying Router SecurityDestroying Router Security
Destroying Router Security
 
SalesRev - Boost Your Conversions and Generate More Business Without Spending...
SalesRev - Boost Your Conversions and Generate More Business Without Spending...SalesRev - Boost Your Conversions and Generate More Business Without Spending...
SalesRev - Boost Your Conversions and Generate More Business Without Spending...
 
Survival Packet
Survival PacketSurvival Packet
Survival Packet
 
2009-2010 10 Syllabus
2009-2010 10 Syllabus2009-2010 10 Syllabus
2009-2010 10 Syllabus
 
10
1010
10
 
P (1)ele escolheu você
P (1)ele escolheu vocêP (1)ele escolheu você
P (1)ele escolheu você
 
Kpi google analytics
Kpi google analyticsKpi google analytics
Kpi google analytics
 
2008-2009 AP Syllabus
2008-2009 AP Syllabus2008-2009 AP Syllabus
2008-2009 AP Syllabus
 
Making Awesome Experiences with Biosensors
Making Awesome Experiences with BiosensorsMaking Awesome Experiences with Biosensors
Making Awesome Experiences with Biosensors
 
Kpi key
Kpi keyKpi key
Kpi key
 
Page compression. PGCON_2016
Page compression. PGCON_2016Page compression. PGCON_2016
Page compression. PGCON_2016
 
Kpi indicator
Kpi indicatorKpi indicator
Kpi indicator
 
Instructivo hidrología unamba
Instructivo hidrología unambaInstructivo hidrología unamba
Instructivo hidrología unamba
 

Similar to Hacking PostgreSQL. Физическое представление данных

Поиск? Sphinx!
Поиск? Sphinx!Поиск? Sphinx!
Поиск? Sphinx!
Roman Zaiev
 
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
pgdayrussia
 
Расширяемость PostgreSQL для хакеров и архитекторов / Олег Бартунов, Александ...
Расширяемость PostgreSQL для хакеров и архитекторов / Олег Бартунов, Александ...Расширяемость PostgreSQL для хакеров и архитекторов / Олег Бартунов, Александ...
Расширяемость PostgreSQL для хакеров и архитекторов / Олег Бартунов, Александ...Ontico
 
Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Ivan Muratov
 
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс Сервер
PVasili
 
2015-12-05 Александр Коротков, Иван Панченко - Слабо-структурированные данные...
2015-12-05 Александр Коротков, Иван Панченко - Слабо-структурированные данные...2015-12-05 Александр Коротков, Иван Панченко - Слабо-структурированные данные...
2015-12-05 Александр Коротков, Иван Панченко - Слабо-структурированные данные...
HappyDev
 
Михаил Трошев — CSS: Систематизация базовых знаний
Михаил Трошев — CSS: Систематизация базовых знанийМихаил Трошев — CSS: Систематизация базовых знаний
Михаил Трошев — CSS: Систематизация базовых знанийYandex
 
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
View как чистая функция от состояния базы данных  - Илья Беда, bro.agencyView как чистая функция от состояния базы данных  - Илья Беда, bro.agency
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
it-people
 
Формальные методы защиты приложений
Формальные методы защиты приложенийФормальные методы защиты приложений
Формальные методы защиты приложений
Positive Hack Days
 
MariaDB 10.1 - что нового.
MariaDB 10.1 - что нового.MariaDB 10.1 - что нового.
MariaDB 10.1 - что нового.
Sergey Petrunya
 
Расширение библиотеки Slick
Расширение библиотеки SlickРасширение библиотеки Slick
Расширение библиотеки Slick
Арсений Жижелев
 
Реализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoРеализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoMagecom Ukraine
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6Technopark
 
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Vladimir Kochetkov
 
MySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации баговMySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации багов
Sveta Smirnova
 
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
pgdayrussia
 
User Defined Materials in LS-DYNA
User Defined Materials in LS-DYNAUser Defined Materials in LS-DYNA
User Defined Materials in LS-DYNA
Yury Novozhilov
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVM
Tech Talks @NSU
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
Яковенко Кирилл
 

Similar to Hacking PostgreSQL. Физическое представление данных (20)

Поиск? Sphinx!
Поиск? Sphinx!Поиск? Sphinx!
Поиск? Sphinx!
 
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 2...
 
Расширяемость PostgreSQL для хакеров и архитекторов / Олег Бартунов, Александ...
Расширяемость PostgreSQL для хакеров и архитекторов / Олег Бартунов, Александ...Расширяемость PostgreSQL для хакеров и архитекторов / Олег Бартунов, Александ...
Расширяемость PostgreSQL для хакеров и архитекторов / Олег Бартунов, Александ...
 
Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...
 
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс Сервер
 
2015-12-05 Александр Коротков, Иван Панченко - Слабо-структурированные данные...
2015-12-05 Александр Коротков, Иван Панченко - Слабо-структурированные данные...2015-12-05 Александр Коротков, Иван Панченко - Слабо-структурированные данные...
2015-12-05 Александр Коротков, Иван Панченко - Слабо-структурированные данные...
 
Михаил Трошев — CSS: Систематизация базовых знаний
Михаил Трошев — CSS: Систематизация базовых знанийМихаил Трошев — CSS: Систематизация базовых знаний
Михаил Трошев — CSS: Систематизация базовых знаний
 
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
View как чистая функция от состояния базы данных  - Илья Беда, bro.agencyView как чистая функция от состояния базы данных  - Илья Беда, bro.agency
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
 
Формальные методы защиты приложений
Формальные методы защиты приложенийФормальные методы защиты приложений
Формальные методы защиты приложений
 
MariaDB 10.1 - что нового.
MariaDB 10.1 - что нового.MariaDB 10.1 - что нового.
MariaDB 10.1 - что нового.
 
Расширение библиотеки Slick
Расширение библиотеки SlickРасширение библиотеки Slick
Расширение библиотеки Slick
 
Реализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoРеализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в Magento
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
 
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!
 
MySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации баговMySQL Test Framework для поддержки клиентов и верификации багов
MySQL Test Framework для поддержки клиентов и верификации багов
 
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
PG Day'14 Russia, PostgreSQL как платформа для разработки приложений, часть 3...
 
User Defined Materials in LS-DYNA
User Defined Materials in LS-DYNAUser Defined Materials in LS-DYNA
User Defined Materials in LS-DYNA
 
Tech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVMTech Talks @NSU: Как приручить дракона: введение в LLVM
Tech Talks @NSU: Как приручить дракона: введение в LLVM
 
Как приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVMКак приручить дракона: введение в LLVM
Как приручить дракона: введение в LLVM
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
 

Hacking PostgreSQL. Физическое представление данных

Editor's Notes

  1. Прежде, чем говорить о физическом хранении данных в базе, надо сначала понять, какие же собственно объекты могут в ней находиться. Обратимся к нашему любимому каталогу. В этой лекции самым полезным и интересным будет pg_class. В этом каталоге описываются таблицы и практически всё, что имеет колонки или каким-то образом подобно таблице. У каждого relation есть уникальный идентификатор OID.
  2. OID или object indentificator, вообще говоря, есть не только у отношений, но у любого объекта PostgreSQL. Объектами являются сами базы данных, отношения, функции, типы данных и так далее. Каждому элементу enum в постгресе тоже присваивается отдельный OID. Глубоко внутри OID это всего лишь unsigned int, но небольшой набор правил превращает его в фундаментальный тип данных постгреса. Итак OID со значением 0 обозначает невалидный OID. Первые 10 тысяч значений зарезервированы для назначения вручну предопределенных OID. Используются они, например, в файлах src/include/catalog Значения от 10 тысяч до 16383 (совершенно необъяснимое магическое число) зарезервированы для назначения в процессе работы initdb. Значения OID начиная с 16384 назначаются генератором OID в процессе обычной работы сервера. Unsigned int содержит много значений, но всё-таки не бесконечно. Поэтому иногда происходит wraparound генератора OID, при этом значения от 0 до FirstNormalObjectId пропускаются.
  3. При создания нового объекта (кроме объектов отношений), нужно сначала сгенерировать для него OID. Функция GetNewOid генерирует OID, уникальный в пределах заданного отношения. Например для создания новой базы нужно вызвать GetNewOid от таблицы каталога pg_database. Уникальность обеспечивается тем, что на всех соответствующих таблицах каталога есть уникальный индекс. При создании relation, OID, если нужно, назначается функцией GetNewRelFileNode. Про то, что такое relfilenode чуть позже. Обе эти функции вызывают внутренний генератор GetNewObjectId, который получает значение nextOid из глобального для всего кластера счетчика OID. Зачем я вам всё это рассказываю? С практической стороны глобальные OID — одно из препятствий, которое нужно преодолеть, для реализации бэкапа отдельной базы.
  4. Если вы создаете новую запись в системном каталоге вручную, например добавляете функцию в pg_proc, нужно выбрать для неё OID и вписать его в строку самостоятельно. Скрипт unused_oids помогает найти свободные для использования OID. Если для некоторых целей вам понадобился целый набор OID, лучше выбрать последовательные значения. Скрипт duplicate_oids можно использовать для проверки уникальности OID. Например, после merge.
  5. Некоторые таблицы каталога содержат системную скрытую колонку OID, чтобы вывести её, надо явно задать её в select. Select * не выдаст вам oid. Для удобства есть различные alias для OID. Например regclass. Помимо regclass есть ещё regproc, regtype и другие типы идентификаторов, которые соответствуют разным таблицам каталога.
  6. Если вы создаете новую запись в системном каталоге вручную, например добавляете функцию в pg_proc, нужно выбрать для неё OID и вписать его в строку самостоятельно. Скрипт unused_oids помогает найти свободные для использования OID. Если для некоторых целей вам понадобился целый набор OID, лучше выбрать последовательные значения. Скрипт duplicate_oids можно использовать для проверки уникальности OID. Например, после merge.
  7. Postgres работает поверх файловой системы. Данные, относящиеся к одному инстансу postgres лежат в директории data. Её расположение можно задать переменной окружения $PGDATA. Эта директория содержит несколько управляющих файлов и поддиректорий, каждая из которых имеет особое назначение. Сегодня мы будем говорить не про все из них, а только про те, которые содержат непосредственно данные пользователя базы или управляют их физической структурой. Файлы журналов, поддержку транзакционности, статистику и много других интересных разделов отложим до следующих занятий, хотя физически все эти данные также по умолчанию лежат в директории PGDATA. Кстати, недавно найденный баг pg_basebackup в Debian. Конфиги там лежат отдельно, и большинство утилит постгреса умеют это понимать, а вот pg_basebackup что-то делает неправильно. Опять же, когда он создается с шаблонным файлом postgesql.conf, тот ложится в pgdata (как на других системах), а не к остальным конфигам.
  8. В директории global лежат данные, общие для всех баз данного инстанса. А именно: pg_control — позиция последнего checkpoint, необходимая для WAL. При запуске восстановления сервер в первую очередь проверяет файл pg_global. Если кому-то интересно, что конкретно там лежит заглядывайте в файл src/include/catalog/pg_control.h pg_filenode.map Для большинства таблиц физическое расположение файла определяется записью в pg_class.relfilenode. Очевидно, что для самого pg_class это не работает. На самом деле не только для pg_class, но и для некоторых других базовых и глобальных relation. Маппингом для них занимается pg_filenode.map. src/backend/utils/cache/relmapper.c pg_internal.init — файл, который используется для ускорения загрузки бэкенда.
  9. Давайте узнаем, что за куча файлов лежит в pg_global. Выберем из pg_class всё, что относится к tablespace global. Я не буду подробно говорить про все эти файлы. Это таблицы каталога и индексы на них. Отмечу только, что relfilenode у них равен нулю. Это значит, что маппингом этих файлов занимается тот самый pg_filenode.map, про который мы узнали на предыдущем слайде.
  10. Просто продолжение таблички с предыдущего слайда.
  11. Табличные пространства позволяют администратору управлять дисковым пространством для инсталляции PostgreSQL. Это полезно минимум по двум причинам. Во-первых, это нехватка места в разделе, на котором был инициализирован кластер и невозможность его расширения. Табличное пространство можно создать в другом разделе и использовать его до тех пор, пока не появится возможность переконфигурирования системы. Even though located outside the main PostgreSQL data directory, tablespaces are an integral part of the database cluster and cannot be treated as an autonomous collection of data files. They are dependent on metadata contained in the main data directory, and therefore cannot be attached to a different database cluster or backed up individually. Similarly, if you lose a tablespace (file deletion, disk failure, etc), the database cluster might become unreadable or unable to start. Placing a tablespace on a temporary file system like a RAM disk risks the reliability of the entire cluster.
  12. Давайте наконец вернемся к нашим базам. Они лежат в поддиректории base. Посмотрим её содержимое. Здорово. Но непонятно. Здесь нам на помощь приходит скрипт oid2name. ... Стало значительно лучше. Три стандартных базы, которые есть в любом постгресе и ещё одна пользовательская.
  13. Можно развлекаться с oid2name. Можно воспользоваться встроенными функциями для маппинга имени relation в файл.
  14. Здорово. Но непонятно. Здесь нам на помощь приходит скрипт oid2name. Рассказать про его работу. Стало значительно лучше. Три стандартных базы, которые есть в любом постгресе и ещё одна пользовательская.
  15. Здорово. Но непонятно. Здесь нам на помощь приходит скрипт oid2name. Рассказать про его работу. Стало значительно лучше. Три стандартных базы, которые есть в любом постгресе и ещё одна пользовательская.
  16. Здорово. Но непонятно. Здесь нам на помощь приходит скрипт oid2name. Рассказать про его работу. Стало значительно лучше. Три стандартных базы, которые есть в любом постгресе и ещё одна пользовательская.
  17. При выполнении некоторых операций, таких как truncate, cluster, relfilenode меняется, в то время как OID остается прежним.
  18. В коде есть структура relfilenode, которая содержит всё, что нужно для физического доступа к relation. Здесь мы рассматриваем relation как нечто атомарное, хотя как мы увидим дальше и он разделен на много разных файлов.
  19. В Berkley Postgres было реализовано несколько различных storage managers. Они не входили во внешние релизы Postgres. Теперь осталась только одна реализация storage manager - (magnetic disk). Название, впрочем, уже не отражает суть. До сих пор есть возможность написать другой storage manager. Честно говоря, я не очень активно слежу за рассылками, но не слышала, чтобы кто-то этим интересовался. В berkley каждый relation имел тэг, который связывал его с smgr. Сейчас этого нет. И если когда-нибудь будет реализован новый smgr, наверное лучше связывать их с tablespace. smgr.c — переключение между различными smgr, управление кэшем SmgrRelation md.c — реализация слоя между API smgr и API файловой системы.
  20. * each data file (heap or index) is divided into postgres disk blocks * (which may be thought of as the unit of i/o -- a postgres buffer * contains exactly one disk block). the blocks are numbered * sequentially, 0 to 0xFFFFFFFE. * * InvalidBlockNumber is the same thing as P_NEW in buf.h. * * the access methods, the buffer manager and the storage manager are * more or less the only pieces of code that should be accessing disk * blocks directly. * this is a storage type for BlockNumber. in other words, this type * is used for on-disk structures (e.g., in HeapTupleData) whereas * BlockNumber is the type on which calculations are performed (e.g., * in access method code). * * there doesn't appear to be any reason to have separate types except * for the fact that BlockIds can be SHORTALIGN'd (and therefore any * structures that contains them, such as ItemPointerData, can also be * SHORTALIGN'd). this is an important consideration for reducing the * space requirements of the line pointer (ItemIdData) array on each * page and the header of each heap or index tuple, so it doesn't seem * wise to change this without good reason.
  21. Есть 4 типа форков.
  22. Код для создания и удаления физического хранилища для relation. Создается только главный форк, остальные создаются только в момент, когда они нужны. Эта функция транзакционна. Если транзакция отменена, storage будет удален. В то же время, drop table удаляет файлы не сразу, а только после коммита транзакции Since most code wants to access the main fork, a shortcut version of ReadBuffer that accesses MAIN_FORKNUM is provided in the buffer manager for convenience.
  23. FSM обновлена в версии 8.4. FSM — бинарное дерево. Для каждой страницы хранится количество свободного места с гранулярностью 1/256. То есть freespace деленное на BLCKSZ/256. Плюсы: Чтобы узнать, что страницы с таким количеством места нет — достаточно проверить root.
  24. Если кто-то хочет быстрой славы) Можете поправить выравнивание этого комментария)