MySQL SELECT in UPDATE v istem SQL stavku
5 naročnikov
5 naročnikov
Ali kdo pozna način, kako iz MySQL baze podatkov najprej izbrati vrstico in jo v istem hipu update-ati. Nekaj takega kot spodaj, a le v enem stavku:
SELECT * FROM ... LIMIT 1;
UPDATE ... SETupdating
='1' (izbrano vrstici)
Ozadje:
verjetno je to ena najpogostejših operacij: izbereš vrstico, ki jo boš posodabljal in jo označiš kot "zasedeno" - ki se update-a. Naslednji, ki izbira vrstico za posodobljati ne sme izbrati iste, ker se ta že posodablja.
Težava:
Če 2 uporabnika(programa) istočasno izbirata vrstico, ki jo bosta posodabljala, bosta oba izbrala isto (ker je noben še ne uspe UPDATE-ati kot zasedeno).
Kako rešiti zgornji problem v MyISAM bazi podatkov?
Hvala za vse nasvete
7 odgovorov
ponavadi delaš tako
UPDATE imetabele tab1
SET imepolja=(SELECT imepolja FROM imetabele2 tab2 WHERE tab1.imepolja=tab2.imepolja LIMIT 1)
WHERE ID=xyz
Se pravi, narediš stavek UPDATE, kličeš pa določen SELECT za neko polje.
Ti to reši problem prve težave?
Zakaj bi dva hkrati updatala isto tabelo (v tisočinko hkrati?) takoj ko nekdo da update na tabelo in vrstico se ta ohrani v seji. Drugemu pa pa reče da ni možno updatat zaradi tega ali onega razloga.
Pozna se šele potem ko prvi da commit. Je pa res da je to iz Oracla vrjetno je tudi tukaj dosti podobno. Tam bi to rešil z pl/sql vrjetno se da tukaj rešit to s kakim php-jem?
Če imaš v tej tabeli nek indikator uporabnika (ali seje, ...), lahko narediš npr. UPDATE pred INSERT:
UPDATE SET updating=1,updater=@1234 WHERE updater=NULL,...
SELECT WHERE updating=1 AND updater@1234, ...
Drugače pa uporabi zaklepanje pred pisanjem na celotni tabeli (LOCK TABLES). MyISAM, če se ne motim, ne podpira zaklepanja na nivoju vrstice.
[EDIT]: Tist updating me moti, zaradi "ing". Če izvajaš več poizvedb, ki so odvisne med seboj nujno s transakcijo.
UPDATE imetabele tab1
SET imepolja=(SELECT imepolja FROM imetabele2 tab2 WHERE tab1.imepolja=tab2.imepolja LIMIT 1)
WHERE ID=xyz
Gogy: kako s tem pridobim tudi vsebino vrstice, ki jo bom update-al? Bistvo je, da označim vrstico, ki jo bom posodobil, nato pa to vrstico preberem (da jo lahko začnem obedlovati)
Zakaj bi dva hkrati updatala isto tabelo
Tody: gre za design: ne sme obstajati opcija, da 2 izbereta isto vrstico in jo sočasno posodabljata.
Če imaš v tej tabeli nek indikator uporabnika (ali seje, ...), lahko narediš npr. UPDATE pred INSERT:
UPDATE SET updating=1,updater=@1234 WHERE updater=NULL,...
SELECT WHERE updating=1 AND updater@1234, ...
Packac: tvoja rešitev reši problem, a precej zakomplicira zadevo, ker je potrebno identificirati updater-je in dodati novo polje v tabelo.
Ideja s transakcijami mi je najbolj všeč. Ali MySQL z MyISAM omogoča transakcije? Pa ne sme se zgoditi, da je v času transakcije tabela zaklenjena, ker potem vsi procesi čakajo, kar vodi v ... vedno daljše vrste in kolaps sistema.
Smo zakompliciral. Dejansko je OK tako kot imaš nastavljen updating stolpec in s tem lahko implementiraš "row lock".
UPDATE ... SET updating
='1 WHERE updating<>1
Potem pa pogledaš affected rows.
Ja, MyISAM ne podpira transkakcij.