Italian community of Lazarus and Free Pascal

Programmazione => Databases => Topic aperto da: tito_livio - Agosto 08, 2022, 01:02:23 pm

Titolo: Aiuto, perdo record
Inserito da: tito_livio - Agosto 08, 2022, 01:02:23 pm
Buongiorno a tutti,
in un nuovo progetto, ho un database Mysql con diverse tabelle, di tipo MyIsam, alle quali accedono alcuni client, anche una decina, con dei mie programmi.
Il problema è che, circa l'uno percento dei record aggiunti, non vengono poi ritrovati.
Essendo che ci sono tabelle anche con 900.000 record, il problema diventa frequente.
I programmi girano sotto Windows 64 bit e 32 bit, sono compilati per 32 bit con la versione 2.0.6.
Uso i componenti nativi, non quelli Zeos, e il codice che uso per salvare segue questo semplice schema:

Codice: [Seleziona]
          fdm.tesiti.AppendRecord([....]);
          fdm.tesiti.applyupdates(8);
          fdm.lab_anno.transaction.commitretaining;
          fdm.tesiti.Close;
          fdm.tesiti.Open;

L'argomento 8 della funzione applyupdates è stato inserito per cercare di correggere il problema ma non risolve.
Grazie in anticipo.
Titolo: Re:Aiuto, perdo record
Inserito da: DragoRosso - Agosto 08, 2022, 02:10:31 pm
Ciao, premettendo che non conosco MySql così bene da poterti dare una mano concreta, ti chiedo comunque alcune info:

1) Hai detto che ci sono diversi client, come comunicano i client con il database ?

2) Perchè non hai aggiornato almeno ad una versione più recente Lazarus e FPC ?

Il fatto che usi commitretaining mi fà sorgere un dubbio: MySql server non supporta più transazioni contemporanee sulla stessa connessione, e commitretaining lascia aperta la transaction .... Se la usi con i Thread o su più Tabelle contemporaneamente, forse quello è il problema.

Ciao
Magari sbaglio ....
Titolo: Re:Aiuto, perdo record
Inserito da: tito_livio - Agosto 08, 2022, 03:10:14 pm
Ciao,
i vari client accedono, in rete locale, al database tramite le librerie native Lazarus.
Non ho aggiornato ancora Lazarus perché pensavo fosse un errore mio e perché spesso ci sono dei problemi di compatibilità fra vecchie e nuove versioni.
A questo punto però è una prova che farò.
Per quanto riguarda le transaction, credo che non sia quello il problema perché il motore Mysql utilizzato è Myisam che non gestisce le transazioni. 
Proverò quindi con una versione aggiornata di lazarus e vedremo.
Grazie.
Titolo: Re:Aiuto, perdo record
Inserito da: tito_livio - Agosto 08, 2022, 03:18:54 pm
Aggiungo, una cosa che ho ricordato adesso, che potrebbe aiutare a chiarire la situazione.
La stessa cosa mi succedeva con un vecchio progetto in Delphi3 che accedeva a Mysql con gli ODBC.
Titolo: Re:Aiuto, perdo record
Inserito da: DragoRosso - Agosto 08, 2022, 05:42:24 pm
Aggiungo, una cosa che ho ricordato adesso, che potrebbe aiutare a chiarire la situazione.
La stessa cosa mi succedeva con un vecchio progetto in Delphi3 che accedeva a Mysql con gli ODBC.

Bhè Delphi3 con ODBC .... eravamo all'alba di un nuovo impero (e nel film sono tutti morti ....  ::) )
Titolo: Re:Aiuto, perdo record
Inserito da: DragoRosso - Agosto 08, 2022, 05:47:25 pm
Codice: [Seleziona]
          fdm.tesiti.AppendRecord([....]);
          fdm.tesiti.applyupdates(8);
          fdm.lab_anno.transaction.commitretaining;
          fdm.tesiti.Close;
          fdm.tesiti.Open;

