Ultimo aggiornamento: 30-Apr-2021

DB2 e IFS non sono due mondi lontani: i DataLinks

Introduzione

Gli sforzi dei laboratori di sviluppo di IBM per creare un’infrastruttura quanto più completa per la gestione dei dati in senso esteso (DB2 UDB Universal DataBase), avevano portato a introdurre la tecnologia dei Data Links nella V4R4.

Il concetto base che sta dietro al tipo dati datalink è creare un collegamento gestito dal DB2 tra record di tabelle del database e oggetti che non sono archiviati nel database e che risiedono p.es. in cartelle di IFS. Ma potrebbero anche trovarsi in file system Unix o Windows.

Per esempio: in una tabella di anagrafica prodotti potrei avere una colonna di tipo datalink per “linkare” il file con l’immagine residente in una cartella su IFS.

Il contenuto di un campo di tipo datalink è sostanzialmente un URL. Il DB2 e il DLFM (Data Links File Manager) garantiscono l’integrità e la coerenza dell’URL memorizzato nel database e l’oggetto a cui l’URL si riferisce.

Per esempio il DLFM garantisce che se un file dell’IFS è “linkato” al record del DB2, il file non può essere cancellato, spostato o ridenominato.

Il servizio DLFF (Data Links Filesystem Filter) intercetta le operazioni eseguite sul file esterno attraverso l’interfaccia del file system (p.es. apertura e/o modifica del file da PC attraverso le cartelle condivise di IFS).

Il servizio DLFF opera su tutte le cartelle registrate come prefissi nel server DLFM indipendentemente dal fatto che il file sia linkato o meno.

I datalink garantiscono anche un livello di sicurezza ulteriore ai file di IFS “linkati”: per esempio è possibile specificare che l’URL del file possa essere ottenuto soltanto accedendo al record del DB2.

La figura seguente riassume l’architettura DataLinks.

Vantaggi

L’utilizzo dei datalink ha un impatto relativamente basso nell’implementazione in applicazioni già esistenti:

– la modifica al database è minima (l’aggiunta di una colonna di tipo datalink a una tabella esistente oppure la creazione di una tabella correlata)

– la tabella deve essere registrata su giornale

– i file da linkare possono continuare a risiedere nelle cartelle dove già si trovano

– non c’è nessun impatto su applicazioni esterne che accedono in lettura ai file residenti su IFS

I vantaggi nell’utilizzo dei datalink sono:

– integrità referenziale tra DB2 e file esterno

– controllo degli accessi al file esterno

– backup e ripristino coordinato tra DB2 e file esterno

– consistenza della transazione

Dove?

I datalink su spinta di IBM sono stati introdotti nello standard ANSI/ISO SQL3 “Management of external data”.

L’utilizzo dei Data Links è disponibile nei seguenti ambienti:

– Journaled File System (JFS) on IBM AIX

– File System Migrator (FSM) on IBM AIX

– Distributed File Service (DFS) in Transarc’s Distributed Computing Environment (DCE) on IBM AIX

– UNIX File System (UFS) on SUN Solaris

– NTFS-formatted drive on Windows NT

– Integrated File System (IFS) on IBM i

Nel seguito dell’articolo prendiamo in esame l’utilizzo dei campi Data Links relativamente a file memorizzati su IFS.

Come è fatto un datalink?

Il campo di tipo datalink contiene un puntatore al file esterno scritto nella forma di URL file://hostname/pathname/filename.

A un campo DataLink possono essere assegnati due valori di default: null oppure il risultato restituito dalla funzione dlvalue(' ', 'URL', ' ').

Il tipo dati DataLink non è compatibile con nessun tipo di variabile host, quindi si può accedere al contenuto di un campo DataLink solo tramite SQL e non tramite I/O nativo.

Per aggiornare o inserire dati in un campo DataLink bisogna utilizzare la funzione DLValue in un’istruzione SQL insert o update.

E’ possibile gestire i record di una tabella contenente campi datalink tramite I/O nativo solo operando su una vista o un file logico che ometta i campi datalink.

Un campo datalink non può essere specificato come campo chiave in un indice e non possono essere definiti check constraints su di esso.

Un campo datalink non può essere specificato in una clausola group by o order by di un’istruzione SQL.

Quando una tabella contiene un campo datalink con la keyword File Link Control è necessario che sia registrata su giornale; se la tabella non è registrata su giornale al momento in cui si tenta di inserire un record si riceve l’errore SQL7008.

Un’operazione di aggiornamento su un record contenente un campo datalink è trattata come se fosse una cancellazione seguita da un inserimento. Quindi il link con il file viene interrotto (unlink) e poi viene linkato il nuovo file. In virtù di questo comportamento, nelle operazioni di update è necessario specificare anche i parametri linktype e comment nella funzione dlvalue, altrimenti verranno impostati ai valori di default.

