Risoluzione di chiavi esterne: cicli di interruzione per abilitare un ordinamento topologico

2

Sfondo per evitare il problema XY: sto costruendo un sistema di migrazione del database che deve risolvere i vincoli delle chiavi esterne (vedi qui per lo sfondo completo). Ho bisogno di determinare quale ordine posso eseguire creare tabelle / modificare le operazioni della tabella in modo da non violare alcun vincolo di chiave esterna. Un ordinamento topologico è un punto di partenza naturale, tranne per il fatto che un database può avere vincoli circolari che un tipico algoritmo di ordinamento topologico non può gestire.

Ci sono già alcune domande in questo senso, e il suggerimento più comune che vedo qui è semplicemente rimuovere i vincoli di chiave esterna e aggiungerli separatamente in seguito. Questa non è la soluzione che sto cercando, perché così facendo si ottengono il doppio delle operazioni di modifica delle tabelle, che è particolarmente importante evitare per tabelle di grandi dimensioni. Per quanto possibile vorrei ridurre al minimo il numero totale di comandi CREATE / ALTER necessari per migrare il database, il che richiede di essere intelligente su di esso.

Ovviamente, nel caso di vincoli di chiave esterna circolare, l'unica opzione è aggiungere le chiavi esterne separatamente. Di conseguenza, l'approccio generale che sto cercando è un approccio in due parti: identificare i vincoli circolari e "interromperli" contrassegnando i vincoli di chiave esterna da aggiungere successivamente, eseguire un ordinamento topologico standard sulle restanti operazioni, aggiornare il database in ordine topologico e infine applicare eventuali vincoli in sospeso che sono stati riservati per dopo. Ho trovato molti esempi di algoritmi di ordinamento topologico e riferimenti ad algoritmi che possono aiutare a identificare i bordi da "spezzare" per abilitare un algoritmo di ordinamento topologico standard, ma senza algoritmi effettivi per quest'ultimo.

Qualsiasi direzione sarebbe apprezzata, sia per il mio problema specifico che per il problema generale.

1 mese dopo: aggiornamento

Alcune settimane in, e ho imparato che ho davvero bisogno di risolvere questo problema. Sono andato con il suggerimento generale di migrare con la chiave esterna, in particolare dato suggerimenti che migliorerà le prestazioni generali. Lo stiamo utilizzando internamente da alcune settimane.

Sfortunatamente , non è una soluzione a prova di proiettile. Si scopre che ci sono casi limite in cui MySQL genera un errore 1215 anche con la verifica di chiavi esterne. Ho sempre avuto un piano da aggiungere in un linter MySQL sulle definizioni della tabella, e questo eviterà il verificarsi di questo caso limite. Esse si verificano principalmente a seguito della modifica della struttura per correggere gli elementi causati dagli sviluppatori che non sono stati abbastanza attenti durante la creazione iniziale delle tabelle. Indipendentemente da ciò, ora so che ci sono casi in cui l'ordine conta anche quando i controlli delle transazioni sono disattivati. Mentre stiamo implementando delle soluzioni istituzionali da parte nostra per evitare questi casi, voglio che questo sia uno strumento per tutti gli altri. Altri possono imbattersi in questi stessi casi limite, il che significa che ho bisogno di implementare un corretto ordinamento topologico, e non posso farlo senza identificare e interrompere i cicli. Per essere chiari, in questo caso i cicli di interruzione significano semplicemente contrassegnare i vincoli di chiave esterna da aggiungere dopo ogni altra cosa. Non deve essere intelligente. È sufficiente identificare quando l'aggiunta di un'operazione add foreign key al piano di migrazione comporterà un ciclo e rimandare l'operazione di aggiunta fino a dopo tutto il resto.

    
posta Conor Mancone 13.10.2017 - 16:01
fonte

3 risposte

1

Quello che stai chiedendo è essenzialmente il cosiddetto problema di arco di feedback , quindi trovare i bordi minimi necessari per essere rimosso dal grafico indotto dai vincoli FK è NP difficile. Esistono algoritmi effcienti menzionati in quell'articolo di Wikipedia, che non garantiscono di trovare il numero minimo di bordi, ma potrebbero essere sufficienti per il tuo caso.

Tuttavia, da un punto di vista pratico, a meno che tu non voglia utilizzare il tuo strumento di migrazione per centinaia di modelli di dati arbitrari, prenderei in considerazione un percorso più semplice (forse come primo passo). È comunque possibile creare uno strumento di migrazione generico che ottiene come input le "chiavi esterne per la migrazione differita" (o in termini di un digramma: i bordi da rimuovere per interrompere i cicli). Quindi, è possibile prendere uno schema di un modello di dati reali, identificare i cicli manualmente e decidere manualmente le chiavi esterne da selezionare per interrompere i cicli. Un tale strumento può essere utilizzato in produzione, anche quando non fa nulla di automatico.

In seguito, se pensi ancora che ne hai davvero bisogno, potresti implementare un algoritmo di rilevamento automatico per gli FK, usando il riferimento dall'alto.

    
risposta data 25.11.2017 - 16:07
fonte
1

Il backend optimizer dispone di diversi percorsi di accesso disponibili e un modello per quanti secondi ogni percorso aggiungerà al tempo di query trascorso. Cerca un grafico alla ricerca di piani con un costo stimato inferiore alla migliore stima corrente.

Mentre leggo i tuoi paragrafi, mi sembra una situazione analoga. I commenti sottolineano che c'è più di un modo per affrontare il tavolo FOO. Potremmo creare FOO1 vuoto, regolare i vincoli e gli indici di FOO1, (lentamente) inserire in FOO1 e rilasciare FOO seguito da rinomina di FOO1. Differenti approcci "equivalenti" potrebbero vincere per tavoli piccoli o grandi.

Se il tuo codice conosce il conteggio delle righe e ha un modello per i tempi di completamento dell'operazione, potrebbe esplorare molte alternative, incluse quelle nei commenti, e difendere la sua ultima linea di azione in base ai confronti del tempo di operazione.

Se una determinata migrazione includerà sia la modifica dei vincoli che la modifica (aumento) del numero di righe, disabilitare FK / inserire / abilitare FK potrebbe risultare vincente.

    
risposta data 25.11.2017 - 07:29
fonte
0

Perché è necessario anche questo? Se la convalida dei vincoli viene differita fino al commit, l'ordine delle operazioni DML non avrà importanza.

    
risposta data 26.10.2017 - 07:10
fonte

Leggi altre domande sui tag