Ora ho notato una cosa: usi "lab_anno" per le commit e "tesiti" per inserire i dati ?
Titolo: Re:Aiuto, perdo record
Inserito da: bonmario - Agosto 09, 2022, 08:03:39 am
Ciao,
oltre alla verifica suggerita da DragoRosso, io ho un unico progetto in cui vado a scrivere il DB, che tra l'altro è MSSql. Le istruzioni che uso sono queste:
Codice: [Seleziona]
        //Ora posso fare la sostituzione.
        //Preparo l'istruzione SQL
        SqlQueryUpdate.UpdateSQL.Clear;
        SqlQueryUpdate.UpdateSQL.Add('update ' + CstNomeTabellaDaSist);
        SqlQueryUpdate.UpdateSQL.Add('set ' +
                                     CstNomeColonnaDaSist +
                                     ' = ' +
                                     MettiVirgolette(CstValCampoNew, tvSemp));
        SqlQueryUpdate.UpdateSQL.Add('where ' + CstNomeColonnaDaSist + ' = ' +
                                     MettiVirgolette(CstValCampoOld, tvSemp));
        //Scrivo la modifica
        //SqlQueryUpdate.UpdateSQL.SaveToFile(WinTemp + 'Mario.txt');
        SqlQueryUpdate.Open;
          SqlQueryUpdate.Edit;
          SqlQueryUpdate.Post;
          SqlQueryUpdate.ApplyUpdates;
        SqlQueryUpdate.Close;

        //Ora che ho finito di leggere il DB, lo posso aggiornare (COMMIT)
        SQLTransaction1.CommitRetaining;

Ricordo che all'epoca le avevo trovate tramite una ricerca, e non so se sono o meno equivalenti a quelle che usi tu.

Ciao, Mario
Titolo: Re:Aiuto, perdo record
Inserito da: bonmario - Agosto 09, 2022, 08:13:47 am
... dimenticavo ... Se l'istruzione di write/update fallisce, dovrebbe segnalare un errore a video.
Se le persone che dicono di avere inserito il record che poi non si trova non hanno visto questo messaggio, può essere che il problema sia da un'altra parte?
Ad esempio, magari il record viene inserito correttamente, ma poi c'è qualcosa che lo va a cancellare in un secondo momento ...

Ciao, Mario
Titolo: Re:Aiuto, perdo record
Inserito da: tito_livio - Agosto 09, 2022, 08:57:18 am
Buongiorno,
per DragoRosso:
Potrebbe essere come dici tu a proposito delle transazioni contemporanee. Ho scoperto che nel mio programma in effetti c'è la possibilità che ci siano due transazioni contemporanee, generate dallo stesso client, su due tabelle diverse, una delle quali è quella che mi crea problemi. Ho escluso la possibilità che questo si verifichi e sto tenenendo il tutto sotto controllo.
Si, uso lab_anno, che è una TMySql50Connection, per la commit, mentre tesiti che è una TSqlQuery per l'append dei nuovi record. Secondo te dovrei fare diversamente?
Per Bonmario:
a parte il fatto che nel tuo codice tu aggiorni mentre io aggiungo, il salvataggio è quasi lo stesso. Le uniche cose che tu scrivi in più sono:
Codice: [Seleziona]
SqlQueryUpdate.Edit;
SqlQueryUpdate.Post;
secondo me Edit è inutile mentre Post ricordo che mi dava problemi ma non mi ricordo quali.
Purtroppo nessuno mi riferisce di messaggi d'errore a video. E nessun umano va a cancellare i record, me ne accorgo da alcune altre tabelle.
Sembra proprio un salvataggio non andato a buon fine. Grazie per la risposta.

Titolo: Re:Aiuto, perdo record
Inserito da: DragoRosso - Agosto 09, 2022, 10:19:24 am
Si, uso lab_anno, che è una TMySql50Connection, per la commit, mentre tesiti che è una TSqlQuery per l'append dei nuovi record. Secondo te dovrei fare diversamente?