Setup DLFM

Il DLFM gestisce solo i campi di tipo Datalink con specificata la keyword File Link Control.

I passi principali per configurare il servizio DLFM sono 6.

Per eseguire i passi successivi è necessario utilizzare un utente con autorizzazione speciale *IOSYSCFG.

E’ necessario che sia installato il prodotto QShell interpreter (57xxSS1 opz. 30).

1) Verificare che nella gestione voci indirizzario del database (WRKRDBDIRE) esista la voce di tipo *LOCAL.

Normalmente questa voce esiste già e il nome del database coincide con il serial number della macchina.

2) Verificare che il nome host (da indicare successivamente nel parametro HOSTDB del comando ADDHDBDLFM) ovvero il nome del database di tipo *LOCAL verificato al punto precedente sia configurato nella tabella host (CFGTCP opz. 10) abbinato all’indirizzo IP del sistema. In mancanza di questa configurazione il DB2 non sarà in grado di comunicare con DLFM; quindi si riceveranno errori come se il DLFM fosse arrestato.

3) InzDLFM: da eseguire normalmente solo una volta. Inizializza il DLFM creando la libreria e tutti gli oggetti necessari al servizio.

INZDLFM CLEARDB(*ALL)

Nel caso si debba rieseguire successivamente dopo aver già configurato i nomi database e i prefissi si dovrebbe utilizzare

INZDLFM CLEARDB(*LNKSTS)

Anche nel secondo caso però le informazioni di tutti gli oggetti collegati andranno perse.

Quindi questo comando è da utilizzare con molta cautela.

Dopo l’esecuzione di questo comando consiglierei di impostare la cancellazione automatica dei ricevitori del giornale creato dall’istruzione create collection qdlfm:

CHGGJRN JRN(QDLFM/QSQJRN) JRNRCV(*GEN) DLTRCV(*YES)

4) StrTcpSvr Server(*DLFM): avvia il servizio DLFM. Se il servizio DLFM è arrestato il DB2 non può gestire i campi datalink, in quanto non può essere eseguito il controllo di integrità tra record della tabella e file su IFS. Però le operazioni di lettura di record contenenti campi DataLink sono sempre possibili anche quando il servizio DLFM è arrestato.

Per verificare se sono attivi i lavori del server DLFM

select *from QDLFM/DFM_JOB;

I lavori sono attivi nel sottosistema QSYSWRK e si chiamano QZDFMSVR, QZDFMGCD, QZDFMCPD, QZDFMDGD, QZDFMUPD.

5) AddHdbDLFM: registra un database host con il servizio DLFM.

ADDHDBDLFM HOSTDBLIB(([nome-lib])) HOSTDB([nome-db])

[nome-lib] è il nome di una o più librerie che conterranno tabelle con tipi dati datalink.

[nome-db] è il nome del database di tipo *LOCAL verificato in precedenza al punto 1)

Verificare con

select hex(DBID) "DB ID", DBINST, DBNAME, PASSWORD, HOSTNAME, XN_ID, ART_NUM, ACTION from QDLFM/DFM_DBID;

che il db sia stato registrato

Nel caso in cui il comando non abbia successo si può operare direttamente da QShell (avviare con STRQSH):

digitare il comando

dfmadmin -add_db

Al successivo prompt digitare sulla stessa riga i 3 parametri separati da uno spazio: [nome-lib] QSYS [nome-db]

> MK1DLFM1T QSYS SXXXXXXX
dbnamee = MK1DLFM1T, dbinst = QSYS, hostname = SXXXXXXX.

6) AddPfxDLFM: registra i prefissi, ovvero le cartelle di IFS che conterranno i file da linkare

ADDPFXDLFM PREFIX(('/mk1dlfm1t'))

Oppure da QShell digitare il comando

dfmadmin -add_prefix

Al successivo prompt digitare il prefisso da registrare

> /mk1dlfm1t/
Nome prefisso : /MK1DLFM1T/.

Verificare con

select hex(PRFX_ID) "ID Prefisso", PRFX_NAME "Nome prefisso"from QDLFM/DFM_PRFX;

che il prefisso sia stato registrato.

Nota bene:

– DLFM monta le cartelle registrate come prefissi (cfr. punto 6) durante l’IPL

– la cartella deve già esistere al momento in cui si effettua la registrazione

Suggerimento: è consigliabile memorizzare i file da linkare in sottocartelle della cartella registrata come prefisso. In questo modo sarà molto più agevole gestire le sottocartelle senza dover modificare la configurazione della registrazione del prefisso nel servizio DLFM.

In profondità: le tabelle di DLFM

