Ignite transactions dont work on multiple cache

classic Classic list List threaded Threaded
2 messages Options
a.dolmatov a.dolmatov
Reply | Threaded
Open this post in threaded view
|

Ignite transactions dont work on multiple cache

Hi!
We try to isolate read transaction from write transaction. So, we write to two transactional caches and commit transaction. From another thread we read from both caches (READ_COMMITED). Ignite isolate data change for every single cache, but not for both caches simultaneously.

In Oracle database, for example, transaction include all the tables, you can read committed data when they appeared in both tables.

I think its very important to show it in documentation.


@Test
public void test_transaction_1() {
Set<Integer> initial = new HashSet<>();
for (int i = 0; i < 10000; i++) {
initial.add(i);
}


CacheConfiguration<Integer, Set> config1
= new CacheConfiguration<>();
config1.setName("TRANSACTION_CACHE_1");
config1.setCacheMode(CacheMode.REPLICATED);
config1.setReadFromBackup(false);
config1.setOnheapCacheEnabled(true);
config1.setCopyOnRead(false);
config1.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);

CacheConfiguration<Integer, Set> config2
= new CacheConfiguration<>();
config2.setName("TRANSACTION_CACHE_2");
config2.setCacheMode(CacheMode.REPLICATED);
config2.setReadFromBackup(false);
config2.setOnheapCacheEnabled(true);
config2.setCopyOnRead(false);
config2.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);


IgniteCache<Integer, Set> cache1 = igniteClientGate.getOrCreateCache(config1);
IgniteCache<Integer, Set> cache2 = igniteClientGate.getOrCreateCache(config2);

cache1.put(1, initial);
cache2.put(1, initial);


CompletableFuture.runAsync(() -> {
AtomicInteger adder = new AtomicInteger(1);
while (true) {


Set<Integer> newSet = new HashSet<>();
initial.forEach(e -> newSet.add(e + adder.get()));


try (Transaction tx = igniteClientLoader.transactions().txStart(TransactionConcurrency.PESSIMISTIC, TransactionIsolation.REPEATABLE_READ)) {
cache1.put(1, newSet);
cache2.put(1, newSet);

tx.commit();
}

adder.incrementAndGet();
}

});

while (true) {

try (Transaction tx = igniteClientLoader.transactions().txStart(TransactionConcurrency.PESSIMISTIC, TransactionIsolation.READ_COMMITTED)) {

Set set1 = cache1.get(1);
Set set2 = cache2.get(1);

if (!set1.equals(set2)) {
System.out.println("not equals, transaction fails");
} else {
System.out.println("equals, transaction works");
}
assert set1.equals(set2);

}

}


}
ilya.kasnacheev ilya.kasnacheev
Reply | Threaded
Open this post in threaded view
|

Re: Ignite transactions dont work on multiple cache

Hello!

I have noticed that you have READ_COMMITTED isolation when reading. It will doubtlessly lead to situation when you read value from TXN-1 to set1 while TXN is in progress, and then will read value from TXN to set2 because it is committed already.

Don't you see it as a problem?

Regards,
--
Ilya Kasnacheev


чт, 24 окт. 2019 г. в 08:57, Andrey Dolmatov <[hidden email]>:
Hi!
We try to isolate read transaction from write transaction. So, we write to two transactional caches and commit transaction. From another thread we read from both caches (READ_COMMITED). Ignite isolate data change for every single cache, but not for both caches simultaneously.

In Oracle database, for example, transaction include all the tables, you can read committed data when they appeared in both tables.

I think its very important to show it in documentation.


@Test
public void test_transaction_1() {
Set<Integer> initial = new HashSet<>();
for (int i = 0; i < 10000; i++) {
initial.add(i);
}


CacheConfiguration<Integer, Set> config1
= new CacheConfiguration<>();
config1.setName("TRANSACTION_CACHE_1");
config1.setCacheMode(CacheMode.REPLICATED);
config1.setReadFromBackup(false);
config1.setOnheapCacheEnabled(true);
config1.setCopyOnRead(false);
config1.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);

CacheConfiguration<Integer, Set> config2
= new CacheConfiguration<>();
config2.setName("TRANSACTION_CACHE_2");
config2.setCacheMode(CacheMode.REPLICATED);
config2.setReadFromBackup(false);
config2.setOnheapCacheEnabled(true);
config2.setCopyOnRead(false);
config2.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);


IgniteCache<Integer, Set> cache1 = igniteClientGate.getOrCreateCache(config1);
IgniteCache<Integer, Set> cache2 = igniteClientGate.getOrCreateCache(config2);

cache1.put(1, initial);
cache2.put(1, initial);


CompletableFuture.runAsync(() -> {
AtomicInteger adder = new AtomicInteger(1);
while (true) {


Set<Integer> newSet = new HashSet<>();
initial.forEach(e -> newSet.add(e + adder.get()));


try (Transaction tx = igniteClientLoader.transactions().txStart(TransactionConcurrency.PESSIMISTIC, TransactionIsolation.REPEATABLE_READ)) {
cache1.put(1, newSet);
cache2.put(1, newSet);

tx.commit();
}

adder.incrementAndGet();
}

});

while (true) {

try (Transaction tx = igniteClientLoader.transactions().txStart(TransactionConcurrency.PESSIMISTIC, TransactionIsolation.READ_COMMITTED)) {

Set set1 = cache1.get(1);
Set set2 = cache2.get(1);

if (!set1.equals(set2)) {
System.out.println("not equals, transaction fails");
} else {
System.out.println("equals, transaction works");
}
assert set1.equals(set2);

}

}


}