2012-05-15 9 views
6

Sto memorizzando le gerarchie del file system di directory e file.Eliminazione a cascata della tabella dati e della tabella di ricerca contemporaneamente

In una tabella innodb, memorizzo i dettagli di ogni directory/file e mantengo la relazione padre figlio con un vincolo di chiave esterna che si sovrapporrà all'eliminazione.

Una tabella myisam viene utilizzata per cercare queste directory/file con una ricerca di testo completo. Contiene i nomi e gli ID di ogni riga.

Qualsiasi riga nella tabella dati (tabella innodb) avrà una riga corrispondente nella tabella di ricerca (tabella myisam) e l'aggiunta o la rimozione di righe dalla tabella dati deve essere riflessa nella tabella di ricerca.

Sto cercando di trovare la soluzione migliore per mantenere la coerenza dei dati tra le due tabelle quando si elimina una directory padre. Il tavolo innodb va bene. Elimina il genitore, l'eliminazione passa in cascata attraverso i bambini fino a quando non vengono tutti eliminati. L'eliminazione delle righe corrispondenti dalla tabella myisam è più difficile.

Il mio primo pensiero è stato quello di utilizzare un trigger on-delete sulla tabella innodb. Quando una riga viene cancellata, cancella la riga corrispondente dalla tabella myisam. Tuttavia, poiché MySQL non attiva i trigger durante l'eliminazione a cascata (un bug noto per 7 anni che è stato risolto citando la mancanza di supporto nel manuale), questa non è un'opzione.

Il mio secondo pensiero è stato mettere una relazione padre figlio nella tabella di ricerca, ma è una tabella myisam per supportare la funzionalità di ricerca di testo completo, e quindi non supporta i vincoli di chiave esterna.

Avevo sentito che innodb ora supporta ricerche di testo completo, quindi ho pensato che forse potevo cambiare il motore della tabella di ricerca, ma è disponibile solo nella versione di laboratorio.

Il mio ultimo pensiero è stato quello di abbandonare i vincoli di chiave esterna e utilizzare solo i trigger per mantenere la coerenza dei dati. Su cancella, cancella sia dalla tabella di innodb che di myisam dove parent = OLD.id. Tuttavia, per evitare loop infiniti che potrebbero corrompere tutti i dati nella tabella, MySQL non supporta la manipolazione dei dati nella stessa tabella che ha attivato il trigger.

Ho fatto ricorso al recupero a livello di codice di tutti i bambini nella directory principale attraverso un ciclo di richieste, tuttavia, ritengo che ci sia un'opzione migliore. C'è qualche altro lavoro che potrebbe essere più efficiente? A questo punto, le uniche due opzioni a cui posso pensare sono in attesa che uno degli approcci precedenti venga corretto o modificato su un RDBMS diverso come PostgreSQL che supporta i trigger di attivazione da un'eliminazione a cascata.

Qualsiasi altra idea sarebbe molto apprezzata.

+0

Non sono sicuro di averlo capito, sono piuttosto confuso riguardo alla relazione tra due tabelle, quello che ottengo è definire una relazione tra due tabelle che hanno un tipo diverso l'una dall'altra. L'ho già provato e ho riscontrato dei problemi nel mantenimento della coerenza dei dati, se si desidera mantenere la coerenza dei dati attraverso la relazione della tabella con l'utente di chiavi esterne e primarie utilizzare innodb su tutte le tabelle in cui si definirà la relazione. –

+0

la tabella di ricerca (myisam) viene utilizzata come motore di ricerca per la tabella di dati (innodb). Ma poiché le directory con sottodirectory e file vengono cancellate, le modifiche devono riflettersi sia nella tabella dei dati sia nella tabella di ricerca. Non posso usare innodb per il motore di ricerca a causa della mancanza di supporto per la ricerca di testo completo (almeno, al momento). La relazione è definita bene nella tabella dati, ma le eliminazioni non si riflettono nella tabella di ricerca. – JayceTDE

+0

+1 per una domanda ben scritta; sfortunatamente non vedo alternative al tuo approccio attuale, ma forse qualcun altro troverà qualcosa – Daan

risposta

1

Questi tipi di mal di testa sono esattamente la cosa che mi ha fatto allontanare da mysql dove possibile.

... mi sembra che vi ha ottenuto di essere una scelta migliore ...

Purtroppo non c'è. Il semplice problema è che non è possibile eliminare la cascata e avere mysql sapere cosa ha appena eliminato. Quindi la tua unica opzione è scoprire che cosa sta per eliminare prima di farlo (questo è l'algoritmo che hai suggerito alla fine).

Poiché il collegamento in cascata interromperà i dati, non utilizzare una chiave on update cascade in modo che il tentativo di eliminare una directory padre senza eliminare il figlio abbia esito negativo.

Si consiglia di creare una procedura per eseguire il sollevamento pesante (eliminazione). Ciò impedirà un I/O di grandi dimensioni tra la tua app e il DB durante la sua scomparsa attraverso tutte le directory. Iy fornirà anche un codice comune per farlo se accederai mai allo stesso db attraverso un'app diversa (o semplicemente vuoi fare qualcosa manualmente).

Come ho affermato prima, utilizzo Postgresql principalmente in questi giorni. Questo è un esempio del perché.