|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: May 2005
Città: Messina
Messaggi: 15654
|
Come gestire la concorrenza tra record?
Salve mi sono avvicinato da poco alla programmazione in visual c# e sono tutt'altro che un programmatore esperto. Fatta questa piccola premessa, ho l'importante necessità, di implementare una gestione della concorrenza su un record durante le operazioni di modifica. Questo vuol dire che avendo due pc che contemporaneamente utilizzano questo software, il primo che tra i due avvia la modifica di un record, deve "bloccare" quel record in modo che quando e se, con la seconda istanza del programma, si tenterà di modificare lo stesso record, verrà mostrato un normalissimo messaggio e venga interrotta la procedura.
Come dbms utilizzo MySql e l'unica cosa che sono riuscito a fare é quella di bloccare il record con "START TRANSACTION" fino a quando non faccio COMMIT o chiudo la connessione. Il problema è che non so come verificare se vi è una transazione attiva o un qualche tipo di blocco per interrompere la procedura e questo comporta che la seconda istanza del programma resta completamente bloccata fin quando non sblocco il record dalla prima istanza. Soluzioni? Grazie per l'attenzione. Inviato dal mio GT-I9300 con Tapatalk 2
__________________
CASE: Antec 900 - ALI: Enermax Pro82+ 525W - MOBO: Asus Z97I-Plus - CPU: i7 4770k @ 4.4 Ghz 1.22v - DISSI: Noctua U-14S - RAM: 2x8GB Corsair Vengeance LP @ 1866 Mhz - VGA: GTX 1070 ARMOR 8G OC - Monitor: Acer XF270HU - SSD: Samsung 850 EVO 500 GB MacBook Pro Retina 15" 2018 - i7 6 core, Radeon Pro 560X, 512 GB SSD
|
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
La gestione mediate transaction che stai facendo e' corretta.
Potresti pero' far fare le modifiche a partire da un altro Thread in background, cosi' non bloccherai la GUI e il secondo thread entrante attendera' che la transazione del primo sia finita. Se la parte di applicativo e' il classico "leggo e faccio vedere la tabella e permetto l'aggiornamento" allora aggiungerei il classico "Last_Modified" o una qualche sequence come colonna aggiuntiva della tabella in questione. Ogni qual volta si aggiunge/inserisce un record nella tabella si deve gestire anche il last_modified o la sequence. Colui che prende controllo del record, subito dopo avere aperto la transazione deve controllare che il campo della sequence corrisponda a quanto da lui ottenuto in fase di lettura precedente di questo specifico record Se sono diversi significa che il record e' stato nel frattempo aggiornato da qualche altro client. E occorrerebbe interrompere l'aggiornamento perche' si e' in possesso di dati staled e l'utente ha eventualmente compiuto decisioni errate. Si potrebbe a questo punto richiedere i dati nuovi, rinfrescare l'immagine della tabella del client e si puo' chiedere all'utente di reinserire i dati.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: May 2005
Città: Messina
Messaggi: 15654
|
Ciao e grazie per la risposta.
Il problema è che se io (primo pc) faccio START TRANSACTION e comincio a modificare quel record, me lo ritrovo bloccato, come è corretto che sia, se però il record da modificare è lungo e vengo interrotto nel mezzo della modifica, o semplicemente mi scordo che lo stavo modificando, questo record resta bloccato anche per mezz'ora. Dall'altra parte (secondo pc), il software tenta di avviare la transazione ed il software si blocca completamente, fino a quando, dopo 55 secondi, innodb va in timeout e compare l'eccezione di timeout... possibile che non ci sia il modo di vedere SUBITO se quel record è attualmente bloccato?
__________________
CASE: Antec 900 - ALI: Enermax Pro82+ 525W - MOBO: Asus Z97I-Plus - CPU: i7 4770k @ 4.4 Ghz 1.22v - DISSI: Noctua U-14S - RAM: 2x8GB Corsair Vengeance LP @ 1866 Mhz - VGA: GTX 1070 ARMOR 8G OC - Monitor: Acer XF270HU - SSD: Samsung 850 EVO 500 GB MacBook Pro Retina 15" 2018 - i7 6 core, Radeon Pro 560X, 512 GB SSD
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Mi sa che e' meglio che lasci stare un'architettura 2 livelli e metti un server in mezzo.
Questo server potra' notificare quando un record e' bloccato e quando sara' sbloccato a tutti i sottoscrittori, facendo vedere on-screen qualcosa al volo (Es i record bloccati vengono messi con background giallo e ci si impedisce a priori il focus nei propri campi). Altrimenti, qualunque cosa tu metta per capire se "Il record e' stato bloccato" avrebbe side effect di multithreading. 1. Tu Controlli che sia bloccato 2. Non e' bloccato 3. Arriva Io e lo blocco ora 4. Tu cerchi di partire e ti ritrovi bloccato con il timeout.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: May 2001
Messaggi: 12883
|
Domanda: ma i DB non dovrebbero gestire in maniera nativa la concorrenza?
|
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: May 2005
Città: Messina
Messaggi: 15654
|
Quote:
__________________
CASE: Antec 900 - ALI: Enermax Pro82+ 525W - MOBO: Asus Z97I-Plus - CPU: i7 4770k @ 4.4 Ghz 1.22v - DISSI: Noctua U-14S - RAM: 2x8GB Corsair Vengeance LP @ 1866 Mhz - VGA: GTX 1070 ARMOR 8G OC - Monitor: Acer XF270HU - SSD: Samsung 850 EVO 500 GB MacBook Pro Retina 15" 2018 - i7 6 core, Radeon Pro 560X, 512 GB SSD
|
|
|
|
|
|
|
#7 | ||
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Quote:
E' un altro componente. Potresti appoggiarti ad IIS e scrivere un servizio web, oppure potresti scrivere un Windows Service, come quelli che appaiono nel pannello di controllo -> Servizi
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
||
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: May 2005
Città: Messina
Messaggi: 15654
|
Quote:
PS mio padre che è un programmatore di vecchia data del linguaggio Clipper, mi diceva che in Clipper c'è l'istruzione RLOCK che fa il tutto, possibile che in linguaggi così avanzati come il C# non sia presente?
__________________
CASE: Antec 900 - ALI: Enermax Pro82+ 525W - MOBO: Asus Z97I-Plus - CPU: i7 4770k @ 4.4 Ghz 1.22v - DISSI: Noctua U-14S - RAM: 2x8GB Corsair Vengeance LP @ 1866 Mhz - VGA: GTX 1070 ARMOR 8G OC - Monitor: Acer XF270HU - SSD: Samsung 850 EVO 500 GB MacBook Pro Retina 15" 2018 - i7 6 core, Radeon Pro 560X, 512 GB SSD
|
|
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Un programma con un RLOCK sara' fatto piu' o meno cosi' 1) Utente tenta di editare un campo 2) RLOCK per vedere se il record e' locked 3) Se non e' locked permetto di editare il campo Ma in ambiente multitasking puo' capitare 1) Utente tenta di editare un campo 2) RLOCK per vedere se il record e' locked 2B) <<< Qui, immediatamente dopo il mio tentativo di RLOCK entra un altro attore a fare il lock sul record. 3) Se non e' locked permetto di editare il campo 3B) <<< Io qui fallisco, perche' oramai il record e' locked. Il compito del server sara' quello, fra le altre cose, di fungere da proxy per l'aggiornamento dei campi. Essenzialmente il server funge da brodcast di messaggi per indicare quali record sono liberi e quali sono invece locked. Prima di editare un campo di un record libero, dico a questo server che mi riservo il compito di bloccare quel record. Il server restituisce OK o KO a seconda che il record sia effettivamente libero. Il server inoltre eventualmente (feature aggiuntiva carina) propaga questa informazione a tutti i client in ascolto, che saranno liberi di usare questa informazione come vogliono (Magari dipingendo di giallo i record bloccati) Quando ho finito di usare un record, allora diro' al server che non ho piu' intenzione di usarlo. Il server di nuovo eventulamente in broadcast segnalera' a tutti i clienti in ascolto che il record e' libero (Ridipingendo i record del colore "libero") 2 metodi quindi: public bool Lock(int RecordNum) Che resitutisce true o false a seconda che io sia riuscito a riservare il record per me oppure no public void Unlock(int RecordNum) per sbloccare il record in questione. Ovviamente il codice di questi metodi deve essere gestito in regione critica, tutto essenzialmente dentro una lock
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. Ultima modifica di gugoXX : 26-11-2012 alle 09:53. |
|
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: May 2005
Città: Messina
Messaggi: 15654
|
EDIT.
__________________
CASE: Antec 900 - ALI: Enermax Pro82+ 525W - MOBO: Asus Z97I-Plus - CPU: i7 4770k @ 4.4 Ghz 1.22v - DISSI: Noctua U-14S - RAM: 2x8GB Corsair Vengeance LP @ 1866 Mhz - VGA: GTX 1070 ARMOR 8G OC - Monitor: Acer XF270HU - SSD: Samsung 850 EVO 500 GB MacBook Pro Retina 15" 2018 - i7 6 core, Radeon Pro 560X, 512 GB SSD
Ultima modifica di rizzotti91 : 26-11-2012 alle 14:16. |
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: May 2001
Messaggi: 12883
|
|
|
|
|
|
|
#12 | |
|
Moderatore
Iscritto dal: Nov 2006
Messaggi: 21883
|
Quote:
a questo punto non fai prima a preparare a parte la query di modifica così ti basta lanciarla con la sua transazione e non devi lasciarla aperta mezzora?
__________________
"WS" (p280,cx750m,4790k+212evo,z97pro,4x8GB ddr3 1600c11,GTX760-DC2OC,MZ-7TE500, WD20EFRX) Desktop (three hundred,650gq,3800x+nh-u14s ,x570 arous elite,2x16GB ddr4 3200c16, rx5600xt pulse P5 1TB)+NB: Lenovo p53 i7-9750H,64GB DDR4,2x1TB SSD, T1000 |
|
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: May 2005
Città: Messina
Messaggi: 15654
|
Quote:
__________________
CASE: Antec 900 - ALI: Enermax Pro82+ 525W - MOBO: Asus Z97I-Plus - CPU: i7 4770k @ 4.4 Ghz 1.22v - DISSI: Noctua U-14S - RAM: 2x8GB Corsair Vengeance LP @ 1866 Mhz - VGA: GTX 1070 ARMOR 8G OC - Monitor: Acer XF270HU - SSD: Samsung 850 EVO 500 GB MacBook Pro Retina 15" 2018 - i7 6 core, Radeon Pro 560X, 512 GB SSD
|
|
|
|
|
|
|
#14 | |
|
Senior Member
Iscritto dal: May 2005
Città: Messina
Messaggi: 15654
|
Quote:
Quando io non capisco un quesito, o non sono in grado di rispondere, mi astengo dal farlo, sarebbe cosa gradita che tutti gli utenti del forum rispettassero questa semplice regola.
__________________
CASE: Antec 900 - ALI: Enermax Pro82+ 525W - MOBO: Asus Z97I-Plus - CPU: i7 4770k @ 4.4 Ghz 1.22v - DISSI: Noctua U-14S - RAM: 2x8GB Corsair Vengeance LP @ 1866 Mhz - VGA: GTX 1070 ARMOR 8G OC - Monitor: Acer XF270HU - SSD: Samsung 850 EVO 500 GB MacBook Pro Retina 15" 2018 - i7 6 core, Radeon Pro 560X, 512 GB SSD
|
|
|
|
|
|
|
#15 | |
|
Moderatore
Iscritto dal: Nov 2006
Messaggi: 21883
|
Quote:
Se invece di flammare con chi sta cercando di aiutarti ti saresti preso la briga di capire quello che volevo dirti forse risolveresti i tuoi problemi in meno tempo no? mica ho scritto io che tengo attiva una transazione anche per mezzora perchè ti dimentichi quello che stavi facendo e passi ad altro no? mai e poi mai ho visto transazioni rimanere attive aspettando i comodi dell'utente ovvero, le transazioni servono per evitare una doppia sovrascrittura dei dati causati dall'accesso concorrente in scrittura allo stesso record. il solo fatto che tu le usi in questo modo significa che non hai capito cosa sono e cosa servono; il che porta giusto appunto alla mia risposta precedente ovvero devi bloccare il db per il minor tempo possibile il che significa preparare la query di modifica prima e una volta preparata e pronta si lancia sul db con la sua bella transazione che si chiude subito dopo così hai un lock di qualche ms invece che di mezzora anche se ti dimentichi il lavoro a metà ps Una semplice regola di buona educazione consisterebbe nel ringraziare gli utenti che perdono il loro prezioso tempo per aiutare gli altri invece che arrogarsi il diritto di prendersela perché costoro hanno in assistenza la sfera di cristallo; dovresti cercare di capire le risposte che si danno visto che, fino a prova contraria quello che ha una minima esperienza con i database e ha problemi sei tu, invece tu ammetti tranquillamente di non aver capito la risposta ma nel contempo l'hai compresa talmente bene da capire che non andava bene, complimenti per la coerenza
__________________
"WS" (p280,cx750m,4790k+212evo,z97pro,4x8GB ddr3 1600c11,GTX760-DC2OC,MZ-7TE500, WD20EFRX) Desktop (three hundred,650gq,3800x+nh-u14s ,x570 arous elite,2x16GB ddr4 3200c16, rx5600xt pulse P5 1TB)+NB: Lenovo p53 i7-9750H,64GB DDR4,2x1TB SSD, T1000 Ultima modifica di !fazz : 26-11-2012 alle 14:56. |
|
|
|
|
|
|
#16 |
|
Senior Member
Iscritto dal: May 2005
Città: Messina
Messaggi: 15654
|
Potrò anche sembrare brusco, ma IO sono abituato nel chiedere chiarimenti ad un utente se ho intenzione di aiutarlo e se ne ho le conoscenze. Qui non si mette in dubbio la vostra preparazione, dato che sono io quello che ha bisogno di aiuto e non voi... la cosa che mi scoccia di un po' tutti i forum è che si comincia a sparare a vanvera su quello che è stato richiesto. Se avessi capito la mia domanda (e non devi prenderla come un insulto, perchè non capire non vuol dire essere stupidi), avresti capito che la mia transazione deve durare anche 10 ore.
Per gestionale intendo un software che gestisca una grandissima mole di dati, in aziende in cui gli utenti utilizzatori, non stanno seduti accanto, bensì in luoghi ben separati.Se si hanno quindi 100 utenti che stanno lavorando sul Database, è probabile che l'utente A noti un prezzo sbagliato, mentre l'utente B noti che c'è una lettera sbagliata nella descrizione, ed infine, l'utente C nota che c'è qualcosa che non va nell'esistenza. A quel punto, se facessi come hai detto tu, sempre se ho capito, dovrei far inserire ad A il prezzo corretto, a B la lettera ed a C l'esistenza; si cliccka quindi su "conferma" e si avvia la transazione di un secondo che blocca il record e lo sblocca subito. Bene, se questi tre utenti hanno cliccato contemporaneamente, cosa succederà a quel record? Deve essere una gara a chi clicca più in fretta il tasto Conferma? Non è più logico che se A sta modificando il record, B e C non possono fin quando non finisce?
__________________
CASE: Antec 900 - ALI: Enermax Pro82+ 525W - MOBO: Asus Z97I-Plus - CPU: i7 4770k @ 4.4 Ghz 1.22v - DISSI: Noctua U-14S - RAM: 2x8GB Corsair Vengeance LP @ 1866 Mhz - VGA: GTX 1070 ARMOR 8G OC - Monitor: Acer XF270HU - SSD: Samsung 850 EVO 500 GB MacBook Pro Retina 15" 2018 - i7 6 core, Radeon Pro 560X, 512 GB SSD
|
|
|
|
|
|
#17 | |
|
Moderatore
Iscritto dal: Nov 2006
Messaggi: 21883
|
Quote:
non hai capito proprio a cosa servono le transazioni, non prenderlo come un insulto ma non esiste parlare di transazioni, ovvero le transazioni proteggono il db (approposito le transazioni non servono nel caso del tuo esempio in cui 3 utenti cambiono 3 campi diversi dello stesso record, le transazioni servono quando ad esempio l'utente a cambia il prezzo a 5 e l'utente B cambia il prezzo a 10 dello stesso articolo (aka anche senza transazioni non avresti problemi nel gestire un caso come il tuo esempio comunque è più logico che se un utente modifica qualcosa la modifica vada a buon fine se nessun altro ha modificato la stessa cosa prima di lui. quello che vorresti fare tu è un blocco a livello software delle modifiche ma non si fà con la transazione (o meglio devi usare le transazioni quando scrivi sul db ma il blocco devi farlo a livello superiore) tu hai un problema a livello applicativo che stai tentando di risolvere solo a livello di dbms quindi assodato che è sbagliato bloccare un record per tutta la durata dell'operazione hai due strade (che entrambe comportano il lock minimale del db ) 1) usi un campo per contenere lo stato del record, quando vuoi modificare il record la prima cosa che fà il sistema è, usando la transazione cambiare lo stato del record ) e gestire la concorrenza degli utenti direttamente da software lasciando il db libero di girare (il primo utente che prova accede alla modifica agli altri viene risposto picche fino a che non ha terminato) 2) leggi i dati e popoli la maschera, alla conferma controlli se i dati letti in precedenza sono ancora validi o meno e in caso affermativo procedi con la modifica ma ovvviamente controlli solo quelli che hai modificato (ovvero cambi il prezzo e controlli se il prezzo non è stato alterato da altri chissenefrega se qualcuno ha modificato la descrizione) la soluzione due mi pare che sia quella che sia quella più elegante e funzionale comunque ti consiglio bene di riguardare la documentazione relativa alle transazioni perchè non fanno quello per cui vuoi utilizzarle, lo scopo delle transazioni lo vedi bene con la seconda modalità che ti ho spiegato prima ovvero ipotizza che nella tua maschera tu voglia modificare prezzo e descrizione del prodotto inizi la transazione controlli se il prezzo è rimasto invariato (ok) update prezzo.... controlli se la descrizione è invariata (orrore qualcuno l'ha modificata) rollback e le tue modifiche sul db vengono annullate, ritorni alla maschera e gestisci l'evento
__________________
"WS" (p280,cx750m,4790k+212evo,z97pro,4x8GB ddr3 1600c11,GTX760-DC2OC,MZ-7TE500, WD20EFRX) Desktop (three hundred,650gq,3800x+nh-u14s ,x570 arous elite,2x16GB ddr4 3200c16, rx5600xt pulse P5 1TB)+NB: Lenovo p53 i7-9750H,64GB DDR4,2x1TB SSD, T1000 Ultima modifica di !fazz : 26-11-2012 alle 15:55. |
|
|
|
|
|
|
#18 |
|
Senior Member
Iscritto dal: May 2005
Città: Messina
Messaggi: 15654
|
So che le transazioni dovrebbero essere utilizzate per altri scopi, come per esempio per vere e proprie transazioni bancarie, in modo da poter ricorrere al ROLLBACK. Il problema è che non so come posso bloccare un record e se il DBMS permetta di farlo (un po' come avviene con le transazioni) e se questo avviene, com'è possibile rilevarlo da dentro il programma (esiste una qualche query??).
Per il fatto che sia più o meno giusta la mia soluzione, la questione non riguarda il numero di modifiche che vengono effettuate, però ti parlo davvero di decine di utenti che lavorano contemporaneamente ad un database e se io comincio a modificare, tu non devi poter far altro che effettuare ricerche, inserimento e visualizzazione, quel record non lo puoi toccare, anche perchè se io lo sto stravolgendo, cliccko conferma, e "tu" nel frattempo avevi modificato una fesseria e cliccki conferma dopo di me, mi sovrascriverai tutte le modifiche da me effettuate e non è una cosa che posso permettermi accada. Per quanto riguarda un'eventuale gestione software, la cosa a cui avevo pensasto, come da altri suggerito, è una campo di tipo timestamp in ogni tabella, in modo da sapere data/ora della modifica... all'inizio controllo questo valore e lo memorizzo in una variabile, effettuo le varie modifiche, passano i minuti o le ore necessarie e prima di effettuare la query di inserimento, controllo se quel valore nel db è diverso rispetto a quello che ho memorizzato, in tal caso farò apparire un messaggio o una qualsiasi altra cosa. Mi vengono in mente due problemi però: A) Se i pc hanno date diverse tra loro? O se anche i minuti fossero di poco "sballati"? B) Lo vedo un po' inutile farti cominciare a modificare ed a scrivere un bel po' di cose, se tanto l'utente che arriva dopo 5 minuti, modifica una caxxata e ciò comporta il farti comparire il messaggio "Il record è stato modificato, confermi i dati da te inseriti o vuoi ricaricare le informazioni?". Cioè se sei a distanza dall'utente che ha effettuato la modifica, non è neanche molto comodo restare in attesa e chiedere "Ehi cosa hai modificato? Posso sovrascrivere e ri-modifichi?", non so se mi spiego... vorrei bloccare la cosa a monte... Eppure facendo ricerche ho visto che questo approccio che voglio adottare è quello definito "pessimistico" e che è sconsigliato... ma è sconsigliato per quali motivi? Una situazione del genere come andrebbe gestita allora? Ha più importanza l'ultima modifica? PS scusami per il post di prima e grazie comunque per l'interessamento.
__________________
CASE: Antec 900 - ALI: Enermax Pro82+ 525W - MOBO: Asus Z97I-Plus - CPU: i7 4770k @ 4.4 Ghz 1.22v - DISSI: Noctua U-14S - RAM: 2x8GB Corsair Vengeance LP @ 1866 Mhz - VGA: GTX 1070 ARMOR 8G OC - Monitor: Acer XF270HU - SSD: Samsung 850 EVO 500 GB MacBook Pro Retina 15" 2018 - i7 6 core, Radeon Pro 560X, 512 GB SSD
|
|
|
|
|
|
#19 | |
|
Moderatore
Iscritto dal: Nov 2006
Messaggi: 21883
|
Quote:
__________________
"WS" (p280,cx750m,4790k+212evo,z97pro,4x8GB ddr3 1600c11,GTX760-DC2OC,MZ-7TE500, WD20EFRX) Desktop (three hundred,650gq,3800x+nh-u14s ,x570 arous elite,2x16GB ddr4 3200c16, rx5600xt pulse P5 1TB)+NB: Lenovo p53 i7-9750H,64GB DDR4,2x1TB SSD, T1000 |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 15:52.




















