PostgreSQL offre una bella interfaccia BLOB che è ampiamente utilizzato. Tuttavia, recentemente ci siamo imbattuti in problemi affrontati da vari clienti, e ha senso riflettere un po ‘ e capire come PostgreSQL gestisce BLOB – e in particolare BLOB cleanup.
Utilizzando l’interfaccia BLOB PostgreSQL
In PostgreSQL, è possibile utilizzare vari mezzi per memorizzare dati binari. La forma più semplice è sicuramente quella di utilizzare il tipo di dati “bytea” (= byte array). In questo caso un campo binario è fondamentalmente visto come parte di una riga.
Ecco come funziona:
Come puoi vedere, questa è una colonna normale e può essere utilizzata proprio come una colonna normale. L’unica cosa che vale la pena menzionare è la codifica che si deve usare a livello SQL. PostgreSQL utilizza una variabile per configurare questo comportamento:
test=# SHOW bytea_output;bytea_output--------------hex(1 row)
La variabile bytea_output accetta due valori: “hex” dice a PostgreSQL di inviare i dati in formato hex. “escape” significa che i dati devono essere inseriti come una stringa ottale. Non c’è molto l’applicazione deve preoccuparsi qui, a parte la dimensione massima di 1 GB per campo.
Tuttavia, PostgreSQL ha una seconda interfaccia per gestire i dati binari: L’interfaccia BLOB. Permettetemi di mostrare un esempio di questo potente strumento in azione:
test=# SELECT lo_import('/etc/hosts');lo_import-----------80343(1 row)
In questo caso, il contenuto di /etc/hosts è stato importato nel database. Si noti che PostgreSQL ha una copia dei dati – non è un collegamento al filesystem. Ciò che è degno di nota qui è che il database restituirà l’OID (ID oggetto) della nuova voce. Per tenere traccia di questi OID, alcuni sviluppatori fanno quanto segue:
INSERT 0 1
Questo va assolutamente bene, a meno che tu non faccia qualcosa di simile qui sotto:
test=# DELETE FROM t_file WHERE id = 1;DELETE 1
Il problema è che l’id oggetto è stato dimenticato. Tuttavia, l’oggetto è ancora lì. pg_largeobject è la tabella di sistema incaricata di memorizzare i dati binari all’interno di PostgreSQL. Tutte le lo_functions parleranno semplicemente con questa tabella di sistema per gestire queste cose:
Perché è un problema? Il motivo è semplice: il tuo database crescerà e il numero di “oggetti morti” si accumulerà. Pertanto il modo corretto per uccidere una voce BLOB è il seguente:
Se dimentichi di scollegare l’oggetto, ne soffrirai a lungo termine – e lo abbiamo spesso visto accadere. Si tratta di un problema importante se si utilizza l’interfaccia BLOB.
vacuumlo: ripulire oggetti di grandi dimensioni morti
Tuttavia, come si può risolvere il problema una volta accumulati migliaia, o forse milioni, di BLOB morti? La risposta è uno strumento da riga di comando chiamato “vacuumlo”.
Creiamo prima una voce morta:
test=# SELECT lo_import('/etc/hosts');lo_import-----------80351(1 row)
Quindi possiamo eseguire vacuumlo da qualsiasi client:
Come puoi vedere, due oggetti morti sono stati uccisi dallo strumento. vacuumlo è il modo più semplice per pulire gli oggetti orfani.
Funzionalità aggiuntive
Tuttavia, non ci sono solo lo_import e lo_unlink. PostgreSQL offre una varietà di funzioni per gestire oggetti di grandi dimensioni in un modo carino:
Ci sono altre due funzioni che non seguono la convenzione di denominazione per ragioni storiche: loread e lowrite:
pg_catalog | loread | bytea | integer, integer | funcpg_catalog | lowrite | integer | integer, bytea | func
Sono funzioni i cui nomi non possono più essere facilmente modificati. Tuttavia, vale la pena notare che esistono.
Finalmente
L’interfaccia BLOB di PostgreSQL è davvero utile e può essere usata per molte cose. Il bello è che è completamente transazionale e quindi il contenuto binario e i metadati non possono più essere sincronizzati.
Se vuoi saperne di più sui trigger per applicare i vincoli in PostgreSQL, ti consigliamo di controllare il nostro post sul blog scritto da Laurenz Albe. Farà luce su questo importante argomento.