Vous êtes sur la page 1sur 37

Transaes e concorrncia

Jobson Ronan {jrjs@cin.ufpe.br}

O que uma transao?

Uma transao uma unidade de trabalho que no pode ser dividida. uma operao atmica. H dois nveis de granularidade em aplicaes corporativas

A maior parte da complexidade de se lidar com transaes ocultada pelo sistema (Hibernate, servidor de aplicaes, banco de dados)

Transaes de banco de dados Transaes longas (de aplicao): envolvem vrias transaes de banco de dados

O trabalho consiste, geralmente, em demarcar o incio e fim das transaes

Uma transao ou termina com sucesso (commit) ou desfaz todo o processo (rollback)

Transaes em servidores

Demarcar transaes em uma aplicao JDBC fcil. Basta configurar a Conexo conn com da seguinte forma

conn.setAutoCommit(false);

Os statements executados sero acumulados e s sero tornados definitivos no banco aps um conn.commit() Ou sero desfeitos caso ocorra um conn.rollback() Em servidores de aplicao, ou quando preciso realizar transaes entre vrios bancos, preciso usar o protocolo Two-phase commit, que gerencia o processo

Para isto existe a API JTA e a classe UserTransaction que encapsula transaes distribudas

Tratamento de transaes em Hibernate


Session session = sessions.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); concludeAuction(); tx.commit(); Executado } catch (Exception e) { if (tx != null) { try { tx.rollback(); } catch (HibernateException he) { //log he and rethrow e } } throw e; } finally { try { session.close(); } catch (HibernateException he) { throw he; } }

dentro da transao

Transaes no Hibernate

O Hibernate encapsula o sistema de transaes do banco (JDBC) ou servidor (ambiente gerenciado) usado A transao comea na Session com uma chamada para
session.beginTransaction() Em um ambiente no gerenciado, isto inicia uma transao JDBC na conexo. Em um ambiente gerenciado, inicia uma transao JTA ou une-se transao existente.

Commit e rollback. Em uma transao Transaction tx:


tx.commit() sincroniza o estado da sesso com o banco de dados. tx.rollback() ou desfaz imediatamente a transao ou marca a transao para rollback.

importante fechar a sesso em um bloco finally para garantir que a conexo JDBC ser liberada e retornada ao pool de conexes.

Flushing (descarregando)

O objeto Session implementa "transparent write behind

Mudanas ao modelo de domnio no so imediatamente persistidas no banco (para reduzir acesso ao banco) Gravao/sincronizao transparente dos dados no final da transao.

Flushing a sincronizao da camada de objetos com a camada de dados. Ocorre quando


Uma transao cometida s vezes, antes que uma query executada Quando a aplicao chama explicitamente session.flush()

Isolamento

Bancos de dados e sistemas transacionais tentam garantir isolamento entre transaes

Isolamento completo uma utopia. muito caro em termos de escalabilidade da aplicao.

Bancos de dados fornecem vrios graus de flexibilizao de isolamento

Variam de isolamento completo a isolamento praticamente inexistente (neste caso, cabe aplicao lidar com os conflitos)

Para a maior parte das aplicaes, isolamento incompleto de uma transao aceitvel

Problemas de isolamento

O padro ANSI SQL define os nveis de isolamento de transaes em termos de fenmenos que podem ou no serem permitidos. Os fenmenos so: Update perdido (lost update)

Duas transaes ambas atualizam um registro e a segunda transao aborta, fazendo com que as duas mudanas sejam perdidas. As transaes concorrentes no tm isolamento algum. Uma transao l mudanas feitas por transao que ainda no cometeu os dados. Essa mudana pode ser desfeita em um rollback.

Leitura suja (dirty read)

Problemas de isolamento

Leitura no-repetvel (unrepeatable read)


Uma transao l um registro duas vezes e obtm um estado diferente em cada leitura. Outra transao pode ter gravado dados e cometido mudanas entre as duas leituras Uma transao executa uma consulta duas vezes, e o segundo resultado inclui registros que no estavam na primeira consulta. Novos registros foram inseridos por outra transao entre as consultas.

Leitura fantasma (phantom read)

Nveis de isolamento JDBC


JTA usa esses mesmos nveis de isolamento Read uncommitted


Permite dirty reads mas no updates perdidos. Uma transao no pode gravar em um registro se outra transao no cometida j gravou dados nele. Este nvel de isolamento pode ser implementado com locks de gravao exclusiva.

Read committed

Permite unrepeatable reads mas no dirty reads. Transao de gravao no cometida impede que outras transaes acessem registro. Transaes de leitura no bloqueiam o sistema.

Nveis de isolamento JDBC

Repeatable read

No permite unrepeatable reads nem dirty reads. Podem ocorrer phantom reads. Transaes de leitura bloqueiam transaes de gravao (mas no outras transaes de leitura) e transaes de gravao bloqueiam todas as outras.

Serializable

Fornece o isolamento mais rigoroso. Emula execuo em srie de transaes (em vez de concorrentemente).

Qual nvel de isolamento?

A escolha do nvel de isolamento depende do cenrio onde a aplicao executa.

No existe uma regra que sirva para todas as situaes.

Qual um nvel razovel de isolamento para aplicaes tpicas?

Isolamento excessivo geralmente no aceitvel, devido ao alto custo quanto escalabilidade (crtica nas aplicaes tpicas do Hibernate), portanto o isolamento serializable no deve ser usado O isolamento read uncommitted perigoso, e no deve ser usado se houver opes melhores no banco Suporte a versioning (travas otimistas) e uso do cache de segundo nvel (por classe) do Hibernate j alcanam a maior parte dos benefcios de um isolamento do tipo repeatable read, usando read committed.

Portanto, read committed uma boa opo com o Hibernate.

Como mudar o nvel de isolamento default?

preciso definir uma propriedade no hibernate.properties ou hibernate.cfg.xml. Use:


hibernate.connection.isolation=numero

onde nmero 1, 2, 4 ou 8. Exemplo:


hibernate.connection.isolation = 4

O nmero refere-se a um dos quatro nveis:


1Read uncommitted isolation 2Read committed isolation 4Repeatable read isolation 8Serializable isolation Servidores de aplicao tm configurao prpria.

S possvel fazer esse controle em ambientes no gerenciados

Estratgias de isolamento locais

Nvel de isolamento global afeta todas as conexes

Read committed um bom isolamento default para aplicaes Hibernate

Mas pode ser desejvel utilizar travas mais rigorosas para transaes especficas Existem duas estratgias

Travas pessimistas (evita colises entre transaes bloqueando totalmente o acesso de outras transaes) Travas otimistas (onde o sistema flexibiliza o isolamento mas lida com eventuais colises)

Travas pessimistas

Uma trava pessimista adquirida quando dados so lidos e mantidos isolados de outras transaes at que a sua transao complete.

Em modo read-committed, o banco de dados nunca adquire travas pessimistas a no ser que sejam requisitadas explicitamente Permite a solicitao de uma trava pessimista em um objeto
Transaction tx = session.beginTransaction(); Category cat = (Category) session.get(Category.class, catId); cat.setName("New Name"); tx.commit();

Classe LockMode

Considere a seguinte transao Uma trava pessimista pode ser obtida da seguinte forma:
Transaction tx = session.beginTransaction(); Category cat = (Category) session.get(Category.class, catId, LockMode.UPGRADE); cat.setName("New Name"); tx.commit();

Controle de LockMode

Os modos suportados para LockMode so:


NONE - S vai ao banco se o objeto no estiver no cache. Default em load() e get() READ - Ignora cache e faz verificao de verso para assegurar-se que o objeto na memria o mesmo que est no banco. UPDGRADE - Ignora cache, faz verificao de verso (se aplicvel) e obtm trava pessimista (se suportada). UPDGRADE_NOWAIT - Mesmo que UPGRADE, mas desabilita a espera por liberao de travas, e provoca exceo de locking se a trava no puder ser obtida. WRITE - Obtida automaticamente quando Hibernate grava em um registro na transao atual

Controle de LockMode

Sincronizao de objeto desligado se registro no foi alterado por outra transao.


Item item = ... ; Bid bid = new Bid(); item.addBid(bid); ... Transaction tx = session.beginTransaction(); session.lock(item, LockMode.READ); tx.commit(); Caching considerada uma soluo melhor que travas pessimistas. Evite usar LockMode explcito a no ser que realmente seja necessrio.

Transaes longas (de aplicao)

Processos de negcio

Podem ser consideradas uma nica unidade de trabalho do ponto de vista de um usurio. Transao de baixa granularidade. Uma noo mais abrangente da unidade de trabalho. Dados so recuperados e mostrados na tela em uma primeira transao do banco O usurio tem uma oportunidade de visualizar e modificar os dados, fora de uma transao As modificaes so feitas persistentes em uma segunda transao de banco de dados

Exemplo de cenrio tpico


1) 2)

3)

