Slide 1

Slide 1 text

Migrações de dados sem downtimes! Jéssica Bonson Principal Engineer no Olist TDC Porto Alegre 2020, Trilha Big Data Truques e lições aprendidas com PostgreSQL no Olist

Slide 2

Slide 2 text

Jéssica Pauli de C Bonson ● +-8 anos de exp em pesquisa/desenvolvimento ● graduação/mestrado em Ciências da Computação ● foco em dev backend, machine learning e big data Jogar RPG Livros Duolingo Hobbies:

Slide 3

Slide 3 text

Maior loja nos principais marketplaces do Brasil. Arquitetura em microsserviços e serverless. Python. Go. PostgreSQL. AWS. Kubernetes. 20+ APIs 120+ serviços 3m+ produtos 30k+ logistas 10m+ anúncios 230k+ pedidos por mês

Slide 4

Slide 4 text

● As migrações de dados são parte do processo de deploy. ○ Alterações nas tabelas ou nos dados ● Como executar as migrações? ○ Downtime X Runtime

Slide 5

Slide 5 text

Conceitos

Slide 6

Slide 6 text

DELETEs e UPDATEs no Postgres ● DELETEs não deletam dados, matam ● UPDATEs não atualizam dados, duplicam ● Por quê? ○ Rollback de transações ○ Diferentes visibilidades de dados ○ Permitir escrita em paralelo com leitura ● Resultado: Cemitério de linhas mortas

Slide 7

Slide 7 text

VACUUM ● É quem deleta ‘de verdade’ ● Não causa exclusive locks nas tabelas ● Só deleta dead rows quando não estão mais sendo usadas ● Na verdade, não deleta, só marca para reuso ○ Alternativa: VACUUM FULL

Slide 8

Slide 8 text

Autovacuum ● PostgreSQL sabe se virar ○ Um daemon checa as tabelas de tempos em tempos ○ Se necessário, roda o VACUUM ● Porém… transações lentas são um problema ○ VACUUM não consegue deletar as linhas ○ Causa table bloat

Slide 9

Slide 9 text

Table Bloat ● Live rows X Dead rows ● Se o VACUUM continuar sem conseguir rodar… ○ A tabela fica cada vez maior ○ VACUUM leva mais tempo ○ Performance da API piora ● Se for um problema recorrente, tunar o autovacuum

Slide 10

Slide 10 text

heroku pg:vacuum_stats DATABASE_URL --app https://github.com/heroku/heroku-pg-extras

Slide 11

Slide 11 text

Locks Locks

Slide 12

Slide 12 text

Migrações para atualização de dados

Slide 13

Slide 13 text

Antes UPDATE product SET currency = 'BRL' WHERE currency is Null;

Slide 14

Slide 14 text

● Fazer a atualização registro a registro ● Dividir a migração em lotes Como resolver?

Slide 15

Slide 15 text

SELECT id FROM product WHERE currency is Null LIMIT :limit; Depois UPDATE product SET currency = 'BRL’ WHERE id = :id;

Slide 16

Slide 16 text

Migrações para alteração de tabelas (PostgreSQL < 11)

Slide 17

Slide 17 text

ALTER TABLE freight ADD COLUMN enable_subsidy boolean NOT NULL DEFAULT FALSE; Antes

Slide 18

Slide 18 text

● Dividir a migração em partes: ○ Exemplo: Criar campo com default False i. Criar campo novo nullable ii. Setar default da coluna para False iii. Setar valores do campo para False iv. Remover nullable Como resolver?

Slide 19

Slide 19 text

ALTER TABLE freight ADD COLUMN enable_subsidy boolean; ALTER TABLE freight ALTER COLUMN enable_subsidy SET DEFAULT FALSE; < Migração para alterar os valores do campo para FALSE > ALTER TABLE freight ALTER COLUMN enable_subsidy SET NOT NULL; Depois

Slide 20

Slide 20 text

Migrações para alteração de tabelas (PostgreSQL >= 11)

Slide 21

Slide 21 text

ALTER TABLE freight ADD COLUMN enable_subsidy boolean NOT NULL DEFAULT FALSE; Quase instântaneo!

Slide 22

Slide 22 text

Réplicas

Slide 23

Slide 23 text

Trade-offs ● Custo x Benefício ○ Melhor performance de leitura ○ Alta disponibilidade ○ Tolerância a falhas ○ Custo maior ○ Performance de escrita vs Consistência dos dados

Slide 24

Slide 24 text

Monitoramento

Slide 25

Slide 25 text

PgHero

Slide 26

Slide 26 text

Elastic APM

Slide 27

Slide 27 text

CloudWatch (AWS)

Slide 28

Slide 28 text

Dicas e Precauções

Slide 29

Slide 29 text

Django ● Testar tempo da migração localmente ○ time python manage.py migrate ● Verificar o SQL que será executado ○ python manage.py sqlmigrate

Slide 30

Slide 30 text

Modelagem do BD ● UPDATE vs INSERT ● Estrutura das tabelas de histórico ● CREATE INDEX CONCURRENTLY vs CREATE INDEX

Slide 31

Slide 31 text

Precauções ● Antes da migração… ○ Evitar executar em horário de pico ○ Lidar com queries longas em execução ○ Criar backup do banco de dados ○ Avisar os outros developers

Slide 32

Slide 32 text

Valeu! @jpbonson

Slide 33

Slide 33 text

Referências https://www.citusdata.com/blog/2018/02/15/when-postgresql-blocks/ http://pankrat.github.io/2015/django-migrations-without-downtimes/ https://momjian.us/main/writings/pgsql/nulls.pdf https://www.citusdata.com/blog/2018/02/22/seven-tips-for-dealing-with-postgres-locks/ https://www.cybertec-postgresql.com/en/a-beginners-guide-to-postgresqls-update-and-autovacuum/ https://devcenter.heroku.com/articles/managing-vacuum-on-heroku-postgres https://www.datadoghq.com/blog/postgresql-vacuum-monitoring/ https://www.cybertec-postgresql.com/en/reasons-why-vacuum-wont-remove-dead-rows/ https://www.percona.com/blog/2018/08/06/basic-understanding-bloat-vacuum-postgresql-mvcc/ https://blog.timescale.com/scalable-postgresql-high-availability-read-scalability-streaming-replication-fb95023e2af/ https://realpython.com/create-django-index-without-downtime/ http://www.interdb.jp/pg/pgsql06.html https://stackoverflow.com/questions/1113277/how-do-i-do-large-non-blocking-updates-in-postgresql https://www.devmedia.com.br/transacoes-no-postgresql-locks-e-bloqueios/5164 https://www.postgresql.org/docs/current/transaction-iso.html https://www.percona.com/blog/2018/10/16/postgresql-locking-part-1-row-locks/