PDA

Bekijk Volledige Versie : Vreemd resultaat transacties PostgreSQL



Math1985
26/03/07, 11:02
Ik laat de volgende queries uitvoeren:

1) begin;
1) delete from forum where id = 20;
1) insert into forum (id, name) values (20, 'test');
2) delete from forum where id = 20;
1) commit;

1) geeft een query aan die uitgevoerd wordt door proces 1 en 2) een query
uitgevoerd door proces 2).
Nu krijgt proces 2 de melding dat er 0 rijen worden verwijderd. Kan iemand
dat verklaren? Ik zelf zou 1 rij verwachten.

id is een uniek veld.

robert
26/03/07, 11:02
Math1985 <usenet2006@matthijsmelissen.nl>:
> Ik laat de volgende queries uitvoeren:
>
> 1) begin;
> 1) delete from forum where id = 20;
> 1) insert into forum (id, name) values (20, 'test');
> 2) delete from forum where id = 20;
> 1) commit;
>
> 1) geeft een query aan die uitgevoerd wordt door proces 1 en 2) een query
> uitgevoerd door proces 2).
> Nu krijgt proces 2 de melding dat er 0 rijen worden verwijderd. Kan iemand
> dat verklaren? Ik zelf zou 1 rij verwachten.

Pas na een commit zijn de resultaten van de insert zichtbaar voor andere
processen, zo werken transacties nou eenmaal (zie een beschrijving van het
ACID principe, http://nl.wikipedia.org/wiki/ACID).

--
robert

math1985@gmail.com
26/03/07, 17:57
On 26 mrt, 08:09, {n.i.w...@allyourbass.org.invalid (robert) wrote:
> Math1985 <usenet2...@matthijsmelissen.nl>:
> > Ik laat de volgende queries uitvoeren:
> >
> > 1) begin;
> > 1) delete from forum where id = 20;
> > 1) insert into forum (id, name) values (20, 'test');
> > 2) delete from forum where id = 20;
> > 1) commit;
> >
> > 1) geeft een query aan die uitgevoerd wordt door proces 1 en 2) een query
> > uitgevoerd door proces 2).
> > Nu krijgt proces 2 de melding dat er 0 rijen worden verwijderd. Kan iemand
> > dat verklaren? Ik zelf zou 1 rij verwachten.

> Pas na een commit zijn de resultaten van de insert zichtbaar voor andere
> processen, zo werken transacties nou eenmaal (zie een beschrijving van het
> ACID principe,http://nl.wikipedia.org/wiki/ACID).

Klopt. Maar zelfs als er al vooraf een rij met id=20 bestaat, krijg ik
nog steeds de melding dat er geen rijen verwijderd worden.
Dus blijkbaar wordt die 1) delete wel gezien? Maar waarom?

