\chapter{Transções e Controlo de Concorrência}

	O PostgreSQL utiliza um modelo de multiversão, o  \textit{Multiversion Concurrency Control} (MVCC) para assegurar a consistência dos dados e gestão de transações, isto pois suporta várias sessões de bases de dados em simultâneo e, como tal necessita de garantir isolamento entre transações entre as sessões, para isso, usando \textit{snapshots} da base de dados. Uma das vantagens de usar este método de controlo de concorrência é o facto de os \textit{locks} MVCC de \textit{read} não entrarem em conflito com os \textit{locks} de \textit{write} e portanto operações de leitura nunca bloqueiam operações de escrita e vice-versa. O PostgreSQL consegue assegurar estas propriedades mesmo usando o nível de isolamento mais restrito através do uso do nível \textit{Serializable Snapshot Isolation} (SSI).
	Por omissão, todos os comandos são executados como transações, mas também é permitido definir blocos de transações explicitamente, usando o comando \begin{lstlisting}BEGIN\end{lstlisting} para demarcar o inicio da transação e acabando com \begin{lstlisting}COMMIT\end{lstlisting}. Para um controlo mais específico, podem ser criados pontos de restauro através do comando \begin{lstlisting}SAVEPOINT\end{lstlisting} aos quais podemos voltar usando \begin{lstlisting}ROLLBACK TO\end{lstlisting}. O PostgreSQL não tem implementação para \textit{nested transactions}, mas é possível atingir o mesmo efeito fazendo uso dos pontos de restauro. O sitema também não impõe limites na duração das transações de longa duração, embora seja desencorajado o uso de transações muito longas.

Para todos os exemplos de transaçõess será usada a seguinte tabela: bank ( nome varchar(10) primary key, balance int), com os tuplos iniciais ('Bob', 100) e ('Alice', 200).

Exemplo de uma transação com uso de savepoints e rollback:
\begin{lstlisting}
BEGIN;
	UPDATE bank SET balance = balance – 100.00 where name = 'Bob';
	SAVEPOINT savepoint;
	UPDATE bank SET balance = balance + 100.00 where name = 'Alice';
	ROLLBACK TO savepoint;
COMMIT;
\end{lstlisting}

O resultado desta transação são os tuplos ('Bob', 0) e ('Alice', 200), o que era de esperar pois voltámos ao ponto em que o update ao segundo tuplo ainda não tinha sido executado.

\section{Locks e Resolução de Deadlocks}

	O PostgreSQL utiliza vários modos de \textit{lock} para o controlo de concorrência de acessos a tabelas, sendo que a maioria dos seus comandos adquirem os \textit{locks} adequados à situação automaticamente.
	O PostgreSQL possui uma variada lista de \textit{locks}  ao nível das tabelas, sendo que estes são adquiridos automaticamente, podendo, no entanto recorrer-se  ao comando \begin{lstlisting}LOCK\end{lstlisting} para adquirir algum dos locks explicitamente. Os locks são: \textit{access share, row share, row exclusive, share update exclusive, share, share row exclusive, exclusive e access exclusive}, estando estes ordenados do que tem menos conflitos com os outros \textit{locks} para o que tem mais, sendo  que o \textit{access exclusive} não permite acesso a mais nenhum outro \textit{lock}.
	Para além dos \textit{locks} ao nível das tabelas, o PostgreSQL também possui \textit{locks}  a nível dos tuplos, sendo que estes podem ser exclusivos ou partilhados. Os \textit{locks} exclusivos são adquiridos automaticamente quando se actualiza ou apaga um tuplo. Para adquirir os \textit{locks} explicitamente, pode-se também usar os comandos \begin{lstlisting}SELECT FOR UPDATE\end{lstlisting}, que adquire um \textit{lock}  exclusivo sem modificar o tuplo, e \begin{lstlisting}SELECT FOR SHARE\end{lstlisting}, que adquire um \texit{lock} partilhado.
	Ao adquirir \textit{locks} explicitamente aumenta-se o risco de causar um \textit{deadlock} entre as transações. O PostgreSQL detecta esses casos automaticamente e resolve-os abortando uma das transações para que a outra possa seguir a sua execução.

