MySQL InnoDB transakcije

A kdo ve če je tole slučajno možno:
imam v transakciji recimo simpl SQL

SELECT * FROM tabela WHERE nekopolje=4 ORDER BY sortpolje LIMIT 1 FOR UPDATE;

če se sedaj večkrat kliče ta stavek v različnih transakcijah se da zadeva na neko wait listi in ko se 1. transakcija zaključi s commit dobi naslednja rezultat.

In sedaj 1mil$ question :)
a je možno da namesto da čakajo transakcije vrnejo 1. nezaklenjeno vrstico?
Omogoča slučajno to katera druga baza? PostGres recimo ali oracle?
Rabil bi nujno to opcijo pa bi jo naredil na nivoju baze, nebi rad programsko čaral tega.

lp

7 odgovorov

našel sem da oracle omogoča FOR UPDATE NOWAIT in FOR UPDATE SKIP LOCKED
pa verjetno tudi najnovejši PostGre.

Še vedno me pa za MySQL zanima če se je kdo srečal s podobnim problemom.

Ne poznam, me pa zanima, v kakšnih primerih to potrebuješ? Ta lock ti prepreči dostop do zapisa, ker ga nameravaš spremeniti, torej nočeš, da ga kdo bere, dokler je v tem procesu. Če ti je vseeno, ali dobiš staro ali svežo vrednost, potem ne uporabi FOR UPDATE, temveč navaden select. Vzporedne transakcije bodo lahko do zapisa dostopale, dokler prva ne izvede updejta, torej ne samo do selecta.

rabim zato ker imam narejeno čakalno vrsto. Ki se bo polnila preko spletnega portala.
Iz čakalne vrste bo pa daemon vzel 1. vrstico in jo bo obdelal. In spet 1. vrstico in jo bo obdelal. Ker se gre pa za hitrejšo obdelavo bo možnost uporabe več daemonov, ki bodo obdelovali podatke. Ampak če en deamon 1. vrstico obdeluje in jo zaklene, ne rabijo ostali čakat da jo sprosti ampak da mu vrne naslednjo prosto.

Čeprav bi šlo tudi tako, da se pač čakajo med sabo, ker bi bil delay minimalen, a samo dokler št. daemonov nebi bilo preveliko. In če že delam sistem potem že v štartu raje naredim tako kot se gre :)

Če spustim FOR UPDATE je isto kot če ga dodam. Proces čaka da tisti ki je zaklenil podatek sprosti.

Aha, razumem. Jaz se ne bi zanašal na locking baze za logiko deljenja podatkov, ne zato, ker ne bi delovalo, ampak ker se mi zdi, da spada to drugam. Recimo, da ena skripta izvaja selecte in jih pošlje workerjem, ki jih obdelujejo, rezultat pa zapišejo v bazo, hkrati pa izvedejo update na tem recordu (označijo recimo status=complete). Master skripta pa ves čas selecta neobdelane. Bi se dalo to še na par načinov, ampak jaz bi se res izognil bazi.

Ena ideja, ki jo bom implementiral bo ta da bodo taski dodeljeni skupini workerjev. Znotraj te skupine bojo pa po principu roundrobin dobili taske- Že to ji bo palo razparceliralo. Če ne bo šlo drugače bom pa z oracle express integriral. Sam moram preverit če deluje python <-> oracle. Ker so workerji v pythonu pisani.

Ja pa še to idejo sem imel

select * from tabela where pogoj order by kolona, rand() limit 1

čeprav je rand() počasen pri velikem št. vrstic.
Bi moral tole potestirat na eni večji tabeli

tukaj bi bila verjetnost majhna, da dobita 2 procesa isto, bi bilo praktično identično SKIP LOCKED. Ker mi vrstni red obdelave niti ni tako pomemben.

ja, pri veliko podatkih je rand() počasen, ker mora izbrati prav vse zapise in jih potem še razvrstiti. Poleg tega imaš še vedno neko realno možnost, da dva dobita isti zapis.