Como lidar com as colises?

Trs estratgias

ltimo commit ganha - os dois updates funcionam, mas o segundo sobrescreve as alteraes do primeiro. Nenhuma mensagem de erro mostrada. Primeiro commit ganha - a primeira modificao feita persistente, e o usurio que envia a segunda recebe uma mensagem de erro. Optimistic locking. Mesclar updates conflitantes - A primeira modificao persistida, e a segunda pode ser aplicada seletivamente pelo usurio. importante que o usurio pelo menos saiba do erro Acontece por default.

A primeira opo problemtica para vrias aplicaes


Hibernate ajuda a implementar as outras duas estratgias usando controle de verses e travas otimistas.

Uso de managed versioning (controle de verso)

Depende de que um nmero seja incrementado sempre que um objeto modificado.


public class Comment { ... private int version; ... void setVersion(int version) {this.version = version;} int getVersion() {return version;} }

No arquivo de mapeamento, <version> vem logo depois de <id>


<class name="Comment" table="COMMENTS"> <id ... <version name="version" column="VERSION"/> ... </class>

O nmero de verso s um contador. No tem outra utilidade.

Uma alternativa usar um timestamp

Timestamp

Alternativa ao <version>. Exemplo:


public class Comment { ... private Date lastUpdated; void setLastUpdated(Date lastUpdated) { this.lastUpdated = lastUpdated; } public Date getLastUpdated() {return lastUpdated;} }