\begin{table}[H]
\begin{center}
\begin{tabular}{|c|c|}
\hline
\textbf{T1} & \textbf{T2} \\ \hline
\begin{lstlisting}begin;\end{lstlisting} && \\ \hline
 && \begin{lstlisting}begin;\end{lstlisting} \\ \hline
\begin{lstlisting}insert into bank (name, balance) values ('Carlos', 100);\end{lstlisting} && \\ \hline
 && \begin{lstlisting}insert into bank (name, balance) values ('Carla', 100);\end{lstlisting} \\ \hline;
\begin{lstlisting}insert into bank (name, balance) values ('Carla', 100);\end{lstlisting} && \\ \hline
 && \begin{lstlisting}insert into bank (name, balance) values ('Carlos' 100);\end{lstlisting} \\ \hline
 \begin{lstlisting}commit;\end{lstlisting} && \\ \hline
 && \begin{lstlisting}commit;\end{lstlisting} \\ \hline
\end{tabular}
\caption{\label{tab:cont_pgdata}Exemplo de utilização:}
\end{center}
\end{table}

Neste exemplo aconteceu que ambas as transações estavam a adquirir \textit{locks} automaticamente, pelo que quando cada uma tentou inserir o segundo tuplo ficou em espera, causando o \textit{deadlock}. O PostgreSQL abortou T2 para que T1 pudesse continuar a sua execução.

\section{Níveis de Isolamento}

\subsection{Read Committed}
	O PostgreSQL permite ao utilizador a escolha de entre os quatro níveis de isolamento definidos pelo standart do SQL, embora, internamente apenas implemente três desses níveis, sendo esses o \textit{Read Committed, Read Uncommitted e Serializable}.  	A razão pela qual o PostgreSQL apenas implementa estes três níveis é porque é a melhor maneira de fornecer os níveis de isolmento standart numa arquitectura de controlo de concorrência multiversão.
	O \textit{Read Committed} é o nível de isolmento definido por omissão dos PostgreSQL, sendo que, com o este nível uma tem visibilidade sobre todas as alterações de dados, desde que as transações que os alteraram tenham feito commit. Este é o nível mais baixo do isolamento, pois uma transação vê as alterações feitas, por outras transações, aos dados que manipula. Para  fornecer este nível de isolamento o sistema cria \textit{snapshots} antes de cada instrução ser executada. 

Exemplo de utilização:
Nestes exemplos usaremos o seguinte escalonamento de transações e iremos comparar o resultado conforme o nível de isolamento.

\begin{table}[H]
\begin{center}
\begin{tabular}{|c|c|}
\hline
\textbf{T1} & \textbf{T2} \\ \hline
\begin{lstlisting}begin;\end{lstlisting} && \\ \hline
 && \begin{lstlisting}begin;\end{lstlisting} \\ \hline
\begin{lstlisting}update bank set balance = balance+100 where name = 'Bob';\end{lstlisting} && \\ \hline
 && \begin{lstlisting}delete from bank where balance = 100;\end{lstlisting} \\ \hline;
 \begin{lstlisting}commit;\end{lstlisting} && \\ \hline
 && \begin{lstlisting}commit;\end{lstlisting} \\ \hline
\end{tabular}
\caption{\label{tab:cont_pgdata}}
\end{center}
\end{table}

\begin{lstlisting}
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
\end{lstlisting}

Neste caso, apesar de o nivel de isolamento da transaçao ser \textit{Read Commited}, como não foi executado o commit, T2 acabou por ficar suspensa até que T1 acabasse a sua execução.

\subsection{Repeatable Read}

	No caso do \textit{Repeatable Read}, que só tem visão sobre os dados que foram \textit{committed} antes da transação começar, não tendo visão sobre valores \textit{uncommitted} ou modificações feitas por transações concorrentes, o sistema cria apenas uma \textit{snapshot}, antes do início da transação. Assim tem-se uma melhor garantia de que a transação tem uma visão consistende da base de dados.

Exemplo de utilização:

\begin{lstlisting}
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
\end{lstlisting}

Também neste caso, T2 ficou suspensa quando ao tentar executar a operação de \textit{delete}.

