Home > Brontolo, SQL > PHP/MySQL Transactions…

PHP/MySQL Transactions…

Ci son cose che proprio non digerisco di SQL, una di quelle è la clausola INSERT e soprattutto come viene gestita in MySQL (via PHP).

Ormai tutti i database di questo mondo permettono di avere tabelle con indici/chiavi numerici autoincrementanti (che non sono standard) eppure la loro implementazione della INSERT spesso viene gestita come una “procedura” e non come una “funzione“: inserisci qualcosa (indice nuovo e autoincrementato) e poi ti tocca fare subito un’altra query (o invocare una funzione wrapper apposita come mysql_insert_id()) per sapere l’ID del record appena inserito (LAST ID).

In una applicazione web seria, con molti inserimenti concorrenti, fra la INSERT e la SELECT (che recupera l’ultimo ID inserito) può inserirsi qualche altra operazione (magari un altro inserimento) che fa cambiare erroneamente il LAST ID…

Una semplice soluzione è rappresentata dalle cosiddette transazioni (secondo SQL e nella documentazione di MySQL).

Si tratta di una serie di query, opportunamente raggruppate, che viene processata “atomicamente” (cfr. lettera “A” delle cosiddette “proprietà ACID” nel campo dei database), ossia come se fosse un’unica operazione.


mysql_query(‘START TRANSACTION’);

//Svariate query (INSERT, RECUPERO ULTIMO ID INSERITO, UPDATE, …)
// [...]

//Verifica prima della chiusura
if($TUTTO_OK)
{
    // confermiamo l’intera transazione
    mysql_query(‘COMMIT’);
}
else
{
    // annulliamo l’intera transazione
    mysql_query(‘ROLLBACK’);
}

Il procedimento è semplice:

  • si apre la transazione;
  • vengono scritte le query da eseguire “in blocco”
  • si conferma l’intero blocco e le relative operazione (COMMIT) o si annullano (ROLLBACK)

Non si sa nulla circa possibili ottimizzazioni a livello di “blocco di query” anche se è possibile che l’ottimizzatore di query interno a MySQL riesca a operare in maniera più agevole e con una migliore granularità (un conto è ottimizzare n query in un colpo, un colpo è invece dover fare n ottimizzazioni su una query per volta).