Mapeamento
<class name="Comment" table="COMMENTS"> <id ...../> <timestamp name="lastUpdated" column="LAST_UPDATED"/> ... </class>

Em tese, um timestamp menos seguro pois duas transaes concorrentes poderiam tentar load e update no mesmo milisegundo.

Travas otimistas

O Hibernate controla a inicializao e gerenciamento de <version> e <timestamp> automaticamente.

Esses recursos permitem o eficiente gerenciamento de colises que implementam a estratgia de trava otimista. StaleObjectStateException lanado em caso de inconsistncia
Enfoque pessimista assume que sero constantes os conflitos e o ideal bloquear completamente o acesso. No ultrapassa os limites de uma sesso Enfoque otimista assume que conflitos sero raros e quando eles acontecerem, possvel lidar com eles. Garante maior escalabilidade e suporta transaes longas.

Otimistas versus Pessimistas

Granularidade de uma Sesso

Session-per-request

Uma sesso tem a mesma granularidade de uma transao

Session-per-request-withdetached-objects

Objetos so modificados entre duas sesses Uma transao por sesso Objetos desligados

Session-per-applicationtransaction

Sesso longa Objetos mantm-se persistentes

Cache

O cache uma cpia local dos dados.

Fica entre sua aplicao e o banco de dados. A aplicao faz uma pesquisa por chave primria ou A camada de persistncia resolve uma associao usando estratgia lazy Escopo de transao - cada unidade de trabalho tem seu prprio cache; vale enquanto a transao est rodando. Escopo de processo - o cache compartilhado entre transaes (h implicaes quanto ao isolamento) Escopo de cluster - compartilhado entre processos na mesma mquina ou entre mltiplas mquinas de um cluster.

O cache evita acesso ao banco sempre que


Podem ser classificados quanto ao escopo:


Cache no Hibernate

Dois nveis

Primeiro nvel tem escopo de transao. Segundo nvel opcional e tem nvel de processo ou cluster. Uma session ou tem a durao de uma transao de banco de dados ou de uma transao de aplicao longa. No pode ser desligada. Garante identidade do objeto dentro da transao.

O segundo nvel cache de estado (valores; no instncias)