No, è che non sapevo cosa era lab_anno, e quindi magari era una svista nel codice (a me è successo più di qualche volta  ;) ).

Ciao
Titolo: Re:Aiuto, perdo record
Inserito da: DragoRosso - Agosto 09, 2022, 03:42:12 pm
Una riflessione, io che provengo storicamente dalla situazione dove i database erano banalmente un insieme di record di dati accodati uno dietro l'altro (l'ISAM originale), dove le transaction erano più che altro delle idee "transitorie" ( ;D ), ho sempre usato i database in un due modi:

- classico andando a scrivere direttamente in ogni singola tabella (salvo l'ausilio relativamente moderno delle master / detail) usando la sequenza INSERT (O EDIT), IMMISSIONE DATI NEI CAMPI, POST;

- usando le QUERY SQL, dove la query fà ovviamente tutto (al limite si lanciano più query).

Il Commit, ossia la chiusura di una transazione l'ho usata pochissime volte e solo ed esclusivamente dove il cliente pretendeva la certificazione (con tanto di log) delle transazioni appunto.

Questo non tanto perchè la tecnologia delle transaction non sia affidabile, ma fino a poco tempo fà c'erano molti limiti al suo utilizzo, e tra l'altro limiti il cui "sforamento" provocava un emerito NULLA, nessuna segnalazione, nessun errore, niente. Certamente per colpa principale dei componenti, delle dll client o di altro, però tant'era.

Ma appunto dal mio provenire dall'ISAM, e non ho mai cambiato atteggiamento, ho sempre ed esclusivamente SCRITTO nel database attraverso UNA E UNA SOLA FUNZIONE, NORMALMENTE TRAMITE UN THREAD, serializzata da un semaforo in modo tale che il programma eseguisse le attività di scrittura da un solo LUOGO e in un solo istante. Per razionalizzare il codice poi o gestito più funzioni MA SEMPRE SERIALIZZATE con lo stesso semaforo. Ciò mi ha consentito di non avere mai alcun problema, con alcun database sia esso basato su Server che su FILE.

Fate attenzione quando lavorate con i database, ma non solo, che con i moderni processori la gestione del Threading deve essere effettuata da "manuale" (nel senso che SI DEVONO ESEGUIRE ALLA LETTERA LE LINEE GUIDA): dimenticatevi i tempi mascherati o altro .... non funzionano. Provato sulla propria pelle.

Ciao
 
Titolo: Re:Aiuto, perdo record
Inserito da: SB - Agosto 14, 2022, 10:08:57 am
Io suderei freddo a perdere un singolo record. Perderne migliaia... :o

Dubito che il problema stia in MySQL. Dubito che stia nelle librerie usate perchè l'operazione sembra troppo banale.

Non è che per caso imposti dei valori non validi nel record da aggiungere e l'operazione fallisce?
Ad esempio un valore non unico in un campo indicizzato unico, o un valore nullo in un campo non nullo?
E non te ne accorgi perchè non controlli che l'operazione sia andata a buon fine, ad esempio con RowsAffected?


Buongiorno a tutti,
in un nuovo progetto, ho un database Mysql con diverse tabelle, di tipo MyIsam, alle quali accedono alcuni client, anche una decina, con dei mie programmi.
Il problema è che, circa l'uno percento dei record aggiunti, non vengono poi ritrovati.
Essendo che ci sono tabelle anche con 900.000 record, il problema diventa frequente.
I programmi girano sotto Windows 64 bit e 32 bit, sono compilati per 32 bit con la versione 2.0.6.
Uso i componenti nativi, non quelli Zeos, e il codice che uso per salvare segue questo semplice schema:

Codice: [Seleziona]
          fdm.tesiti.AppendRecord([....]);
          fdm.tesiti.applyupdates(8);
          fdm.lab_anno.transaction.commitretaining;
          fdm.tesiti.Close;
          fdm.tesiti.Open;

L'argomento 8 della funzione applyupdates è stato inserito per cercare di correggere il problema ma non risolve.
Grazie in anticipo.
Titolo: Re:Aiuto, perdo record
Inserito da: tito_livio - Agosto 14, 2022, 03:03:50 pm

Ma appunto dal mio provenire dall'ISAM, e non ho mai cambiato atteggiamento, ho sempre ed esclusivamente SCRITTO nel database attraverso UNA E UNA SOLA FUNZIONE, NORMALMENTE TRAMITE UN THREAD, serializzata da un semaforo in modo tale che il programma eseguisse le attività di scrittura da un solo LUOGO e in un solo istante.
 

Ma tu intendi che per ogni client scrivi sempre con un solo thread su di una sola tabella alla volta oppure serializzi la scrittura ad una tabella (o a tutto il database) per tutti i client in rete?

Io suderei freddo a perdere un singolo record. Perderne migliaia... :o

Infatti, ho rimediato al problema ma in una maniera complicata che non mi piace.

Non è che per caso imposti dei valori non validi nel record da aggiungere e l'operazione fallisce?
Ad esempio un valore non unico in un campo indicizzato unico, o un valore nullo in un campo non nullo?

Non penso che sia questo perché ripetendo la stessa scrittura, con gli stessi dati, non succede.
In pratica una volta su tante la scrittura non va a buon fine, anche se scrivo sempre le stesse cose.

E non te ne accorgi perchè non controlli che l'operazione sia andata a buon fine, ad esempio con RowsAffected?

Questo si, lo proverò, grazie per la risposta.
Titolo: Re:Aiuto, perdo record
Inserito da: SB - Agosto 14, 2022, 03:42:45 pm
Non è che per caso imposti dei valori non validi nel record da aggiungere e l'operazione fallisce?
Ad esempio un valore non unico in un campo indicizzato unico, o un valore nullo in un campo non nullo?

Non penso che sia questo perché ripetendo la stessa scrittura, con gli stessi dati, non succede.
In pratica una volta su tante la scrittura non va a buon fine, anche se scrivo sempre le stesse cose.

Dunque i valori che inserisci sarebbero validi
A me sembra un errore di valori duplicati su un campo indicizzato.
Ad esempio, per qualche motivo non hai usato i campi chiave autonumeranti e i client generano autonomamente delle chiavi per identificare i record, ma non hai un meccanismo che garantisca che queste chiavi siano effettivamente uniche nella tabella. Il meccanismo che usi funziona bene normalmente (al 99%) ma ogni tanto saltano fuori chiavi identiche su client diversi e l'append fallisce
Titolo: Re:Aiuto, perdo record
Inserito da: DragoRosso - Agosto 14, 2022, 05:58:30 pm
Ma appunto dal mio provenire dall'ISAM, e non ho mai cambiato atteggiamento, ho sempre ed esclusivamente SCRITTO nel database attraverso UNA E UNA SOLA FUNZIONE, NORMALMENTE TRAMITE UN THREAD, serializzata da un semaforo in modo tale che il programma eseguisse le attività di scrittura da un solo LUOGO e in un solo istante.

Ma tu intendi che per ogni client scrivi sempre con un solo thread su di una sola tabella alla volta oppure serializzi la scrittura ad una tabella (o a tutto il database) per tutti i client in rete?


Intendevo per operazioni effettuate da un singolo client direttamente dall'applicativo. Lasciando per un attimo perdere i client su rete, già con un solo client puoi avere problemi se instauri più transazioni (ossia scritture multiple) contemporanee da più Thread: ovvio che dipende dal motore che scegli. Se usi Oracle o Microsoft con le versioni enterprise dei prodotti è certo che puoi fare più o meno quello che vuoi senza prestare bada ai Thread, ai client o ad altri dettagli.

Poi, pensando ad un sistema multiclient, le cose si fanno più complesse e occorre molto spesso migrare su database più performanti e sicuri.

Ciao
Titolo: Re:Aiuto, perdo record
Inserito da: tito_livio - Agosto 18, 2022, 03:36:58 pm
Dunque i valori che inserisci sarebbero validi
A me sembra un errore di valori duplicati su un campo indicizzato.
Ad esempio, per qualche motivo non hai usato i campi chiave autonumeranti e i client generano autonomamente delle chiavi per identificare i record, ma non hai un meccanismo che garantisca che queste chiavi siano effettivamente uniche nella tabella. Il meccanismo che usi funziona bene normalmente (al 99%) ma ogni tanto saltano fuori chiavi identiche su client diversi e l'append fallisce

La tabella ha due campi chiave, uno autoincrementante che però io non riempio e lascio fare al DBMS, l'altro non è unico. Credo quindi che non possanio essere fatti errori.

Intendevo per operazioni effettuate da un singolo client direttamente dall'applicativo. Lasciando per un attimo perdere i client su rete, già con un solo client puoi avere problemi se instauri più transazioni (ossia scritture multiple) contemporanee da più Thread: ovvio che dipende dal motore che scegli. Se usi Oracle o Microsoft con le versioni enterprise dei prodotti è certo che puoi fare più o meno quello che vuoi senza prestare bada ai Thread, ai client o ad altri dettagli.

Poi, pensando ad un sistema multiclient, le cose si fanno più complesse e occorre molto spesso migrare su database più performanti e sicuri.


Quindi se tu dovessi gestire un sistema multiclient scarteresti Mysql e Firebird. Cosa ne pensi di PostgreSql?
Comunque, da circa una settimana, ho eliminato l'accesso contemporaneo a due tabelle, da parte di un applicativo di un client.
Il rimedio sembra efficace anche se lo terrò ancora sotto controllo.
Titolo: Re:Aiuto, perdo record
Inserito da: DragoRosso - Agosto 18, 2022, 05:49:02 pm
Quindi se tu dovessi gestire un sistema multiclient scarteresti Mysql e Firebird. Cosa ne pensi di PostgreSql?
Comunque, da circa una settimana, ho eliminato l'accesso contemporaneo a due tabelle, da parte di un applicativo di un client.
Il rimedio sembra efficace anche se lo terrò ancora sotto controllo.

Il rimedio sarà sicuramente efficace, tenuto conto delle specifiche MySQL.
Per il consiglio non saprei dirti, ho usato tantissimi Database ma nei tempi che furono e non per applicazioni gestionali multiutente. Poi ho sempre più usato (per scelta dei clienti) MSSql (versione free o quella server).

Per un periodo, legato alla difficoltà di trovare un DB compatibile con applicazioni e sistemi industriali, mi sono fatto un mio server "SIMIL SQL" che interfacciava i vari client e scriveva poi su un db SQLite.

In questo momento, dovessi scegliere un DB multiclient FREE (o quasi FREE) tra quelli disponibili mi troverei in difficoltà, dovrei studiarci sopra un attimo.

Forse, qualcuno del forum con una maggiore esperienza potrebbe darti qualche consiglio utile.

Ciao
Titolo: Re:Aiuto, perdo record
Inserito da: Mimmo - Agosto 19, 2022, 09:13:26 am
Io attualmente uso postgres per un'applicazione gestionale multi-utente utilizzata da una trentina di client qui in azienda e non ho mai avuto problemi. L'applicazione è fatta con lazarus e l'accesso utilizza la libreria di sistema sqldb/PQConnection. Lettura e scrittura però sono tutte gestite attraverso query sql (nessun componente grafico TDB-qualcosa che legga e scriva su db direttamente) e anche le transazioni sono gestite esplicitamente a codice.

Per quella che è la mia esperienza Postgresql è assolutamente utilizzabile come soluzione enterprise. Ad esempio ho visto il sistema di prenotazione CUP di diversi distretti lombardi e piemontesi e i sistemi di prenotazione di alcuni importanti ospedali milanesi usare pg come db del backend.
Titolo: Re:Aiuto, perdo record
Inserito da: bonmario - Agosto 19, 2022, 10:55:35 am
Io attualmente uso postgres per un'applicazione gestionale multi-utente utilizzata da una trentina di client qui in azienda e non ho mai avuto problemi

Scusami, vado un po' fuori tema, ma ne approfitto per chiederti una cosa che magari sai.
Al lavoro, abbiamo un applicativo che lavora su 3 DB: Microsoft SQL Server, Oracle, Postgre, ma è di una lentezza esasperante.

Ho fatto io un programma con Lazarus, che legge i dati dai vari DB, ma al momento lo uso solo io sul mio PC. Vorrei farlo usare anche dai colleghi, ma per funzionare ha bisogno delle dll dei vari DB. Per MSSql, ed Oracle, ho capito che ci sarebbero problemi di licenza, per quanto riguarda invece Postgre, credo di poter copiare tranquillamente su ogni PC in cui serve le dll che gli servono per poter funzionare, ma non ne sono sicuro al 100%. Tu ne sai qualcosa di più ?

Io, con queste licenze, vado sempre in paranoia, e ci capisco poco !!!!


Grazie, Mario
Titolo: Re:Aiuto, perdo record
Inserito da: Mimmo - Agosto 19, 2022, 12:40:33 pm
Ciao Mario,
innanzitutto confesso che non mi sono posto il problema..  ::) quindi non so darti una risposta assolutamente certa.
Possiamo però cogliere l'occasione e fare un ragionamento assieme: Postgresql è rilasciato con la licenza PostgreSQL License https://www.postgresql.org/about/licence/ (https://www.postgresql.org/about/licence/) che è una licenza estremamente permissiva e il cui primo punto recita

Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies.