robert
26/03/07, 17:57
math1985@gmail.com <math1985@gmail.com>:
> On 26 mrt, 08:09, {n.i.w...@allyourbass.org.invalid (robert) wrote:
>
>> Pas na een commit zijn de resultaten van de insert zichtbaar voor
>> andere processen, zo werken transacties nou eenmaal (zie een
>> beschrijving van het ACID principe,http://nl.wikipedia.org/wiki/ACID).
>
> Klopt. Maar zelfs als er al vooraf een rij met id=20 bestaat, krijg ik
> nog steeds de melding dat er geen rijen verwijderd worden. Dus blijkbaar
> wordt die 1) delete wel gezien? Maar waarom?

Ik kan het niet reproduceren, de DELETE wordt bij mij pas uitgevoerd na de
COMMIT; vóór die tijd kan client 2 het record nog gewoon zien.

--
robert

math1985@gmail.com
26/03/07, 17:57
On 26 mrt, 13:53, {n.i.w...@allyourbass.org.invalid (robert) wrote:
> math1...@gmail.com <math1...@gmail.com>:
> > On 26 mrt, 08:09, {n.i.w...@allyourbass.org.invalid (robert) wrote:

> >> Pas na een commit zijn de resultaten van de insert zichtbaar voor
> >> andere processen, zo werken transacties nou eenmaal (zie een
> >> beschrijving van het ACID principe,http://nl.wikipedia.org/wiki/ACID).

> > Klopt. Maar zelfs als er al vooraf een rij met id=20 bestaat, krijg ik
> > nog steeds de melding dat er geen rijen verwijderd worden. Dus blijkbaar
> > wordt die 1) delete wel gezien? Maar waarom?

> Ik kan het niet reproduceren, de DELETE wordt bij mij pas uitgevoerd na de
> COMMIT; vóór die tijd kan client 2 het record nog gewoon zien.

Dat is fijn te horen. Blijkbaar is er iets mis met mijn SQL-versie, of
mijn instellingen.

De DELETE wordt bij mij ook pas uitgevoerd na de COMMIT (of tegelijk,
dat kan ik niet zien; er wordt in elk geval met uitvoeren gewacht op
de COMMIT) maar toch krijg ik DELETE 0 te zien, niet DELETE 1.

Welke (Postgres?)ql-versie gebruik je?

robert
27/03/07, 11:52
math1985@gmail.com <math1985@gmail.com>:
> On 26 mrt, 13:53, {n.i.w...@allyourbass.org.invalid (robert) wrote:
>
>> Ik kan het niet reproduceren, de DELETE wordt bij mij pas uitgevoerd na
>> de COMMIT; vóór die tijd kan client 2 het record nog gewoon zien.
>
> Dat is fijn te horen. Blijkbaar is er iets mis met mijn SQL-versie, of
> mijn instellingen.
>
> De DELETE wordt bij mij ook pas uitgevoerd na de COMMIT (of tegelijk,
> dat kan ik niet zien; er wordt in elk geval met uitvoeren gewacht op de
> COMMIT) maar toch krijg ik DELETE 0 te zien, niet DELETE 1.
>
> Welke (Postgres?)ql-versie gebruik je?

Ik moet mezelf even corrigeren, ik had niet goed getest. Even opnieuw
geprobeerd, en inderdaad zie ik wat jij ook ziet.

Ik denk dat het volgende gebeurt:
- client 2 wil deleten, haalt de object-id van het te deleten record op, en
blokkeert dan omdat client 1 in een transactie bezig is;
- client 1 commit z'n veranderingen, waarbij de object-id van het record
met id == 20 verandert (je hebt het record immers in je transactie
verwijderd en een nieuw record aangemaakt);
- client 2 probeert een delete uit te voeren op een object-id dat niet meer
bestaat, en geeft daarom 'DELETE 0' terug;

Anders zou ik het ook niet kunnen verklaren.

--
robert

Math1985
27/03/07, 11:52
robert wrote:
> math1985@gmail.com <math1985@gmail.com>:
>> On 26 mrt, 13:53, {n.i.w...@allyourbass.org.invalid (robert) wrote:


| 1) begin;
| 1) delete from forum where id = 20;
| 1) insert into forum (id, name) values (20, 'test');
| 2) delete from forum where id = 20;
| 1) commit;

> - client 2 wil deleten, haalt de object-id van het te deleten record
> op, en blokkeert dan omdat client 1 in een transactie bezig is;
> - client 1 commit z'n veranderingen, waarbij de object-id van het
> record met id == 20 verandert (je hebt het record immers in je
> transactie verwijderd en een nieuw record aangemaakt);
> - client 2 probeert een delete uit te voeren op een object-id dat
> niet meer bestaat, en geeft daarom 'DELETE 0' terug;

Ja, dat klinkt plausibel. MySQL doet trouwens wel de te verwachten 'DELETE
1'.

Wat ik precies wil is dit: ik heb twee clients die tegelijk dit doen:

1) delete from forum where id = 20;
1) insert into forum (id, name) values (20, 'testa');

2) delete from forum where id = 20;
2) insert into forum (id, name) values (20, 'testb');

Ik weet dus niet van te voren in welke volgorde ze dit doen. Ik kan geen
update gebruiken, omdat ik niet zeker weet of er al een rij bestaat met
id=20.
Als ik geen maatregelen qua transacties/locking oid neem, krijg ik de
foutmelding dat er al een id bestaat met waarde 20.

Lijkt mij niet zo'n vreemde taak, dus je zou toch zeggen dat het wel
mogelijk is.

robert
27/03/07, 17:27
Math1985 <usenet2006@matthijsmelissen.nl>:
> robert wrote:
>
>> - client 2 wil deleten, haalt de object-id van het te deleten record
>> op, en blokkeert dan omdat client 1 in een transactie bezig is;
>> - client 1 commit z'n veranderingen, waarbij de object-id van het
>> record met id == 20 verandert (je hebt het record immers in je
>> transactie verwijderd en een nieuw record aangemaakt);
>> - client 2 probeert een delete uit te voeren op een object-id dat
>> niet meer bestaat, en geeft daarom 'DELETE 0' terug;
>
> Ja, dat klinkt plausibel. MySQL doet trouwens wel de te verwachten
> 'DELETE 1'.

Yup, had ik ook even getest.

> Wat ik precies wil is dit: ik heb twee clients die tegelijk dit doen:
>
> 1) delete from forum where id = 20;
> 1) insert into forum (id, name) values (20, 'testa');
>
> 2) delete from forum where id = 20;
> 2) insert into forum (id, name) values (20, 'testb');
>
> Ik weet dus niet van te voren in welke volgorde ze dit doen. Ik kan geen
> update gebruiken, omdat ik niet zeker weet of er al een rij bestaat met
> id=20. Als ik geen maatregelen qua transacties/locking oid neem, krijg
> ik de foutmelding dat er al een id bestaat met waarde 20.
>
> Lijkt mij niet zo'n vreemde taak, dus je zou toch zeggen dat het wel
> mogelijk is.

