Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

TDD o Test-Driven Development
immagine docker per lavorare con lazarus e free pascal
Indice
Installare lazarus su mac osx sierra
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non)
Advanced Record Syntax: un esempio pratico
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
DB concetti fondamentali e DBGrid
Advanced Record Syntax
DB concetti fondamentali e ZeosLib
DB concetti fondamentali e connessioni standard
guida all'installazione di fpc trunk da subversion in linux gentoo
Creare un server multithread
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Free Pascal e Lazarus sul Raspberry Pi
fpcup: installazioni parallele di lazarus e fpc
Ubuntu - aggiornare free pascal e lazarus
Come interfacciare periferica twain
Lazarus 1.0
Aspetto retrò (Cmd Line)
Disporre le finestre in un blocco unico (come Delphi)
Zeos ... dietro le quinte (prima parte)
Lavorare con file in formato JSON con Lazarus
Overload di operatori
Dataset virtuale
Linux + Zeos + Firebird
Pascal Script
La gestione degli errori in Lazarus
Indy 10 - Invio email con allegati
Brute force
Le permutazioni
Da DataSource a Excel
StatusBar - aggirare l'errore variabile duplicata
Visualizzare un file Html esterno
Evidenziare voci TreeView
Toolbar
Direttiva $macro
Indy gestiore server FTP lato Client
TImage su Form e Panel
PopUpMenu sotto Pulsante (TSpeedButton)
Conversione numerica
Proprietà
Funzioni a parametri variabili
Overload di funzioni
Liste e puntatori
Conferma di chiusura di un applicazione
Il file: questo sconosciuto
UIB: Unified Interbase
System Tray con Lazarus
Intercettare tasti premuti
LazReport, PDF ed immagini
Lazarus e la crittografia
Ampliare Lazarus
Generare controlli RUN-TIME
TTreeview e Menu
TTreeView
Utilizzare Unità esterne
Lavorare con le directory
Realizzare programmi multilingua
Codice di attivazione
File INI
Esempio lista in pascal
Stabilire il sistema operativo
Recuperare codice HTML da pagina web
Trascinare un file nel programma
Mandare mail con Lazarus
Welcome to Italian community of Lazarus and Free Pascal. Please login or sign up.

Recenti

How To

Utenti
Stats
  • Messaggi totali: 20.582
  • Totale discussioni: 2.471
  • Online today: 310
  • Online ever: 5.949 (Luglio 30, 2026, 09:49:59 PM)
Utenti online
  • Users: 0
  • Guests: 5
  • Total: 5
5 Visitatori, 0 Utenti

Aiuto, perdo record

Aperto da tito_livio, Agosto 08, 2022, 01:02:23 PM

Discussione precedente - Discussione successiva

tito_livio

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:


          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.

DragoRosso

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 ....
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

tito_livio

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.

tito_livio

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.

DragoRosso

Citazione di: tito_livio il 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.

Bhè Delphi3 con ODBC .... eravamo all'alba di un nuovo impero (e nel film sono tutti morti ....  ::) )
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

Citazione di: tito_livio il Agosto 08, 2022, 01:02:23 PM

          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 ?
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

bonmario

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:
        //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

bonmario

... 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

tito_livio

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:
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.


DragoRosso

Citazione di: tito_livio il Agosto 09, 2022, 08:57:18 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
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

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
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

SB

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?


Citazione di: tito_livio il 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:


          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.

tito_livio

Citazione di: DragoRosso il Agosto 09, 2022, 03:42:12 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?

Citazione di: SB il Agosto 14, 2022, 10:08:57 AM
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.

Citazione di: SB il Agosto 14, 2022, 10:08:57 AM
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.

Citazione di: SB il Agosto 14, 2022, 10:08:57 AM
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.

SB

Citazione di: tito_livio il Agosto 14, 2022, 03:03:50 PM
Citazione di: SB il Agosto 14, 2022, 10:08:57 AM
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

DragoRosso

Citazione di: tito_livio il Agosto 14, 2022, 03:03:50 PM
Citazione di: DragoRosso il Agosto 09, 2022, 03:42:12 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
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.