Le tabelle del servizio DLFM si trovano nella libreria QDLFM (cfr. punto 3 del par. precedente). Le principali tabelle sono:

DFM_DBID: database registrati

DFM_PRFX: prefissi registrati (con il comando AddPfxDLFM)

DFM_JOB: lavori attivi di DLFM.

DFM_FILE: file registrati

Backup e ripristino

Se si utilizzano i campi di tipo DataLink è importante aggiungere nella propria strategia di backup il salvataggio della libreria QDLFM. In questa libreria vengono memorizzate tutte le informazioni necessarie al DB2 e al servizio DLFM per mantenere “linkati” i record del DB2 e i file di IFS. Perdere queste informazioni significa compromettere l’integrità e la coerenza delle informazioni.

I comandi per salvare le librerie (che contengono le tabelle) e le cartelle di IFS sono diversi (SAVLIB/SAVOBJ e SAV rispettivamente).

Attualmente non c’è un collegamento tra il salvataggio di una tabella con campi datalink e il relativo percorso di IFS che contiene i file linkati. Bisogna gestire manualmente la coerenza del backup.

Non è possibile salvare tabelle con campi DataLink ad una release inferiore a V4R4.

Nel processo di ripristino il DB2 fornisce un supporto per ripristinare in maniera coerente i dati (tabelle e file linkati).

  • Esempio 1 Ripristinare le tabelle prima dei file linkati (sconsigliato)

Quando si ripristina la tabella in questa situazione controllando con il comando DSPFD si può notare che il parametro “File is in link pending status” è uguale a Yes.

Questo significa che la tabella ha almeno un file linkato che non esiste sul sistema. Quindi la tabella si trova in stato “read-only”; non è possibile eseguire operazioni di insert, update o delete (si riceverebbe l’errore SQ20054).

Si può utilizzare anche il comando specifico WRKPFDL (Work with Physical File DataLinks). Questo comando oltre a mostrare che esistono file linkati in pending status espone il nome del campo che contiene il datalink e il nome del server.

Se a questo punto ripristiniamo sul sistema anche la cartella di IFS che contiene i file linkati e si ricontrolla con il comando WRKPFDL si noterà che “link pending” è ancora Yes. E’ necessario eseguire opzione 2 “Riconciliazione”. Questo imposta la tabelle come pronta per essere riconciliata. Per eseguire la riconciliazione bisogna eseguire il comando EDTDLFA.

  • Esempio 2 Ripristinare le tabelle dopo i file linkati (consigliato)

In questo caso durante il ripristino della tabella i file linkati vengono contestualmente riconciliati.

Alternativa ai Data Links

Un metodo alternativo all’utilizzo dei campi di tipo Datalink è usare nel DB2 i campi di tipo LOB e memorizzare in questi campi i file.

Dal punto di vista applicativo questa soluzione ha un forte impatto, in quanto i file saranno accessibili solo tramite SQL e le API del DB2.

Esempio di utilizzo dei campi di tipo DATALINK

Creazione della tabella

Creiamo una tabella che registra un elenco di ordini e nel campo datalink memorizziamo l’url del file pdf con la stampa dell’ordine

create or replace table DLEXM00F
  (
    DocID bigint generated by default as identity
       (start with 1 increment by 1 no cycle cache 50 order) implicitly hidden,
    DocType char(2) not null with default,
    DocNumber dec(7, 0) not null with default,
    DocTitle varchar(200) not null with default,
    DocLink datalink(1000) linktype url file link control mode db2options,
    DocUpdate timestamp not null generated by default for each row on update as row change timestamp implicitly hidden
  )
  rcdfmt DLEXM;

N.B. La lunghezza di default di un campo datalink è 200 byte. La lunghezza massima è 32718. La lunghezza in ogni caso allocata è almeno 50 byte.

Nella definizione del campo datalink bisogna specificare quale tipo di controllo si desidera gestire sul file linkato:

– No Link Control: non viene eseguito nessun controllo sul file linkato, viene solo validata la corretta sintassi del link. Quindi non si beneficia delle potenzialità dei Data Links e dei controlli di integrità gestiti da DLFM. In effetti in questo caso il DLFM non entra neanche in gioco.

– File link control: quando un record viene inserito il servizio DLFM immediatamente tenta di linkare il file. Il file quindi deve esistere ed essere accessibile. Un file può essere linkato solo in un record. Una volta che un file viene linkato non può essere spostato, rinominato o cancellato.

La keyword mode db2options è equivalente ad applicare le seguenti regole:

– INTEGRITY ALL

– READ PERMISSION FS: il file system controlla l’accesso in lettura al file linkato

– WRITE PERMISSION FS: il file system controlla l’accesso in scrittura al file linkato

– RECOVERY NO