Categories: Brontolo, SQL Tag:, , ,
  1. nexus80
    8 Gennaio 2008 alle 16:29 | #1

    Scusa JP ma qui ti becchi una bastonata…

    Non e’ un problema di MySQL/PHP: e’ un problema di tutte le applicazioni con scritture concorrenti e nessun motore di DB/interfaccia e’ in grado di risolverti la questione automagically (a meno che la funzione di inserimento del frontend non faccia una lock senza dirtelo e ti ritorni l’ID inserito tramite una chiamata in sequenza alla funzione di recpuero dell’ID).

    I lock sulle tabelle ed i blocchi di query servono proprio a questo!

  2. jp
    8 Gennaio 2008 alle 16:46 | #2

    Nel post non ho mai definito “problema” quanto esposto.

    Semplicemente, visto che ogni implementazione (es: la citata “MySQL su PHP”) si crea o “personalizza” a piacere le cose andando fuori standard (funzioni, clausole, … ne ho viste di ogni), non vedrei nulla di male se estendesse _anche_ la INSERT per far tornare qualcosa _direttamente_ e senza giri malsani che forzano a usare lock, transaction o quant’altro.

    Da quello che mi ha detto Eros (che si è letto i libroni dello standard SQL) non esiste il concetto di tipo autoincrementante in SQL e quindi questa tipologia di datatype è una estensione (ormai adottata universalmente o quasi) => estendono SQL per supportare sta cosa e non estendono LA funzione che la usa? Ma dai…

    Il senso del post era: come si fa a ottenere il LAST ID in maniera “sicura”. :P

    PS: grazie per il commento. ^^

  3. nexus80
    9 Gennaio 2008 alle 02:41 | #3

    Ehm… ok, non capisco perche’ ti sei concentrato su PHP/MySQL, allora.
    Sembrava che stessi descrivendo un problema unico di tale accoppiata! :)

  4. jp
    9 Gennaio 2008 alle 08:15 | #4

    Veramente ho parlato di “implementazioni di DB” e ho citato l’esempio MySQL/PHP visto che è quello con cui mi son trovato a “giocare” recentemente… :P

  5. nexus80
    9 Gennaio 2008 alle 09:50 | #5

    Io ho riletto, ma da come ha disposto le frasi continuo a fraintendere! ^^

    Vabbe’, tanto ormai ci siamo capiti.

  6. jp
    9 Gennaio 2008 alle 13:21 | #6

    Beh… Spesso mi fraintendo da solo, quando penso fra me e me (“fraintendimento interiore”), quindi non preoccuparti: è (solo) colpa mia. :P :P :P

    Ghghgh…

  7. kailash
    26 Novembre 2008 alle 15:12 | #7

    correggimi se sbaglio, ma io credo che last_insert_id sia sicura anche con molti inserimenti concorrenti in quanto restituisce l’ultimo id autoincrementato generato dall’ultima query effettuata dalla connessione corrente..

    infatti la funzione php mysql_insert_id() accetta come parametro l’identificativo di connessione generato da mysql_connect() appunto per non sbagliarsi

    qua se ne parla:
    http://forum.html.it/forum/showthread.php?threadid=723377

    peace

  8. jp
    26 Novembre 2008 alle 16:15 | #8

    Ciao! :P

    Ho letto il post ma ho un dubbio: supponiamo di avere un processo con 2+ thread figli (quindi stesso utente/resource_id supponendo che la connessione al server MySQL sia stata aperta dal processo-padre e sia quindi condivisa fra i thread-figli) che fanno query di inserimento nello stesso tempo.

    Che succede ai last_id? Secondo me ci scappa il problema in questo caso… :D

    Non ho tempo per provare la cosa (magari MySQL ce la fa lo stesso eh), sorry…

    Grazie per il commento! :)

  9. 27 Novembre 2008 alle 09:14 | #9

    Come è già accaduto, ogni tanto scopro l’esistenza di un post passato interessante… come in questo caso.
    Non sono qui a disquisire su *last_insert_id* (se avrò tempo farò anch’io delle prove per vedere se è thread-safe… anche se condivido i dubbi di JP ;) ), ma solo per fare un paio di considerazioni su alcune pratiche comuni (quando si lavora con i DB) e, IMO, quantomai erronee:

    (a) partiamo dalle ultime considerazioni di JP nel suo post: le transazioni. In contesti come quelli esemplificati da JP, non sono una “semplice soluzione”, ma “La Soluzione” standard al problema. Sono state introdotte nei DBMS proprio per garantire la possibilità di eseguire query di questo tipo (i.e. legate tra di loro).

    (b) sembra che tutti amino i campi auto-incrementanti usati come primary key di tabella… ma se andiamo a vedere cosa è una primary key (al di fuori della semplice definizione funzionale; i.e., ” l’attributo – o gli attributi – che identificano univocamente ciascuna tupla di una relazione “), si comprende come la primary key andrebbe scelta tra gli attributi “reali” che rappresentano la tabella… per esplicitare al massimo, è assurdo usare un campo auto-incrementante come primary key, in una tabella anagrafica dove si può usare il codice fiscale (e ho visto situazioni di questo tipo). Quindi, per fare una storia lunga, corta: se state decidendo di usare un campo auto-incrementante, probabilmente c’è un errore di fondo nella progettazione del database ;)

    cheers

  10. 27 Novembre 2008 alle 11:13 | #10

    Dipende sempre e comunque dal tipo di applicazione che userà il db.

    Per esperienza personale usare il CF come chiave primaria è un suicidio.
    Tanto per cominciare è un varchar 16 (indicizzazione e creazione dei nuovi record rallentata a causa della creazione dell’indice).
    Inoltre se il CF fosse inserito manualmente dall’utente il rischio di fare dei casotti abominevoli è dietro l’angolo.
    Se invece nell’applicazione c’è un sistema automatico di generazione del CF è quasi peggio: persone diverse possono avere cf uguali (omocodi) che rende praticamente impossibile il calcolo _certo_ del CF. (cfr.: http://it.wikipedia.org/wiki/Codice_fiscale).

    IMHO, hai espresso un concetto (teoricamente) corretto con un esempio poco calzante. ;)

  11. 27 Novembre 2008 alle 13:36 | #11

    Ciao, in realtà l’esempio del CF è quello che più adatto a spiegare l’idea alla base… anche perché la possibilità di avere due persone che per errore hanno lo stesso codice fiscale è quasi nulla… avrei potuto dire equivalentemente il numero di patente… ma cosa usare come chiave primaria è solo una questione di applicazione e di design

    Il fatto di usare un varchar come chiave, in realtà non impatta così tanto sui sistemi, sia perché le macchine odierne sono molto potenti e sia perché comunque l’indice viene creato in ogni caso :)

    Sul fatto che il codice fiscale sia possa essere non univoco è solo questione di “mancanza di informazioni” quando lo si genera… ma ormai i casi di codici fiscali duplicati dovrebbero essere veramente pochi, visto che 7/8 anni fa c’è stata una revisione completa da parte dello stato degli stessi con la partecipazione di tutti i comuni italiani… se poi disquisiamo che (a) gli operatori quando inseriscono i dati fanno cavolate e (b) gli applicativi non applicano nemmeno il minimo controllo su quello inserito dagli stessi ti do pienamente ragione :)

    cheers

  12. 27 Novembre 2008 alle 15:57 | #12

    Gli omocodi non hanno cf uguale per errore, ma per calcolo.
    Fidati, non usarlo mai come chiave primaria.

  13. 27 Novembre 2008 alle 16:08 | #13

    fidati anche tu… il calcolo non sbaglia se hai tutti i dati di input… solitamente però quando utilizzi programmi automatici per la generazione dei CF (differenti da quelli installati nei comuni, che da 7/8 anni fa fanno capo a un database centralizzato) manca un dato fondamentale: quante persone, con codice fiscale assegnato, hanno le prime 15 cifre del codice fiscale identiche (e quindi anche la 16 perché generata dalle altre ;) ). Questo dato, permette allo stato di risolvere i casi omocodi.
    Proprio per questo non bisogna fidarsi dei CF generati, ma chiedere all’utenza da registrare di fornirci il suo codice fiscale direttamente dal documento che dovrebbe avere con se… che è generato a partire dalla banca dati centrale.

    cheers

  14. jp
    27 Novembre 2008 alle 16:16 | #14

    Usare come chiave primaria qualcosa univoco e di esterno o non riconducibile ai dati-record è il sistema migliore per gestirli.

    Un numero autoincrementato, slegato quindi dai dati attuali, ha molto senso, IMHO. Fra l’altro impostando autoincrementato senza ripetizioni (default di molti DBMS) hai la certezza dell’univocità che è essenziale: puoi fare qualunque idiozia sui dati ma la chiave autoincrementata non la tocchi più (se il DBMS è serio). :D

    Se poi parliamo di eleganza nella progettazione di un DB, beh… Se hai già una chiave primaria che sai essere univoca che te ne fai di un’altra? :D

    Non userei mai il CF come chiave: l’algoritmo che lo genera è intrinsecamente fatto male e ci vuole un nulla per incappare in un errore (e so che la Bau ha prove certe della stupidità dei CF) nonostante le pezze che mettono i Comuni o chi per essi…

  15. 27 Novembre 2008 alle 16:21 | #15

    IMO introdurre un dato in una tabella solo per comodità (da verificare) e che non ha senso nel dominio del problema, non è la cosa più bella da fare… ma forse perché io ritengo che la buona progettazione sia la base di un buon lavoro e un campo auto-incrementante come chiave primaria non rientra nei miei stilemi di buona progettazione :)

    cheers

  16. 27 Novembre 2008 alle 16:24 | #16

    @Contezero: mi sa che non hai capito quello che ho scritto nel primo post.
    Io non sto parlando del caso delle PA che avranno (spero) accesso alla base dati centrale dello stato, ma di situazioni in cui questo collegamento non c’è (e quindi la verifica di quanti omocodi sono già in giro).
    Come dici tu (e come ti sto dicendo io) “non bisogna fidarsi dei CF generati”.
    Nel mio campo non sai quanti pazienti si presentano allo sportello senza tessera sanitaria (e cf)! e non sai quante segretarie riescono a sbagliare a inserirlo manualmente.
    Inseriscono persino nome e data di nascita sbagliati: figurati che cf calcoliamo!
    ;)

    Cmq, per farla breve: dipende sempre e solo da che applicazione si sta facendo.
    Il db bello ed elegante ma inutilizzabile… non serve a nessuno.

  17. jp
    27 Novembre 2008 alle 16:29 | #17

    Per me invece sì: è la certezza a priori che posso anche inzaccherare una tabella ma quel campo non lo posso toccare.

    Inoltre, entro nel discorso prestazioni, gli autori dei DBMS sanno perfettamente che i valori autoincrementati sono usati come chiave (i campi autoincrementati non sono standard, sono estensioni ormai universalmente usate) e quindi scommetto che sono ottimizzatissimi by default. :D

    Inoltre il disaccoppiamento chiave-dati è ottimo in chiave di protezione identità. Un conto è parlare di “Utente con ID 200″ (e l’ID non c’entra nulla col resto dei dati) e uno è dire “Utente Mario Rossi”. Un po’ come quando per risolvere un’equazione introduci termini a somma/rapporto unitario (modifica equivalente) per risolverla più agevolmente. Introduci per risolvere… :D

    Dimmi un singolo campo dell’anagrafica standard di una persona che sia davvero univoco. Non vale aggregare campi come uno solo… :D

  18. 27 Novembre 2008 alle 16:32 | #18

    ma quindi il problema non sta nel fatto di usare il CF come chiave ma di “volere” un sistema dove siano tollerati (o tollerabili) gli errori degli operatori o dei clienti.
    Forse sarò un poco troppo pragmatico (lo ammetto :) ) … ma io troverei corretto che se vado a richiedere una visita all’ospedale e mi chiedono la tessera sanitaria e io non ce l’ho con me, mi dicano torni la prossima volta :)

    Ma poniamo il caso di voler gestire sistemi “tolleranti” e alcune volte si ha la necessità che sia così (e.g., sistema di gestione bibliotecario… i libri non hanno un codice fino a quando non li registri ;) ), non sarebbe forse opportuno gestire le chiavi non come campi auto-incrementanti ma come qualcosa di più sofisticato (a livello di applicativo e non di DB) tipo un UUID generato prima di inserire i record (di algoritmi ce ne sono tanti che sono ottimi), in modo da evitare i campi auto-incrementanti.

    Se non si fosse capito… *non li sopporto* :P

    cheers

  19. 27 Novembre 2008 alle 16:38 | #19

    JP, se si vuole preservare la privacy nessuno seriamente penserebbe di usare il campo auto-incrementante… ci sono fior fiore di algoritmi che gestiscono l’anonimizzazione dei dati (e.g., k-anonymity), e ci sono anche leggi specifiche da rispettare (anche in Italia, strano ma vero), nel caso i DB debbano contenere dati anagrafici e dati sensibili.

    Per quanto riguarda i magici contatori auto-incrementanti super ottimizzati… non ci conterei molto (considerando che viviamo in un mondo dove Oracle ha inserito il supporto all’operatore di join da pochi anni ;) ). Le strutture dati per gestire gli indici non variano in base al dominio del dato ed è quella che garantisce le prestazioni (non il dominio stesso).

    cheers

    P.S. post molto attivo… si vede che sto litigando con i tedeschi? :P

  20. jp
    27 Novembre 2008 alle 16:45 | #20

    Non vorrei dire ma le librerie serie hanno codici speciali “pro-tempore” univoci e non riciclabili per i libri non ancora schedati.

    Il valore univoco come lo calcoli? Sui libri, è facile.

    Ma sulle anagrafiche? Qualunque algoritmo che usi deve essere deterministico nel darti lo stesso valore con gli stessi input. Quindi prima o poi 2 individui avranno le stesse cose o, peggio, lo stesso “hash”.

    Come puoi escludere, matematicamente parlando, la possibilità che partendo dai dati di due individui, con un algoritmo a caso, si arrivi allo stesso hash o UUID? Ci metti un salt come gli UNIX? A quel punto usa direttamente una chiave extra autoincrementata e stop. :D

    La risposta è ovvia: non puoi. Siamo 7 miliardi, dopotutto…

    L’unica è estraniarsi dal dato stesso e generarne uno assolutamente slegato ad esso e che gli faccia da chiave…

    A livello prestazionale, aggregare più campi come chiave richiede più tempo da processare rispetto ad un singolo campo extra. Un conto è fare hash(singolo int), un conto è fare hash(funzione(lista campi))…

  21. 27 Novembre 2008 alle 17:00 | #21

    non parlavo di librerie, ma biblioteche… se ci fermassimo alle librerie il valore unico e l’ISBN (o analogo)… per le biblioteche il codice del libro (che non ha nulla a che fare col codice dewey) deve essere univoco anche per copie multiple… e solitamente viene associato quando si fa l’inserimento dello stesso nel catalogo di biblioteca.

    non ho capito due dei tuoi punti:
    - “Qualunque algoritmo che usi deve essere deterministico nel darti lo stesso valore con gli stessi input”. Perchè? Non mi sembra che i campi auto incrementanti siano univoci a parità degli altri attributi della tupla.
    - “A livello prestazionale, aggregare più campi come chiave richiede più tempo da processare rispetto ad un singolo campo extra” … questo è vero però è da vedere l’ordine di grandezza di questo tempo in più rispetto al tempo di ricerca all’interno degli indici.

    P.S. per dimostrarti che il campo auto-incrementante è il male di tutto ti ricordo che il primo “DBMS” che l’ha usato è stato Access di M$ :P

    cheers

  22. jp
    27 Novembre 2008 alle 17:11 | #22

    Il cielo è azzurro, l’acqua trasparente e in una tabella i campi autoincrementati senza possibilità di riciclo sono univoci “finchè DROP DATABASE non li separi” (anche a livello di tupla). :P

    Per avere una ragionevole certezza di univocità su una tabella anagrafica ti serve aggregare un bel po’ di campi, erro? Bye bye prestazioni… :D

    PS: MS Jet (il DBMS, Access è solo la GUI per fortuna :P ) non è nato in seno a MS quindi non “fu” male, almeno inizialmente… :D

  23. 27 Novembre 2008 alle 17:12 | #23

    ah ok… forse ho capito… per il primo punto ti stavi riferendo alla privacy :)
    Comunque vale sempre il commento che ho fatto :)

    cheers

  24. 27 Novembre 2008 alle 17:15 | #24

    con il CF non hai bisogno di aggregare :) e sul fatto prestazioni comunque non concordo :)

    Per quanto riguarda MS JET hai ragione… nel senso che il DBMS dientro ad Access è MS JET, ma per quanto mi risulta già la prima release era targata mamma MS…

    cheers

  25. jp
    27 Novembre 2008 alle 17:25 | #25

    Mettiamola così: il CF andrebbe bene se fosse davvero univoco e/o se tu avessi la certezza di usarlo sempre univocamente.

    Nel mondo reale (e la Bau lo sa benissimo avendolo sperimentato su DB di enormi proporzioni) purtroppo non è così…

    Qualunque soluzioni usi per aggregare dati, la paghi sempre in più rispetto ad averne una singola e già pronta da usare (es: campo incrementato univoco). O ti tieni via un valore precalcolato o te lo ricalcoli ogni volta, o fai ricerche in parallelo, o $ALTRA_SOLUZIONE ma in ogni caso paghi sempre qualcosa…

    Su Jet hai ragione: mi son confuso con l’antenato FoxPro acquisito da mamma MS… :D

  26. 27 Novembre 2008 alle 17:35 | #26

    il fatto è che per sua natura il CF è da considerare univoco (sai come sarebbe bello se le mie tasse le pagasse qualcu’altro :) ) … se permetti di usarlo in modo non univoco o (a) hai sbagliato qualcosa a livello di progettazione, o (b) nei sei consapevole (è una “features”) e ne devi scendere a patti.

    Il fatto è che tu consideri sbagliato “aggregare i dati” perché è costoso… in realtà il fatto di aggregare i dati provoca un aumento di costi lineare nel numero di campi e quindi (su db di dimensioni reali) di molti ordini di grandezza inferiore rispetto alle operazioni fatte sull’intera tabella dove i dati risiedono. Se poi dici che il problema è che i campi su cui aggreghi non sono indicizzati… bhe allora il problema è di design :)

    Comunque, vorrei farti notare, che l’uso del campo auto-incrementante lo paghi… subito dopo averlo “creato” (via INSERT), quando lo devi andare a recuperare… lo paghi poco… vero… molti ordini di grandezza in meno rispetto all’operazione di INSERT :P

    cheers

  27. 27 Novembre 2008 alle 17:46 | #27

    “non sarebbe forse opportuno gestire le chiavi non come campi auto-incrementanti ma come qualcosa di più sofisticato (a livello di applicativo e non di DB) tipo un UUID generato prima di inserire i record”
    Basta un rallentamento, una macchina più inchiodata di un’altra e sei fottuto (perdonate il francesismo).
    E anche tutti gli algoritmi che vuoi/puoi usare si mangiano risorse e potrebbero rallentare il tuo programma.
    Ehy! c’è qualcuno che crea in modo sicuro la chiave al posto mio e si smazza tutto! Perché devo farlo io che sono cooooosì pigra? ;)

    Tornando al discorso CF (ma a questo punto estendo a tutti i campi varchar): supponiamo che decidiamo di usare come chiave esterna COGNOME_NOME e che ci sia una tabella dove ad ogni chiave corrispondono + record.
    Non rabbrividiresti anche tu a vedere una sfilza di COGNOME_NOME? :$

    Temo che alla fine di questa discussione ognuno resterà cmq fermo sulle proprie posizioni. XD

  28. 27 Novembre 2008 alle 17:52 | #28

    > “Temo che alla fine di questa discussione ognuno
    > resterà cmq fermo sulle proprie posizioni. XD”

    questo e sicuro… ma non penso che nessuno inizialmente abbia mai pensato di poter far cambiare idea a qualcu’altro :)

    > Basta un rallentamento, una macchina più inchiodata
    > di un’altra e sei fottuto (perdonate il francesismo).

    non ne sono così sicuro (dipende come sono implementate le applicazioni)… ma se la mia applicazione si crea il suo UUID e lo usa per fare tutte le sue INSERT, UPDATE, etc. dentro la sua bella transazioncina… non vedo come può fregarti :) … (mi sono messo nello stesso caso esemplificativo del post originale… siamo partiti da li ;)

    > supponiamo che decidiamo di usare come chiave
    > esterna COGNOME_NOME e che ci sia una tabella
    > dove ad ogni chiave corrispondono + record. Non
    > rabbrividiresti anche tu a vedere una sfilza di
    > COGNOME_NOME?

    si… ma non molto di più di vedere una sfilza di numero 12345 :)

    cheers

  29. jp
    27 Novembre 2008 alle 17:55 | #29

    Una volta che un campo è inserito e marcato read-only (campo autoincrementato ad esempio :P ) sei a posto sempre+comunque e non devi più calcolare nulla a differenza dei “conti” sui campi aggregati… :D

  30. 27 Novembre 2008 alle 18:02 | #30

    i ” “conti” sui campi aggregati” sono solitamente delle operazioni di confronto… che fai comunque anche sui campi auto-incrementanti… altrimenti i join non li fai ;)

  31. 27 Novembre 2008 alle 18:02 | #31

    opsss… ho dimenticato il

    cheers :P

  32. jp
    27 Novembre 2008 alle 18:38 | #32

    Allora, in termini simil-C:

    auto_inc_t chiave;

    varchar nome;
    varchar cognome;
    date data_nascita;

    Vuoi dirmi seriamente che è la stessa cosa fare find(chiave) e find(funzione(nome, cognome, data_nascita, …))?

    Scusa ma non credo proprio…

    Opzioni:

    - precalcoli funzione(nome, cognome, data_nascita, …) e lo metti da qualche parte, in memoria o su disco.

    - fai confronti campo-campo in parallelo

    Tutte assolutamente più costose di usare direttamente chiave.

    Considerando che anche trovando una soluzione paragonabile come performance a funzione(chiave) stai usando aggregati senza certezza di univocità (“chiavi della mutua”), direi che una chiave autoincrementata ha MOLTO diritto di esistere…

    Ah, altro motivo per ottimizzare: siccome so che la chiave autoincrementata non c’entra nulla con i dati, hai una vaga idea di che splendide ottimizzazioni potrebbero saltar fuori come bonus? :D

    Infine, e qui sta la gabola, sei convinto che tu richieda funzione(nome, cognome, data_nascita) e lui, il DBMS, in maniera trasparente e silente non crei una chiave nascosta autoincrementata e ti faccia credere di ascoltarti? :D

  33. 27 Novembre 2008 alle 19:44 | #33

    “non ne sono così sicuro (dipende come sono implementate le applicazioni)… ma se la mia applicazione si crea il suo UUID e lo usa per fare tutte le sue INSERT, UPDATE, etc. dentro la sua bella transazioncina… non vedo come può fregarti :) … ”

    Appunto per questo dico: io calcolo UUID, per quaclhe cavolo di motivo mi si inchioda la macchina e qualcun altro calcola lo stesso UUID.. e magari io avevo già fatto alcune insert su alcune tabelle e non avevo ancora finito…
    Non sto dicendo che sia il db che ti frega, ma la tua apllicazione.

  34. 28 Novembre 2008 alle 08:57 | #34

    @JP: come ha detto la tua Bau, su queste cose possiamo stare a discuterne a vita (basta vedere la lunghezza di questo post ;) ) … ti lascio però con due domande provocatorie come la tua: non ti chiedi come mai (a) in tutti i corsi di DB non si parla mai di usare come chiavi indici numerici che non appartengono al dominio del problema (e.g., chiavi auto-incrementanti)? (b) perché se la chiave auto-incrementante è così bella, nello standard SQL non c’è?
    Comunque per rispondere alla tua (“Infine, e qui sta la gabola, sei convinto che tu richieda funzione(nome, cognome, data_nascita) e lui, il DBMS, in maniera trasparente e silente non crei una chiave nascosta autoincrementata e ti faccia credere di ascoltarti?”): per almeno un ottimo DBMS ne sono sicuro: PostgreSQL:)

    @Nemuriko: due cose da non dimenticare:
    - la tua applicazione A sta lavorando dentro una transazione e quindi se qualcosa va storto dovrebbe fare un rollback e quindi dati spuri non ne rimangono;
    - ho parlato di UUID e quindi per sua natura univoco ;) se due applicazioni A e B potessero generare lo stesso UUID non sarebbe più univoco :P

    cheers

  35. 29 Gennaio 2009 alle 14:44 | #35

    int mysql_insert_id ([ resource $link_identifier ] )

    inserendo il resource $link_identifier HAI l’id di quel inserimento!

  36. 29 Gennaio 2009 alle 16:04 | #36

    @Paladinux: non mi sembra che tu abbia letto proprio tutto.. cmq.. da http://it.php.net/manual/en/function.mysql-insert-id.php

    “mysql_insert_id() converts the return type of the native MySQL C API function mysql_insert_id() to a type of long (named int in PHP). If your AUTO_INCREMENT column has a column type of BIGINT, the value returned by mysql_insert_id() will be incorrect. Instead, use the internal MySQL SQL function LAST_INSERT_ID() in an SQL query.
    Note: Because mysql_insert_id() acts on the last performed query, be sure to call mysql_insert_id() immediately after the query that generates the value.

    Note: The value of the MySQL SQL function LAST_INSERT_ID() always contains the most recently generated AUTO_INCREMENT value, and is not reset between queries. “

    E comunque si stava parlando di transactions.

  37. jp
    29 Gennaio 2009 alle 16:48 | #37

    Ciau!

    In uno dei miei commenti di questo thread (N° 8 dall’alto) ho spiegato il rischio. Magari è un dubbio/problema solo teorico applicato a MySQL, magari no… ^^’

  38. Guderian
    9 Dicembre 2009 alle 01:07 | #38

    Ciao, giusto un commento sul tema chiavi id_auto_inc e chiavi varchar :
    posso capire la simmetria e il rigore nella struttura di un db che usa come chiavi i campi dati effettivi (che possono anche lorev avere l’unicità garantita se definisci un indice di tipo UNIQUE) , ma provate a confrontare le prestazioni tra i due tipi di db facendo delle aggregazioni complesse a più livelli tra le tabelle.
    il DBMS aggrega dati da tabelle linkate con chiavi id a scheggia, mentre prima di fare lo stesso con delle tabelle con chiave stringa comincia a desiderare di suicidarsi !
    io ho, purtroppo, dovuto farle dovendo importare dati in MySQL da un applicativo MS che usava chiavi varchar(60), e non vi dico per fare delle viste e delle viste di viste quanti secondi ci metteva. specifico che ovviamente tutte queste tabelle singolarmente avevano gli indici a posto :)

    c’è una enorme differenza di prestazioni,che è appunto uno dei motivi x cui gli sviluppatori dei DBRMS hanno introdotti le primary key con auto_increment, xè fare join usando chiavi INT è infinitamente + preformante che farlo con chiavi VARCHAR. naturalmente maggiore è il numero delle join maggiore è la differenza di prestazioni.

    su mysql last_insert_id, avete ragione entrambi, su singolo thread è sicura xè basata sull id di connessione, mentre su multi-thread il dubbio rimane (nn ho avuto tempo di documentarmi in merito, sorry)
    ciao

  39. jp
    9 Dicembre 2009 alle 08:25 | #39

    Ah beh, i confronti stringa-stringa sono estremamente costosi. Dovendo usare una stringa come indice, probabilmente mi creerei un campo nascosto con l’hash della stringa… :D

    Ciao e grazie per essere passato! :D

  1. No trackbacks yet.