Waarom draai je ze niet alle twee in een transactie? Een DELETE die geen
rijen weggooit is geen reden voor een transactie om te mislukken.

--
robert

blacklistme@xs4all.nl
28/03/07, 01:37
robert wrote in nl.internet.www.server-side:
> Math1985 <usenet2006@matthijsmelissen.nl>:
> > Ik laat de volgende queries uitvoeren:
> >
> > 1) begin;
> > 1) delete from forum where id = 20;
> > 1) insert into forum (id, name) values (20, 'test');
> > 2) delete from forum where id = 20;
> > 1) commit;
> >
> > 1) geeft een query aan die uitgevoerd wordt door proces 1 en 2) een query
> > uitgevoerd door proces 2).
> > Nu krijgt proces 2 de melding dat er 0 rijen worden verwijderd. Kan iemand
> > dat verklaren? Ik zelf zou 1 rij verwachten.
>
> Pas na een commit zijn de resultaten van de insert zichtbaar voor andere
> processen, zo werken transacties nou eenmaal (zie een beschrijving van het
> ACID principe, http://nl.wikipedia.org/wiki/ACID).

Pgsql is ACID ja, maar werkt wel op basis van [1]MVCC en kan heel soms
leuke effecten hebben. "SET TRANSACTION" nalezen cq aanpassen kan helpen
in dit soort gevallen. Zeker het op SERIALIZABLE zetten gaat je aborts
opleveren als de transacties niet meer serialiseerbaar zijn terwijl het
in veel gevallen ander ook gewoon goed kan gaan.

B.

[1] http://en.wikipedia.org/wiki/Multiversion_concurrency_control

robert
28/03/07, 11:04
blacklistme@xs4all.nl <blacklistme@xs4all.nl>:
> robert wrote in nl.internet.www.server-side:
>>
>> Pas na een commit zijn de resultaten van de insert zichtbaar voor
>> andere processen, zo werken transacties nou eenmaal (zie een
>> beschrijving van het ACID principe, http://nl.wikipedia.org/wiki/ACID).
>
> Pgsql is ACID ja, maar werkt wel op basis van [1]MVCC en kan heel soms
> leuke effecten hebben. "SET TRANSACTION" nalezen cq aanpassen kan helpen
> in dit soort gevallen.

Daar zat ik idd ook mee te spelen.

--
robert

Math1985
28/03/07, 11:04
robert wrote:
>> Wat ik precies wil is dit: ik heb twee clients die tegelijk dit doen:
>>
>> 1) delete from forum where id = 20;
>> 1) insert into forum (id, name) values (20, 'testa');
>>
>> 2) delete from forum where id = 20;
>> 2) insert into forum (id, name) values (20, 'testb');
>>
>> Ik weet dus niet van te voren in welke volgorde ze dit doen. Ik kan
>> geen update gebruiken, omdat ik niet zeker weet of er al een rij
>> bestaat met id=20. Als ik geen maatregelen qua transacties/locking
>> oid neem, krijg ik de foutmelding dat er al een id bestaat met
>> waarde 20.
>>
>> Lijkt mij niet zo'n vreemde taak, dus je zou toch zeggen dat het wel
>> mogelijk is.

> Waarom draai je ze niet alle twee in een transactie? Een DELETE die
> geen rijen weggooit is geen reden voor een transactie om te mislukken.

Omdat de tweede transactie dan een id invoert wat al bestaat, en dat geeft
wel een foutmelding.

Math1985
28/03/07, 11:04
blacklistme@xs4all.nl wrote:
> robert wrote in nl.internet.www.server-side:
>> Math1985 <usenet2006@matthijsmelissen.nl>:
>>> Ik laat de volgende queries uitvoeren:
>>>
>>> 1) begin;
>>> 1) delete from forum where id = 20;
>>> 1) insert into forum (id, name) values (20, 'test');
>>> 2) delete from forum where id = 20;
>>> 1) commit;
>>>
>>> 1) geeft een query aan die uitgevoerd wordt door proces 1 en 2) een
>>> query uitgevoerd door proces 2).
>>> Nu krijgt proces 2 de melding dat er 0 rijen worden verwijderd. Kan
>>> iemand dat verklaren? Ik zelf zou 1 rij verwachten.
>>
>> Pas na een commit zijn de resultaten van de insert zichtbaar voor
>> andere processen, zo werken transacties nou eenmaal (zie een
>> beschrijving van het ACID principe,
>> http://nl.wikipedia.org/wiki/ACID).
>
> Pgsql is ACID ja, maar werkt wel op basis van [1]MVCC en kan heel soms
> leuke effecten hebben. "SET TRANSACTION" nalezen cq aanpassen kan
> helpen in dit soort gevallen.

Ik heb alle 4 de opties geprobeerd, maar kon daarmee het probleem niet
oplossen.