Nel caso in cui si specifichi WRITE PERMISSION DB è possibile specificare anche On Unlink delete così da cancellare automaticamente il file linkato nel momento in cui viene eliminato il link dal record della tabella del DB2 (ATTENZIONE: come scritto in precedenza l’operazione di update di un campo datalink equivale a una cancellazione seguita da un inserimento). Con le keyword READ PERMISSION DB/WRITE PERMISSION DB il DB2 ha il pieno controllo degli accessi al file linkato. La proprietà del file linkato viene trasferita all’utente QDLFM.

Inserimento di un record

insert into DLEXM00F
  values('01', 23, 'ordine n. 23 del 14/12/17', 
    dlvalue('file://SXXXXXX/mk1dlfm1t/ord_01_0000023_2017.pdf', 'URL', 'ordine n. 23'));

Verifica effettiva registrazione in DLFM:

select hex(PRFXID) "ID Prefisso", PRFX_NAME "Nome prefisso", hex(DBID) "DB ID", DBNAME, hex(GRP_GENID) "GRP ID", PGRPNAME "Path", STEMNAME "File", hex(FSID) "FSID", hex(LINK_RECID) "Link rec ID", hex(UNLINK_RECID) "Unlink rec ID", ORG_FILE_SZ "Dimensione file", INSERT_TIME "Data/ora inserimento"
  from QDLFM/DFM_FILE
    inner join QDLFM/DFM_DBID using (DBID)
    inner join QDLFM/DFM_PRFX on PRFXID = PRFX_ID
  order by PGRPNAME, STEMNAME;

Se si tenta di inserire un altro record collegato allo stesso file si riceve errore di tipo 25, sqlcode = -358, sqlstate = 428D1

insert into DLEXM00F
  values('01', 23, 'ordine n. 23 del 14/12/17', 
    dlvalue('file://SXXXXXX/mk1dlfm1t/ord_01_0000023_2017.pdf', 'URL', 'ordine n. 23'));

Se si cerca di inserire un link con il server DLFM arrestato o comunque con problemi di interazione tra DB2 e server DLFM si riceve errore di tipo 8, sqlcod = -357, sqlstate = 57050

Se si cerca di inserire un link non esistente si riceve errore di tipo 24, sqlcode = -358, sqlstate = 428D1

insert into DLEXM00F
  values('01', 23, 'ordine n. 23 del 14/12/17', 
    dlvalue('file://SXXXXXX/mk1dlfm1t/ord_01_0000023.pdf', 'URL', 'ordine n. 23'));

Se si cerca di inserire un link esistente ma con prefisso non registrato si riceve errore di tipo 22, sqlcode = -358, sqlstate = 428D1

insert into DLEXM00F
  values('01', 23, 'ordine n. 23 del 14/12/17', 
    dlvalue('file://SXXXXXX/mk1test/ord_01_0000023_2017.pdf', 'URL', 'ordine n. 23'));

Lettura campo datalink

La lettura è sempre possibile anche se il server DLFM è arrestato

select D.*,
 dlcomment(DOCLINK) as "Commento",
 dllinktype(DOCLINK) as "Link type",
 dlurlcomplete(DOCLINK) as "URL",
 dlurlpath(DOCLINK) as "Path",
 dlurlpathonly(DOCLINK) as "Path only", 
 dlurlscheme(DOCLINK) as "Protocollo",
 dlurlserver(DOCLINK) as "Database"
  from DLEXM00F as D;

Operazioni sui file linkati da file system

Se si tenta di rinominare (RNM) il file linkato si riceve l’errore CPFA0D4 con errore numero 3534 ovvero l’errore CPE3534

Messaggio . . . : L'oggetto è un oggetto Datalink. 
Causa. . . . . : L'oggetto di riferimento è sotto controllo Datalink. Le 
funzioni di apertura senza un token di accesso valido, di eliminazione o di 
ridenominazione non sono consentite.

Se si tenta di rinominare il file linkato accedendo da PC tramite le risorse condivise di NetServer possono venire mostrati messaggi di errore meno significativi ma l’operazione non viene eseguita. P.es. “Memoria insufficiente per completare l’operazione”

Funzioni SQL

  • DLVALUE: da utilizzare per inserire o aggiornare un campo datalink
  • DLCOMMENT: restituisce il commento di un campo datalink
  • DLLINKTYPE: restituisce il tipo di link (attualmente è gestito solo URL)
  • DLURLCOMPLETE: restituisce il percorso completo e nome file linkato (server name + full directory path + access control token)
  • DLURLPATH: restituisce il percorso e nome file linkato (full directory path + access control token)
  • DLURLPATHONLY: restituisce solo il percorso del file linkato (full directory path)
  • DLURLSCHEME: restituisce il tipo di protocollo (file o http o https)
  • DLURLSERVER: restituisce il nome server