Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Optimisticko zakljucavanje

[es] :: Java :: Optimisticko zakljucavanje

[ Pregleda: 1503 | Odgovora: 2 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

bojan_mch
Student

Član broj: 228358
Poruke: 1
*.teol.net.



Profil

icon Optimisticko zakljucavanje18.07.2009. u 21:39 - pre 179 meseci
Zdravo!

Imam jedan problem u realizaciji ovog principa!!
Napravio sam servlet koji klijentima omogucava da vrse update u bazu podataka!Izvrsio sam optimisticko zakljucavanje
tako sto sam dodao kolonu verzija u tabelu cija vrednost se prilikom svakog upisa inkrementira! Princip je takav da se prilikom pristupa
update stranici, ocitava trenutna verzija odgovarajuceg reda iz tabele, i jos jednom prilikom updatea se vrsi provera verzije...
pa ako je broj verzije isti, vrsi se update jer niko u medjuvremenu nije promenio nista u tabelli...
al PITANJE: sta ako klijenti u istoj milisekundi pritisnu dugme za update...kako to da se spreci??
jer ce obe transakcije, oba puta da procitaju isti broj verzije, i obe ce uraditi update, pa je baza nekonzistentna!!

SInhornizacioni blok ne moze, jer ce se program koristiti na visestrukim JVM (takve su instrukcije)
 
Odgovor na temu

bantu

Član broj: 38670
Poruke: 305
89.111.240.*



+27 Profil

icon Re: Optimisticko zakljucavanje20.07.2009. u 07:21 - pre 179 meseci
Realizuj to na nivou baze, najjednostvnije i najefikasnije. U jednoj transakciji čitaj verziju i izvrši insert i onda inkrementuj verziju. Bazin mehanizam će ti obezbjediti atomičnost transakcije, tako da ti u svojoj aplikaciji nećeš morati da vodiš računa o tome.
 
Odgovor na temu

Dejan Lozanovic
Dejan Lozanovic
Beograd

Član broj: 691
Poruke: 2325
91.148.86.*

Jabber: null@elitesecurity.org
Sajt: speedy-order.com


+75 Profil

icon Re: Optimisticko zakljucavanje21.07.2009. u 16:50 - pre 179 meseci
Ako koristis neku JPA implementaciju postoji @Version anotacija koja radi bas to, optimisticko lokovanje, i uglavnom ako se desi da je neko izmenio rekord dobices RunTimeExeption, uglavnom sam SQL izgleda tipa

Code:

update ..... , version= version +1  where id = 42 and version = 3


Mozda ti ovaj deo pomogne :)

Citat:

16.3.5. Optimistic Locking

The isReserved query we used earlier in combination with the Serializable isolation level allowed the bookPassage( ) method to prevent double bookings. With this query in place, there will be far fewer angry customers. This solution for double bookings has a serious performance drawback, though. In order for the isReserved query to work, no other reservation referencing the cabin the customer is trying to book, or the query may be invalid. In most databases, an exclusive lock would need to be obtained on the entire RESERVATION table to make this work. This means that any bookPassage( ) or listAvailableCabin( ) invocations could happen only one at a time. This is a huge scalability problem. As Titan's business grows and adds more ships, cruises, and customers, our system will not be able to handle the new processing load, no matter how many machines we buy or CPUs we upgrade. This is because there will be a high contention on a shared resource (i.e., on the RESERVATION table).

So, how can we solve this concurrency problem? One solution is to use the optimistic locking design pattern. Optimistic locking isn't locking in the traditional sense. The way it works is that in our bookPassage( ) method, we assume that no other customer is trying to book the same cabin at the same time. Then, at transaction commit time, we let the database resolve whether the cabin has been reserved. If it has been reserved, we throw an exception and roll back the transaction. In other words, we are being optimistic that no other customer is reserving the same cabin. How does this work? How does this avoid table-level locks? Well, to use optimistic locking we have to redesign our Titan reservation system a little and use a special feature of Java Persistence.

The first thing we need to do is create a new entity class that holds information about a particular cabin for a particular cruise. Let's call this new entity class CruiseCabin. A CruiseCabin entity class will be created for each cabin for each cruise:

Code:

package com.titan.domain;

