You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ignite.apache.org by John Wilson <sa...@gmail.com> on 2018/07/25 16:58:09 UTC

Dirty Reads and READ_COMMITTED

Hi,

Consider the following transaction where we read key 1 twice.

try (Transaction tx = Ignition.ignite().transactions().txStart(PESSIMISTIC,
READ_COMMITTED)) {
cache.get(1);
//...
cache.get(1);
tx.commit();
}

According to the documentation here,
https://apacheignite.readme.io/docs/transactions, data is read without a
lock and is never cached. If that is the case, then how do we avoid a dirty
read on the second cache.get(1)? Another uncommitted transaction may update
the key between the first and second reads.

In most RDMS, a READ_COMMITTED isolation level, acquires locks for both
read and writes. The read lock is released after a read while the write
lock is held until the transaction completes. So for the above example, I
expect a read lock on each cache.get(1).


Thanks,

Re: Dirty Reads and READ_COMMITTED

Posted by Anton Vinogradov <av...@apache.org>.
Hi all,

Let's initially agree we're discussing about PESSIMISTIC, since OPTIMISTIC
provides no warranty on read before it commited.

Also, we should have some reproducer to make sure we're discussing same
issue.

I guess it's possible to have dirty reads only in following case
- first transaction commiting now under writelocks (I hope we acquire them
(all) before firs write, and release (all) after last write)
- second transaction does not acquire readlocks and just reads what can

anyway, in case we have some issues here, it should be easy to write a
reproducer.
Or we already have tests covers isolation issues?

чт, 26 июл. 2018 г. в 1:58, Dmitriy Setrakyan <ds...@apache.org>:

> Let's suppose that some transaction is trying to update values A and B:
>
> *tx.start() *
>
>
>
>
> > *cache.put("A", 1);cache.put("B", 2); *
>
>
>
> *tx. commit();*
>
>
> If you use READ_COMMITTED isolation level, it is possible that you will
> read the new value of A and the old value of B. If you need to make sure
> that you read the new values for A and B, then you need to use
> REPEATABLE_READ transaction in PESSIMISTIC mode. Note, that you can also
> use OPTIMISTIC SERIALIZABLE transactions as well, but in this case if you
> run into a conflict, then the transaction will be rolled back.
>
> D.
>
> On Wed, Jul 25, 2018 at 11:19 PM, Valentin Kulichenko <
> valentin.kulichenko@gmail.com> wrote:
>
> > I believe Ignite updates values during the commit phase, so it's not
> > possible to get a dirty read even if you do not acquire distributed locks
> > on reads with READ_COMMITTED isolation. But I would let other community
> > members who are more knowledgeable in this topic to add there comments,
> as
> > it's possible that I'm missing something.
> >
> > As for documentation, looks like semantic of "lock" there always implies
> > that it is help until transaction is committed or rolled back. Probably
> it
> > makes sense to clarify this as well.
> >
> > And yes, please disregard the REPEATABLE_READ point. I misread you
> initial
> > message a little bit.
> >
> > -Val
> >
> > On Wed, Jul 25, 2018 at 11:25 AM John Wilson <sa...@gmail.com>
> > wrote:
> >
> > > And no. I'm not describing REPEATABLE_READ. I'm describing
> > > https://en.wikipedia.org/wiki/Isolation_(database_systems)#Dirty_reads
> > and
> > > how READ_COMMITTED isolation can avoid dirty reads.
> > >
> > > On Wed, Jul 25, 2018 at 11:20 AM, John Wilson <sami.hailu.15@gmail.com
> >
> > > wrote:
> > >
> > > > I agree with your description. But the documentation  https://
> > > > apacheignite.readme.io/docs/transactions is misleading in stating
> that
> > > no
> > > > read locks are acquired (says "READ_COMMITTED - Data is read without
> a
> > > lock
> > > > and is never cached in the transaction itself."). Which should be
> > wrong.
> > > > Read locks are acquired but they are released as soon as the read is
> > > > complete (and they are not held until the transaction commits or
> rolls
> > > > back).
> > > >
> > > > Thanks,
> > > >
> > > > On Wed, Jul 25, 2018 at 10:33 AM, Valentin Kulichenko <
> > > > valentin.kulichenko@gmail.com> wrote:
> > > >
> > > >> Hi John,
> > > >>
> > > >> Read committed isolation typically implies that lock on read is not
> > held
> > > >> throughout the transaction lifecycle, i.e. released right after read
> > is
> > > >> completed (in Ignite this just means that no lock is required at
> all).
> > > >> This
> > > >> semantic allows second read to get an updated value that was already
> > > >> committed by another transaction. See Wikipedia description for
> > example:
> > > >>
> > > https://en.wikipedia.org/wiki/Isolation_(database_systems)#
> > Read_committed
> > > >>
> > > >> What you're describing is REPEATABLE_READ isolation which guarantees
> > > that
> > > >> subsequent reads return the same value. In Ignite it's achieved by
> > > >> acquiring lock on read and releasing it only on commit/rollback.
> > > >>
> > > >> -Val
> > > >>
> > > >> On Wed, Jul 25, 2018 at 10:12 AM John Wilson <
> sami.hailu.15@gmail.com
> > >
> > > >> wrote:
> > > >>
> > > >> > Hi,
> > > >> >
> > > >> > Consider the following transaction where we read key 1 twice.
> > > >> >
> > > >> > try (Transaction tx = Ignition.ignite().transactions
> > > >> ().txStart(PESSIMISTIC,
> > > >> > READ_COMMITTED)) {
> > > >> > cache.get(1);
> > > >> > //...
> > > >> > cache.get(1);
> > > >> > tx.commit();
> > > >> > }
> > > >> >
> > > >> > According to the documentation here,
> > > >> > https://apacheignite.readme.io/docs/transactions, data is read
> > > without
> > > >> a
> > > >> > lock and is never cached. If that is the case, then how do we
> avoid
> > a
> > > >> dirty
> > > >> > read on the second cache.get(1)? Another uncommitted transaction
> may
> > > >> update
> > > >> > the key between the first and second reads.
> > > >> >
> > > >> > In most RDMS, a READ_COMMITTED isolation level, acquires locks for
> > > both
> > > >> > read and writes. The read lock is released after a read while the
> > > write
> > > >> > lock is held until the transaction completes. So for the above
> > > example,
> > > >> I
> > > >> > expect a read lock on each cache.get(1).
> > > >> >
> > > >> >
> > > >> > Thanks,
> > > >> >
> > > >>
> > > >
> > > >
> > >
> >
>

Re: Dirty Reads and READ_COMMITTED

Posted by Dmitriy Setrakyan <ds...@apache.org>.
Let's suppose that some transaction is trying to update values A and B:

*tx.start() *




> *cache.put("A", 1);cache.put("B", 2); *



*tx. commit();*


If you use READ_COMMITTED isolation level, it is possible that you will
read the new value of A and the old value of B. If you need to make sure
that you read the new values for A and B, then you need to use
REPEATABLE_READ transaction in PESSIMISTIC mode. Note, that you can also
use OPTIMISTIC SERIALIZABLE transactions as well, but in this case if you
run into a conflict, then the transaction will be rolled back.

D.

On Wed, Jul 25, 2018 at 11:19 PM, Valentin Kulichenko <
valentin.kulichenko@gmail.com> wrote:

> I believe Ignite updates values during the commit phase, so it's not
> possible to get a dirty read even if you do not acquire distributed locks
> on reads with READ_COMMITTED isolation. But I would let other community
> members who are more knowledgeable in this topic to add there comments, as
> it's possible that I'm missing something.
>
> As for documentation, looks like semantic of "lock" there always implies
> that it is help until transaction is committed or rolled back. Probably it
> makes sense to clarify this as well.
>
> And yes, please disregard the REPEATABLE_READ point. I misread you initial
> message a little bit.
>
> -Val
>
> On Wed, Jul 25, 2018 at 11:25 AM John Wilson <sa...@gmail.com>
> wrote:
>
> > And no. I'm not describing REPEATABLE_READ. I'm describing
> > https://en.wikipedia.org/wiki/Isolation_(database_systems)#Dirty_reads
> and
> > how READ_COMMITTED isolation can avoid dirty reads.
> >
> > On Wed, Jul 25, 2018 at 11:20 AM, John Wilson <sa...@gmail.com>
> > wrote:
> >
> > > I agree with your description. But the documentation  https://
> > > apacheignite.readme.io/docs/transactions is misleading in stating that
> > no
> > > read locks are acquired (says "READ_COMMITTED - Data is read without a
> > lock
> > > and is never cached in the transaction itself."). Which should be
> wrong.
> > > Read locks are acquired but they are released as soon as the read is
> > > complete (and they are not held until the transaction commits or rolls
> > > back).
> > >
> > > Thanks,
> > >
> > > On Wed, Jul 25, 2018 at 10:33 AM, Valentin Kulichenko <
> > > valentin.kulichenko@gmail.com> wrote:
> > >
> > >> Hi John,
> > >>
> > >> Read committed isolation typically implies that lock on read is not
> held
> > >> throughout the transaction lifecycle, i.e. released right after read
> is
> > >> completed (in Ignite this just means that no lock is required at all).
> > >> This
> > >> semantic allows second read to get an updated value that was already
> > >> committed by another transaction. See Wikipedia description for
> example:
> > >>
> > https://en.wikipedia.org/wiki/Isolation_(database_systems)#
> Read_committed
> > >>
> > >> What you're describing is REPEATABLE_READ isolation which guarantees
> > that
> > >> subsequent reads return the same value. In Ignite it's achieved by
> > >> acquiring lock on read and releasing it only on commit/rollback.
> > >>
> > >> -Val
> > >>
> > >> On Wed, Jul 25, 2018 at 10:12 AM John Wilson <sami.hailu.15@gmail.com
> >
> > >> wrote:
> > >>
> > >> > Hi,
> > >> >
> > >> > Consider the following transaction where we read key 1 twice.
> > >> >
> > >> > try (Transaction tx = Ignition.ignite().transactions
> > >> ().txStart(PESSIMISTIC,
> > >> > READ_COMMITTED)) {
> > >> > cache.get(1);
> > >> > //...
> > >> > cache.get(1);
> > >> > tx.commit();
> > >> > }
> > >> >
> > >> > According to the documentation here,
> > >> > https://apacheignite.readme.io/docs/transactions, data is read
> > without
> > >> a
> > >> > lock and is never cached. If that is the case, then how do we avoid
> a
> > >> dirty
> > >> > read on the second cache.get(1)? Another uncommitted transaction may
> > >> update
> > >> > the key between the first and second reads.
> > >> >
> > >> > In most RDMS, a READ_COMMITTED isolation level, acquires locks for
> > both
> > >> > read and writes. The read lock is released after a read while the
> > write
> > >> > lock is held until the transaction completes. So for the above
> > example,
> > >> I
> > >> > expect a read lock on each cache.get(1).
> > >> >
> > >> >
> > >> > Thanks,
> > >> >
> > >>
> > >
> > >
> >
>

Re: Dirty Reads and READ_COMMITTED

Posted by Valentin Kulichenko <va...@gmail.com>.
I believe Ignite updates values during the commit phase, so it's not
possible to get a dirty read even if you do not acquire distributed locks
on reads with READ_COMMITTED isolation. But I would let other community
members who are more knowledgeable in this topic to add there comments, as
it's possible that I'm missing something.

As for documentation, looks like semantic of "lock" there always implies
that it is help until transaction is committed or rolled back. Probably it
makes sense to clarify this as well.

And yes, please disregard the REPEATABLE_READ point. I misread you initial
message a little bit.

-Val

On Wed, Jul 25, 2018 at 11:25 AM John Wilson <sa...@gmail.com>
wrote:

> And no. I'm not describing REPEATABLE_READ. I'm describing
> https://en.wikipedia.org/wiki/Isolation_(database_systems)#Dirty_reads and
> how READ_COMMITTED isolation can avoid dirty reads.
>
> On Wed, Jul 25, 2018 at 11:20 AM, John Wilson <sa...@gmail.com>
> wrote:
>
> > I agree with your description. But the documentation  https://
> > apacheignite.readme.io/docs/transactions is misleading in stating that
> no
> > read locks are acquired (says "READ_COMMITTED - Data is read without a
> lock
> > and is never cached in the transaction itself."). Which should be wrong.
> > Read locks are acquired but they are released as soon as the read is
> > complete (and they are not held until the transaction commits or rolls
> > back).
> >
> > Thanks,
> >
> > On Wed, Jul 25, 2018 at 10:33 AM, Valentin Kulichenko <
> > valentin.kulichenko@gmail.com> wrote:
> >
> >> Hi John,
> >>
> >> Read committed isolation typically implies that lock on read is not held
> >> throughout the transaction lifecycle, i.e. released right after read is
> >> completed (in Ignite this just means that no lock is required at all).
> >> This
> >> semantic allows second read to get an updated value that was already
> >> committed by another transaction. See Wikipedia description for example:
> >>
> https://en.wikipedia.org/wiki/Isolation_(database_systems)#Read_committed
> >>
> >> What you're describing is REPEATABLE_READ isolation which guarantees
> that
> >> subsequent reads return the same value. In Ignite it's achieved by
> >> acquiring lock on read and releasing it only on commit/rollback.
> >>
> >> -Val
> >>
> >> On Wed, Jul 25, 2018 at 10:12 AM John Wilson <sa...@gmail.com>
> >> wrote:
> >>
> >> > Hi,
> >> >
> >> > Consider the following transaction where we read key 1 twice.
> >> >
> >> > try (Transaction tx = Ignition.ignite().transactions
> >> ().txStart(PESSIMISTIC,
> >> > READ_COMMITTED)) {
> >> > cache.get(1);
> >> > //...
> >> > cache.get(1);
> >> > tx.commit();
> >> > }
> >> >
> >> > According to the documentation here,
> >> > https://apacheignite.readme.io/docs/transactions, data is read
> without
> >> a
> >> > lock and is never cached. If that is the case, then how do we avoid a
> >> dirty
> >> > read on the second cache.get(1)? Another uncommitted transaction may
> >> update
> >> > the key between the first and second reads.
> >> >
> >> > In most RDMS, a READ_COMMITTED isolation level, acquires locks for
> both
> >> > read and writes. The read lock is released after a read while the
> write
> >> > lock is held until the transaction completes. So for the above
> example,
> >> I
> >> > expect a read lock on each cache.get(1).
> >> >
> >> >
> >> > Thanks,
> >> >
> >>
> >
> >
>

Re: Dirty Reads and READ_COMMITTED

Posted by John Wilson <sa...@gmail.com>.
And no. I'm not describing REPEATABLE_READ. I'm describing
https://en.wikipedia.org/wiki/Isolation_(database_systems)#Dirty_reads and
how READ_COMMITTED isolation can avoid dirty reads.

On Wed, Jul 25, 2018 at 11:20 AM, John Wilson <sa...@gmail.com>
wrote:

> I agree with your description. But the documentation  https://
> apacheignite.readme.io/docs/transactions is misleading in stating that no
> read locks are acquired (says "READ_COMMITTED - Data is read without a lock
> and is never cached in the transaction itself."). Which should be wrong.
> Read locks are acquired but they are released as soon as the read is
> complete (and they are not held until the transaction commits or rolls
> back).
>
> Thanks,
>
> On Wed, Jul 25, 2018 at 10:33 AM, Valentin Kulichenko <
> valentin.kulichenko@gmail.com> wrote:
>
>> Hi John,
>>
>> Read committed isolation typically implies that lock on read is not held
>> throughout the transaction lifecycle, i.e. released right after read is
>> completed (in Ignite this just means that no lock is required at all).
>> This
>> semantic allows second read to get an updated value that was already
>> committed by another transaction. See Wikipedia description for example:
>> https://en.wikipedia.org/wiki/Isolation_(database_systems)#Read_committed
>>
>> What you're describing is REPEATABLE_READ isolation which guarantees that
>> subsequent reads return the same value. In Ignite it's achieved by
>> acquiring lock on read and releasing it only on commit/rollback.
>>
>> -Val
>>
>> On Wed, Jul 25, 2018 at 10:12 AM John Wilson <sa...@gmail.com>
>> wrote:
>>
>> > Hi,
>> >
>> > Consider the following transaction where we read key 1 twice.
>> >
>> > try (Transaction tx = Ignition.ignite().transactions
>> ().txStart(PESSIMISTIC,
>> > READ_COMMITTED)) {
>> > cache.get(1);
>> > //...
>> > cache.get(1);
>> > tx.commit();
>> > }
>> >
>> > According to the documentation here,
>> > https://apacheignite.readme.io/docs/transactions, data is read without
>> a
>> > lock and is never cached. If that is the case, then how do we avoid a
>> dirty
>> > read on the second cache.get(1)? Another uncommitted transaction may
>> update
>> > the key between the first and second reads.
>> >
>> > In most RDMS, a READ_COMMITTED isolation level, acquires locks for both
>> > read and writes. The read lock is released after a read while the write
>> > lock is held until the transaction completes. So for the above example,
>> I
>> > expect a read lock on each cache.get(1).
>> >
>> >
>> > Thanks,
>> >
>>
>
>

Re: Dirty Reads and READ_COMMITTED

Posted by John Wilson <sa...@gmail.com>.
I agree with your description. But the documentation  https://apacheignite.
readme.io/docs/transactions is misleading in stating that no read locks are
acquired (says "READ_COMMITTED - Data is read without a lock and is never
cached in the transaction itself."). Which should be wrong. Read locks are
acquired but they are released as soon as the read is complete (and they
are not held until the transaction commits or rolls back).

Thanks,

On Wed, Jul 25, 2018 at 10:33 AM, Valentin Kulichenko <
valentin.kulichenko@gmail.com> wrote:

> Hi John,
>
> Read committed isolation typically implies that lock on read is not held
> throughout the transaction lifecycle, i.e. released right after read is
> completed (in Ignite this just means that no lock is required at all). This
> semantic allows second read to get an updated value that was already
> committed by another transaction. See Wikipedia description for example:
> https://en.wikipedia.org/wiki/Isolation_(database_systems)#Read_committed
>
> What you're describing is REPEATABLE_READ isolation which guarantees that
> subsequent reads return the same value. In Ignite it's achieved by
> acquiring lock on read and releasing it only on commit/rollback.
>
> -Val
>
> On Wed, Jul 25, 2018 at 10:12 AM John Wilson <sa...@gmail.com>
> wrote:
>
> > Hi,
> >
> > Consider the following transaction where we read key 1 twice.
> >
> > try (Transaction tx = Ignition.ignite().transactions().txStart(
> PESSIMISTIC,
> > READ_COMMITTED)) {
> > cache.get(1);
> > //...
> > cache.get(1);
> > tx.commit();
> > }
> >
> > According to the documentation here,
> > https://apacheignite.readme.io/docs/transactions, data is read without a
> > lock and is never cached. If that is the case, then how do we avoid a
> dirty
> > read on the second cache.get(1)? Another uncommitted transaction may
> update
> > the key between the first and second reads.
> >
> > In most RDMS, a READ_COMMITTED isolation level, acquires locks for both
> > read and writes. The read lock is released after a read while the write
> > lock is held until the transaction completes. So for the above example, I
> > expect a read lock on each cache.get(1).
> >
> >
> > Thanks,
> >
>

Re: Dirty Reads and READ_COMMITTED

Posted by Valentin Kulichenko <va...@gmail.com>.
Hi John,

Read committed isolation typically implies that lock on read is not held
throughout the transaction lifecycle, i.e. released right after read is
completed (in Ignite this just means that no lock is required at all). This
semantic allows second read to get an updated value that was already
committed by another transaction. See Wikipedia description for example:
https://en.wikipedia.org/wiki/Isolation_(database_systems)#Read_committed

What you're describing is REPEATABLE_READ isolation which guarantees that
subsequent reads return the same value. In Ignite it's achieved by
acquiring lock on read and releasing it only on commit/rollback.

-Val

On Wed, Jul 25, 2018 at 10:12 AM John Wilson <sa...@gmail.com>
wrote:

> Hi,
>
> Consider the following transaction where we read key 1 twice.
>
> try (Transaction tx = Ignition.ignite().transactions().txStart(PESSIMISTIC,
> READ_COMMITTED)) {
> cache.get(1);
> //...
> cache.get(1);
> tx.commit();
> }
>
> According to the documentation here,
> https://apacheignite.readme.io/docs/transactions, data is read without a
> lock and is never cached. If that is the case, then how do we avoid a dirty
> read on the second cache.get(1)? Another uncommitted transaction may update
> the key between the first and second reads.
>
> In most RDMS, a READ_COMMITTED isolation level, acquires locks for both
> read and writes. The read lock is released after a read while the write
> lock is held until the transaction completes. So for the above example, I
> expect a read lock on each cache.get(1).
>
>
> Thanks,
>