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

Oops ho sovrascritto le tue modifiche

Oops ho sovrascritto le tue modifiche

Mai capitato di sovrascrivere dati involontariamente dall’interfaccia web o tramite il pannello di amministrazione di una applicazione Django? In questo talk vedremo qualche strategia per ovviare al problema.

Vedremo delle strategie generiche come salvare un log delle nostre modifiche, fare il locking delle righe del database oppure usare la concorrenza ottimistica. Quindi vedremo una strategia specifica di PostgreSQL implementando un sistema di concorrenza ottimistica per le modifiche fatte da utenti tramite il pannello di amministrazione di Django.

Riccardo Magliocchetti

June 06, 2022
Tweet

More Decks by Riccardo Magliocchetti

Other Decks in Programming

Transcript

  1. Capita solo da admin? # processo 1 # processo 2

    t = Talk.objects.get( name=”oops” ) t.done = True Talk.objects.update( name=”more oops” ) t.save()
  2. In questo caso è facile # processo 1 # processo

    2 t = Talk.objects.get( name=”oops” ) t.done = True Talk.objects.update( name=”more oops” ) t.save(update_fields=["done"])
  3. Ad ogni aggiornamento o cancellazione di un modello serializzo la

    versione precedente con un nome di versione e dei metadati. Con lo storico delle modifiche è possibile provare a ripristinare i dati.
  4. Salvare un log delle modifiche: recap abbiamo un log di

    audit incluso abbiamo una buona chance di ripristinare i dati
  5. Locking delle righe: recap risolviamo corse critiche sull'aggiornamento non possiamo

    tenere il lock troppo a lungo per mantenere concorrenza
  6. Concorrenza in PostgreSQL MVCC (Multi-Version Concurrency Control): alla modifica di

    una riga si crea una nuova riga con id di transazione maggiore e poi il VACUUM elimina quelle vecchie
  7. xmin in Django from django.db import models from django.db.models import

    Expression class XMin(Expression): output_field = models.PositiveIntegerField() def as_postgresql(self, compiler, connection): return f'"{compiler.query.base_table}"."xmin"', () Talk.objects.all().annotate(row_version=XMin())
  8. Problema: corsa critica tra admin e sistema ad eventi Condizioni

    basta impedire l'override di modifiche da admin basta che funzioni su PostgreSQL
  9. riduce la possibilità di sovrascrivere dati tramite l'admin implementa concorrenza

    ottimistica su PostgreSQL senza modificare i modelli semplice: due mixin da usare, 62 righe in totale django-optimistic-admin-pg
  10. from optimisticadmin.mixins import OptimisticAdminModelFormM class TalkForm(OptimisticAdminModelFormMixin, forms.ModelFor row_version = forms.IntegerField(

    required=False, widget=forms.HiddenInput() ) from optimisticadmin.mixins import OptimisticAdminMixin from .forms import TalkForm @admin.register(Talk) class TalkAdmin(OptimisticAdminMixin, admin.ModelAdmin): form = TalkForm
  11. Conclusioni tenere un log delle modifiche per evitare di perdere

    dati usare dei lock per serializzare gli aggiornamenti implementare un sistema di concorrenza ottimistica
  12. Conclusioni strategia rischio tradeoff quando Log modifiche no robusta audit,

    recovery Locking righe no robusta assegnazione risorse, soldi :) Concorrenza ottimistica si perf poco rischio di collisione Una combinazione delle precedenti
  13. Riferimenti con implementazione semplice di concorrenza ottimistica su PostgreSQL ed

    API con Django Rest Framework di Haki Benita su concorrenza pessimistica vs ottimistica su concorrenza MVCC di PostgreSQL MVCC PostgreSQL Articolo articolo articolo Heroku Documentazione ufficiale