\subsection{Serializable}

	Para o nível de isolamento \textit{Serializable}, que é o nível de isolamento mais rigoroso pois emula uma execução em série de transações concorrentes, o sistema usa os mesmos métodos do \textit{Repeatable Read}, com a excepção da monitorização de condições que possam tornar a execução de um conjunto de transações serializáveis concorrentes iconsistente em todas as possíveis serializações dessas transações. Uma estratégia que o PostgreSQL utiliza para garantir a serialização de transações é o uso do protocolo de \textit{predicate locking}, que mantém \textit{locks} que permitem ao sistema determinar quando uma qualquer operação de escrita de uma transação possa afectar o resultado de um \textit{read} prévio de uma transação concorrente, caso esta última se tenha iniciado primeiro. No PostgreSQL, a utilização  destes \textit{locks} não leva ao risco de \textit{deadlock}, pois estes não são bloqueantes, servindo apenas para assinalar e identificar dependências entre transações serializáveis concorrentes que, em certas combinações, podem levar a problemas de serialização.

Exemplo de utilização:

\begin{lstlisting}
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
\end{lstlisting}

Também neste caso, T2 ficou suspensa quando ao tentar executar a operação de \textit{delete}.

\section{Consistência de Dados}

	Em termos de consistências, dada a natureza do nível de isolamento \textit{Read Committed}, o PostgreSQL tem grandes dificuldades em garantir a consistência dos dados sem suporte adicional. Já com o nível de isolamento \textit{Repeatable Read}, o sistema tem um pequeno problema em manter a consistência caso não tenha cuidados extra. Esse problema deve-se ao facto de usar \textit{snapshots} do tipo MVCC e são chamados de conflitos \textit{read/write}.  Este caso acontece quando uma transação quando se forma um ciclo no grafo de precedências das transações.
Caso o  nível de isolamento utilizado para todos os \textit{reads}  e  \textit{writes} seja o \textit{Serializable}, então não é necessário esforço adicional para garantir a consistência dos dados.
	Quando se utilizam \textit{writes} não serializáveis, é necessário fazer uso dos \textit{locks} para assegurar a consistência dos dados. O uso de \textit{locks} é mais aconselhado para os níveis de isolamento \textit{Repeatable Read} e \textit{Read Commited}, sendo que o Postgres os adquire automaticamente quando usa estes níveis de isolamento.
	Como existem níveis de isolamento que podem não garantir a consistência dos dados, o PostgreSQL oferece ao utilizador um método de verificação de integridade da base de dados, que pode ser configurado para correr no fim de cada transacção (\begin{lstlisting}DEFERRED\end{lstlisting}) ou entre as instruções da transacção (\begin{lstlisting}IMMEDIATE\end{lstlisting}).
	
Exemplo de utilização:

\begin{lstlisting}
SET CONSTRAINTS CONSTRAINT_NAME DEFFERED;
\end{lstlisting}

\section{Recuperação de Dados}

	Como mecanismo de recuperação, o PostgreSQL mantém \textit{logs} do tipp WAL (\textit{Write Ahead Log}), guardados na subdirectoria  \textit{pg_xlog}. Estes \textit{logs} registam qualquer tipo de alteração nos dados da base de dados servido, primariamente, para recuperação de crashes.
	O uso deste mecanismo permite garantir a durabilidade de uma transação, sem precisar de que toda a operação tenha escrito em disco, escrevendo primeiro no \textit{log} e, depois, permanecendo em disco quando se der a operação de escrita de \textit{logs} em disco. Por outro lado, este mecanismo permite simplificar o caso em que uma transação é abortada pois o sistema não tem alterar os ficheiros em disco para fazer \textit{rollback} bastando, para isso, alterar o \textit{log} em que foi escrito o resultado da transação.
	O facto de o PostgreSQL utilizar o MVCC já dá algum suporte a este mecanismo de recuperação.

\section{Comparação com o Oracle}

Comparando ambos os sistemas concluímos que no aspecto de controlo de concorrência são muito parecidos, havendo algumas pequenas diferenças como por exemplo um maior número de \textit{lock modes} que o PostgreSQL possui.