opcional Pode ser configurado por classe ou por associao.

O primeiro nvel a Session.

Primeiro e segundo cache

Cache de primeiro nvel


Automtico (Session) Usado sempre que se passa um objeto para save(), update(), saveOrUpdate() ou quando ele requisitado com load(), find(),
list(), iterate(), ou filter()

Garante que quando uma aplicao requisita o mesmo objeto persistente duas vezes numa sesso, ela recebe de volta a mesma instncia. Instncias persistentes so desmontadas ( como serializao, mas o algoritmo mais rpido). Requer conhecimento sobre os dados para uso eficiente (no automtico as classes so mapeadas ao cache uma por uma) Se dados so mais freqentemente atualizados que lidos, no habilite o cache de segundo nvel Requer configurao fina em gerente de cache para melhor performance

Cache de segundo nvel


Resumo: tags de mapeamento

<version>

Usado em implementao de transaes longas, para sinalizar que uma tabela/objeto est sendo alterada Usado para definir poltica de cache de segundo nvel

<cache>

Propriedades: transao e cache

hibernate.cache.provider_class=nome.da.Classe Usa um cache provider prprio em substituio ao nativo usado pelo Hibernate (implementao de org.hibernate.cache.CacheProvider) hibernate.transaction.factory_class=nome.da.Classe Para definir um gerente de transaes prprio, ou org.hibernate.transaction.<nome> para usar uma

implementao disponvel, onde <nome> pode ser


JBossTransactionManagerLookup WeblogicTransactionManagerLookup WebSphereTransactionManagerLookup OrionTransactionManagerLookup ResinTransactionManagerLookup JOTMTransactionManagerLookup JOnASTransactionManagerLookup ...

Propriedades para hibernate.properties ou hibernate.cfg.xml

Boas Prticas

Usar sempre o padro facade ...mas como englobar vrias operaes a a vrios DAOs em uma transao?

Classe utilitria simples


public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { Configuration cfg = new Configuration(); sessionFactory = cfg.configure().buildSessionFactory(); } catch (Throwable ex) { ex.printStackTrace(System.out); throw new ExceptionInInitializerError(ex); } } //... }

Classe utilitria simples


//.. private static Session session; public static Session getSession() { try { if (session == null || !session.isOpen()) { SessionFactory factory = getSessionFactory(); session = factory.openSession(); } return session; } catch (Exception e) { throw new RuntimeException(e); } } //...

Classe utilitria simples

Suporte transacional
//.. private static Transaction transaction;

public static void beginTransaction() { transaction = getSession().beginTransaction(); }


public static void commit() { if (transaction != null) transaction.commit(); } public static void rollback() { if (transaction != null) transaction.rollback(); } //...

Usando

Todo DAO, quando precisar de uma Sesso, ir obte-la atravs do getSession()

Para que vrios DAOs obtenham a mesma sesso, basta no fecha-la

A fachada pode gerencar a transao com os metodos begin, commit e rollback

Os DAOs no gerencia, mais as transaes

...Mas se a houver acesso concorrente

Classe utilitria com suporte a concorrencia


//.. private static final ThreadLocal<Session> localSession = new ThreadLocal<Session>();
public static Session getSession() { try { Session session = localSession.get(); if (session == null || !session.isOpen()) { SessionFactory factory = getSessionFactory(); session = factory.openSession(); localSession.set(session); } return session; } catch (Exception e) { throw new RuntimeException(e); } } //...

Classe utilitria com suporte a concorrencia


//.. private static final ThreadLocal<Transaction> localTx = new ThreadLocal<Transaction>();
public static void beginTransaction() { localTx.set(getSession().beginTransaction()); } public static void commit() { if (localTx.get() != null) localTx.get().commit(); } public static void rollback() { if (localTx.get() != null) localTx.get().rollback(); } //...

Exerccio

Criar o modelo de Objetos analisando o schema do banco legado


script.sql

Criar criar DAOs e fachada para a aplicao Criar methodos de negcio para

Realizar uma reserva Agendar uma reserva Cancelar uma reserva

Transaes e concorrncia
Jobson Ronan {jrjs@cin.ufpe.br}

Vous aimerez peut-être aussi