Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How not to step on elephant’s trunk

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

How not to step on elephant’s trunk

Avatar for Sergey Ponomarev

Sergey Ponomarev

November 15, 2018

More Decks by Sergey Ponomarev

Other Decks in Programming

Transcript

  1. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup FACTS ‣ The largest land

    animal in the world ‣ They are fast ‣ They are clever 9
  2. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup TRUNK IS THE FEATURE ‣

    Extremely functional ‣ Extremely complex ‣ Essential for elephants’ life 10
  3. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup RELATIONAL DATABASE ‣ records are

    organised into rows ‣ group of records are organised into tables ‣ attributes are stored in table columns ‣ there is an ability to define relationships ‣ query language is provided, usually SQL 15
  4. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup ATOMICITY CREATE TABLE test (id

    SERIAL PRIMARY KEY); BEGIN; INSERT INTO test VALUES (1); INSERT INTO test VALUES (2); COMMIT; BEGIN; INSERT INTO test VALUES (3); INSERT INTO test VALUES (4); ROLLBACK; SELECT * FROM test; -- id -- ---- -- 1 -- 2 -- (2 rows) 17
  5. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup CONSISTENCY Column | Type |

    Modifiers --------+---------+--------------------------------------------------- id | integer | not null default nextval('test_id_seq' ::regclass) Indexes: "test_pkey" PRIMARY KEY, btree (id) BEGIN; INSERT INTO test VALUES (1); INSERT INTO test VALUES (2); COMMIT; BEGIN; INSERT INTO test VALUES (2); -- ERROR: duplicate key value violates unique constraint "test_pkey" -- DETAIL: Key (id)=(2) already exists. ROLLBACK; 18
  6. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup ISOLATION BEGIN; INSERT INTO test

    VALUES (1); INSERT INTO test VALUES (2); -- Concurrent call proceeds here COMMIT; -- Concurrent call SELECT COUNT(*) FROM test; -- 0 19
  7. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup DURABILITY BEGIN; INSERT INTO test

    VALUES (4); COMMIT; -- COMMIT -- Time: 3.089 ms • Сбой в оборудовании • Отключение электричества 
 20
  8. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup $ df -h Filesystem Size

    Used Avail Use% Mounted on /dev/sda1 500G 467G 33G 93% / udev 64M 0 64M 0% /dev tmpfs 1000M 0 1000M 0% /sys/fs/cgroup shm 64M 0 64M 0% /dev/shm tmpfs 1000M 0 1000M 0% /proc/acpi tmpfs 1000M 0 1000M 0% /sys/firmware 23
  9. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup ❓❓❓ $ df -h Filesystem

    Size Used Avail Use% Mounted on /dev/sda1 500G 467G 33G 93% / udev 64M 0 64M 0% /dev tmpfs 1000M 0 1000M 0% /sys/fs/cgroup shm 64M 0 64M 0% /dev/shm tmpfs 1000M 0 1000M 0% /proc/acpi tmpfs 1000M 0 1000M 0% /sys/firmware 25
  10. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup ALTERNATIVE REALITY Schema | Name

    | Type | Owner | Size --------+-------------------+-------+----------+------- public | records | table | app | 100G 26 UPDATE records SET type = 'legacy'; -- UPDATE 3133731337 Schema | Name | Type | Owner | Size --------+-------------------+-------+----------+------- public | records | table | app | 197G
  11. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup DISK LAYOUT ‣ 8kb pages

    ‣ One page consist of one or more records/rows = tuples ‣ Tuple is “immutable” ‣ UPDATE = INSERT + DELETE 29
  12. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup TUPLE ‣ ctid – page

    id and index on that page ‣ xmin – insert transaction id ‣ xmax – “delete” transaction id 30
  13. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup TUPLE 31 BEGIN; SELECT txid_current();

    -- 31337 INSERT INTO test VALUES (DEFAUL, 30); SELECT ctid, *, xmin, xmax FROM test;
  14. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup TUPLE 32 -- Simply SELECT

    * FROM test; -- Is equal SELECT * FROM test WHERE xmin <= txid_current() AND (xmax = 0 OR txid_current() < xmax);

  15. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup VACUUM 35 VACUUM VERBOSE records;

    INFO: vacuuming "public.records" INFO: index "records_pkey" now contains 471203743 row versions in 2352308 pages DETAIL: 0 index row versions were removed. 999999 index pages have been deleted, 999999 are currently reusable. CPU 0.00s/0.00u sec elapsed 0.00 sec. INFO: index "index_records_user_id" now contains 471203743 row versions in 23423 pages DETAIL: 0 index row versions were removed. 0 index pages have been deleted, 0 are currently reusable. Skipped 0 pages due to buffer pins. 0 pages are entirely empty. CPU 2425.00s/0.00u sec elapsed 2525.00 sec. VACUUM …………
  16. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup ❓❓❓ $ df -h Filesystem

    Size Used Avail Use% Mounted on /dev/sda1 500G 467G 33G 93% / udev 64M 0 64M 0% /dev tmpfs 1000M 0 1000M 0% /sys/fs/cgroup shm 64M 0 64M 0% /dev/shm tmpfs 1000M 0 1000M 0% /proc/acpi tmpfs 1000M 0 1000M 0% /sys/firmware 36
  17. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup VACUUM FULL 38 VACUUM FULL

    VERBOSE records; INFO: vacuuming "public.records" INFO: index "records_pkey" now contains 471203743 row versions in 2352308 pages DETAIL: 0 index row versions were removed. 999999 index pages have been deleted, 999999 are currently reusable. CPU 0.00s/0.00u sec elapsed 0.00 sec. INFO: index "index_records_user_id" now contains 471203743 row versions in 23423 pages DETAIL: 0 index row versions were removed. 0 index pages have been deleted, 0 are currently reusable. Skipped 0 pages due to buffer pins. 0 pages are entirely empty. …………
  18. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup SOLUTIONS ‣ Copy to another

    table ‣ pg_repack ‣ AUTOVACUUM tuning for prevention ‣ 40
  19. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup EXPLAIN SELECT * FROM records

    WHERE user_id = 31337; QUERY PLAN ------------------------------------------------------------------- ---- Seq Scan on records (cost=0.00 ..239783.28 rows=174 width=195) Filter: (user_id = 31337) 42
  20. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup ✅ ✅ ✅ EXPLAIN SELECT

    * FROM records WHERE user_id = 31337; QUERY PLAN ------------------------------------------------------------- Index Scan using index_records_user_id on records (cost=0.43 ..524.33 rows=174 width=195) Index Cond: (user_id = 31337) 47
  21. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup PROBLEM \d users; Table "public.users"

    Column | Type | Collation | Nullable | Default --------+------------------------+-----------+----------+--------- id | integer | | not null | email | character varying(256) | | not null | trial | boolean | | | Three states of ‘trial’ – true, false, NULL 49
  22. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup TABLE-LEVEL LOCKS ‣ ACCESS SHARE

    // SELECT ‣ ROW SHARE // SELECT FOR UPDATE, FOR SHARE ‣ ROW EXCLUSIVE // UDPATE, DELETE, INSERT ‣ SHARE UPDATE EXCLUSIVE // VACUUM, ALTER, CREATE INDEX CONCURRENTLY ‣ SHARE // CREATE INDEX ‣ SHARE ROW EXCLUSIVE // ALTER ‣ EXCLUSIVE // REFRESH MATERIALIZED VIEW ‣ ACCESS EXCLUSIVE // DROP, TRUNCATE, VACUUM FULL, ALTER TABLE 54
  23. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup SOLUTION ALTER TABLE users ADD

    CONSTRAINT not_null_trial CHECK (trial IS NOT NULL) NOT VALID; ALTER TABLE users VALIDATE CONSTRAINT not_null_trial; 56
  24. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup RESULT \d users; Table "public.users"

    Column | Type | Collation | Nullable | Default --------+------------------------+-----------+----------+--------- id | integer | | not null | email | character varying(256) | | not null | trial | boolean | | | Check constraints: "not_null_trial" CHECK (trial IS NOT NULL) 57
  25. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup PARANOID MODE ON 59 $

    rails c --sandbox Loading development environment in sandbox (Rails 5.2.0) Any modifications you make will be rolled back on exit [1] (rails_new) main: 0> User.count (17.7ms) SELECT COUNT(*) FROM "users" => 1 [2] (rails_new) main: 0> User.destroy_all User Load (0.4ms) SELECT "users".* FROM "users" (1.5ms) SAVEPOINT active_record_1 User Destroy (7.4ms) DELETE FROM "users" WHERE "users"."id" = $1 [["id", 1]] (0.7ms) RELEASE SAVEPOINT active_record_1 => [#] [3] (rails_new) main: 0> User.count (0.3ms) SELECT COUNT(*) FROM "users" => 0 [4] (rails_new) main: 0> (0.8ms) ROLLBACK
  26. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup SCENARIO ‣ $ rails -c

    sandbox ‣ User.count ‣ ☎ ‣ ALTER TABLE users ADD COLUMN lol VARCHAR; 61
  27. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup PG BIBLES ‣ Alexey Vasiliev

    – Safe and unsafe operations for high volume PostgreSQL ‣ Илья Космодемьянский – Внутреннее устройство PostgreSQL для практикующих инженеров ‣ Tom Lane – Transaction Processing in PostgreSQL ‣ Dmitri Fountaine – Mastering PostgreSQL in Application Development 65
  28. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup PARANOID MODE -- Limit potentially

    dangerous operations -- (inside current transaction) SET lock_timeout = X -- default: 0 -- Logging slow locks (server level) SET log_lock_waits = true -- default: false SET deadlock_timeout = 1s -- default: 1s 68
  29. @bufo_alvarius @sponomarev Tver.IO Philosophy Meetup CREDITS 72 Tusks | The.Rohit

    | Flickr Elephant bath | Tambako The Jaguar | Flickr Elephant, riding an elephant, man and asia HD photo by Jordi Ganduxe (@gandu) on Unsplash Not Wassana photo by Céline Haeberly (@celinehaeberly) on Unsplash elephant | elephant, tanzania | Andy Lederer | Flickr Elephants | Subash BGK | Flickr Elephant, animal, tusk and trunk HD photo by Jason Briscoe (@jbriscoe) on Unsplash Grey Elephant Throwing Sand With Trunk Near Green Trees · Free Stock Photo Elephant | Got a little too much soil with that one. | C. E. Timothy Paine | Flickr Elephant at Work-1& | Elephant at Work | John | Flickr