Inoltre nella documentazione della vecchia versione 8.2 di pg ho trovato scritto:

Normally you do not need to install any of the client files. You should place the libpq.dll file in the same directory as your applications .EXE-file.

La trovi qui https://www.postgresql.org/docs/8.2/install-win32.html (https://www.postgresql.org/docs/8.2/install-win32.html).

Quindi non vedrei problemi a distribuire le dll necessarie a far funzionare il tuo applicativo insieme con l'applicativo stesso, salvo includere anche la licenza di pg e specificare nella documentazione la presenza di quei file così licenziati.
Titolo: Re:Aiuto, perdo record
Inserito da: bonmario - Agosto 19, 2022, 04:49:26 pm
Ok, grazie.

Mi hanno fatto spaventare qualche anno fa, e da allora vado sempre con i piedi di piombo su queste cose !!!

Ciao, Mario
Titolo: Re:Aiuto, perdo record
Inserito da: DragoRosso - Agosto 19, 2022, 06:28:06 pm
Ok, grazie.
Mi hanno fatto spaventare qualche anno fa, e da allora vado sempre con i piedi di piombo su queste cose !!!
Ciao, Mario

In genere, per il problema delle licenze soprattutto per i motori dei DB, non devi preoccuparti più tanto. Chi vuole limitare il funzionamento di un sistema adotta ben altri sistemi (oltre alle dichiarazione scritta di licenza) a maggior ragione se si parla di società come Microsoft o Oracle. Per MS SQL i driver sono già inclusi in tutte le distribuzioni di Windows, o sono eventualmente scaricabili in maniera gratuita. E' l'uso che è "blindato" a seconda delle licenza del server, per cui o ti connetti "presentando" tu una licenza oppure ti connetti con i limiti imposti dal server, ma comunque non violi licenze perchè al limite il server semplicemente non risponderà alle tue richieste.

Per Oracle non sò come funziona, ma ritengo adotti più o meno lo stesso sistema.

Certo, conoscere la tipologia d'uso di un servizio è fondamentale ma a meno che tu non sia il "distributore" dei sistemi server è sicuramente un fatto di cui non avere un timore innaturale.

Ciao