import javax.persistence.*;

@Entity
public class CruiseCabin {
   private int id;
   private Cabin cabin;
   private Cruise cruise;
   private boolean isReserved;
   private long version;

   @Id @GeneratedValue
   public int getId( ) {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }

   @OneToOne
   public Cabin getCabin( ) {
      return cabin;
   }
   public void setCabin(Cabin cabin) {
      this.cabin = cabin;
   }

   @OneToOne
   public Cruise getCruise( ) {
      return cruise;
   }

   public void setCruise(Cruise cruise) {
      this.cruise = cruise;
   }

   public boolean getIsReserved( ) {
      return isReserved;
   }
   public void setIsReserved(boolean is) {
     isReserved = is;
   }

@Version 

   protected long getVersion( ) {
      return version; 

   }
   protected void setVersion(long version) {
      this.version = version;
   }
}


The CruiseCabin entity class references the cabin and cruise to which it belongs. The isReserved property lets us know whether somebody has reserved the cabin for that cruise. The new and interesting property is the version property, which is annotated with @javax.persistence.Version . An @Version property is a column in the CruiseCabin table that will hold a version ID of a particular CruiseCabin row. Whenever the CruiseCabin entity class is updated, the version column is incremented. When a transaction beginning the commit process and business logic has updated the CruiseCabin, the entity manager first checks to see if the version property of the in-memory CruiseCabin instance matches the version column currently stored in the database. If the versions match, then the version property is incremented. If they don't match, then the entity manager throws an exception and the whole transaction rolls back. Let's change bookPassage( ) to use this new feature:

Code:

public TicketDO bookPassage(CreditCardDO card, double price)
    throws IncompleteConversationalState {

    if (customer == null || cruise == null || cabin == null) {
        throw new IncompleteConversationalState( );
    }
    try {
     Query getCruiseCabin = entityManager.createQuery(
           "SELECT cc FROM CruiseCabin cc WHERE" +
           "cc.cabin = :cabin AND cc.cruise = :cruise");
        getCruiseCabin.setParameter("cabin", cabin);
        getCruiseCabin.setParameter("cruise", cruise);
        CruiseCabin cc = (CruiseCabin)getCruiseCabin.getSingleResult( );

        if (cc.getIsReserved( )) 
        throw new EJBException("Cabin is already reserved for cruise");
        cc.setIsReserved(true);
 
        Reservation reservation = new Reservation(
            customer, cruise, cabin, price);
        entityManager.persist(reservation);

        this.process.byCredit(customer, card, price);

        TicketDO ticket = new TicketDO(customer,cruise,cabin,price);

        return ticket;
    } catch(Exception e) {
        throw new EJBException(e);
    }
}


The bookPassage( ) method conducts a query for the relevant CruiseCabin entity class. If it is reserved, it aborts the transaction. If not, then it sets the isReserved property and continues with the rest of the method. At transaction commit time, the entity manager invokes an SQL query that both verifies and increments the version column of the entity. Let's assume that the queried CruiseCabin has an ID of 1 and the current version is 101:

update CRUISE_CABIN set isReserved=true, version=version + 1
where id = 1 AND version = 101;


If this update returns zero modified rows, then the entity manager knows that the CruiseCabin has been updated by another transaction and a concurrency error has occurred. In this error condition, it throws the javax.persistence.OptimisticLock-Exception and rolls back the transaction. Otherwise, the transaction completes successfully, and the queried CruiseCabin is updated as reserved and its version property is incremented. This optimistic locking solution creates a quick write-lock on one row in our database instead of the vastly unscalable table lock in the Serializable solution that was presented earlier in this chapter.

It should be noted that the optimistic locking design pattern does not work all the time. If you have a row in your database that has a high concurrent write contention, then it is probably less efficient to use the optimistic locking pattern because it will create a lot of rollbacks, which create a lot of overhead in your system. In that scenario, the Serializable solution is possibly more scalable. A redesign of your data model is probably more appropriate in this situation, however. If you have high concurrent access to one particular row in your database, then your system probably won't scale much anyway.


 
Odgovor na temu

[es] :: Java :: Optimisticko zakljucavanje

[ Pregleda: 1503 | Odgovora: 2 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.