Download Desarrollo de Bases de Datos Oscar Díaz

Document related concepts
no text concepts found
Transcript
Desarrollo de Bases de Datos
SQLJ
Motivación
Motivación
?Dos tipos de usuario:
? ocasionales:
? desarrolladores:
utilizan SQL interactivo
utilizan SQL embebido
para recuperar datos
para tratamiento de datos
Utilización de variables compartidas
Compatibilidad de tipos
Recuperación de datos
Tratamiento de excepciones
Contexto de ejecución
Contexto de conexión
Ejecución de una aplicación SQLJ
SQL embebido
?Estándar para la inclusión de instrucción SQL dentro de
un lenguaje de programación
?Se “extiende” el leng. prog. mediante la pre-compilación
?Requisitos del tratamiento de datos
? modificar/recuperar tuplas ? SQL
? capacidad de cálculo + instrucciones de control ? COBOL, C
?Por tanto, el tratamiento de datos requiere utilizar
SQL dentro de un lenguaje de programación
SQLJ
?Interfaz de alto nivel: consultas directamente en SQL
?Análisis sintáctico y semántico en tiempo de
(pre)compilación
?Interoperabilidad: estándar ANSI (diciembre, 1998)
?Toda instrucción SQL aparece precedida por una palabra
clave reconocida durante la pre-compilación
?Para el caso de JAVA
?estándar SQLJ
Pasos para la ejecución de una
aplicación .sqlj
Código fuente: Java + SQLJ
.....
Pre-compilador SQLJ
• comprobación de sintaxis
• comprobación de tipos
• comprobación de esquema
#sql [contexto conexión] {select ...};
>>sqlj mifichero.sqlj
Código fuente: Java + JDBC
Compilador Java
>>javac mifichero.java
Código byte: Java + llamadas al controlador JDBC
>>java mifichero.class
Controlador JDBC
Sistema
Base de Datos
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
Desarrollo de Bases de Datos
Utilización de variables compartidas
?Variables de Java que aparecen en sentencias SQL
void ejemplo() throws Exception {
String cuentaA = null;
String cuentaB = null;
Integer elSaldo = null;
DefaultContext contexto1 = new DefaultContext (
“jdbc:oracle:oci8:@midb”, “unusuario”, “secreto ”, false );
#sql [contexto1] {select saldo INTO :elSaldo
from cuentaCorriente where codigo = :cuentaA};
#sql [contexto1] {update cuentaCorriente
set saldo = saldo + :elSaldo where codigo = :cuentaB};
Compatibilidad de tipo SQL ? Java
#sql [ctx] {update Alumno set nota= :la_nota where dni = :el_dni}
? A la variable de SQL “nota” se le asigna la variable JAVA
“la_nota” ? sus tipos tienen que ser compatibles
Tipos Java
(escalares)
Tipos SQL
boolean
byte
short
int
long
float
double
BIT
TINYINT
SMALLINT
INTEGER
BIGINT
REAL
FLOAT, DOUBLE
cont.
Cont.
?OJO: Identificadores de SQL no son sensibles.
Identificadores de Java sí son sensibles
#sql [ctx] {update Alumno
set nota= :la_nota where dni = :el_dni}
instrucción
SQLJ
contexto en el que se
ejecuta la sentencia SQL
Las variables compartidas
precedidas por “ :”
#sql [ctx1] {select nombre into :el_nombre from Alumno
where dni = :el_dni}
El valor null
Los tipos de datos de Java NO soportan el valor null.
? SQLJ define para cada clase
escalar de Java, una clase
“wrapper” donde
? se soporta el valor “null”
? existe un método xxxValue que
permite la conversión al tipo
primitivo (p.ej intValue pasa a
int)
? otros métodos: toString(int),
valueOf(String), shortValue()
? Nótese que si el tipo es
wrapper empieza por
mayúscula
Tipos Java
(clases wrapper)
java.lang.Boolean
java.lang.Byte
java.lang.Short
java.lang.Integer
java.lang.Long
java.lang.Float
java.lang.Double
java.lang.String
java.math.BigDecimal
byte[ ]
java.sql.Date
java.sql.Time
java.sql.Timestamp
Tipos SQL
BIT
TINYINT
SMALLINT
INTEGER
BIGINT
REAL
FLOAT, DOUBLE
CHAR, VARCHAR,
LONGVARCHAR
NUMERIC, DECIMAL
BINARY, VARBINARY,
LONGBINARY
DATE
TIME
TIMESTAMP
Recuperación de datos
?Pasar null de Java a SQL
String elNombre = null;
Short laEdad = null;
#sql {insert into Alumno (dni, nombre, edad)
values (444, :elNombre, :laEdad)};
•Recuperar null de SQL en Java
Short elDni;
Short laEdad;
#sql {select edad into :laEdad
from Alumno where dni = :elDni}
short auxEdad = laEdad.shortValue(); error
?Si SELECT devuelve un solo valor.
?El resultado se guarda en una variable del lenguaje anfitrión
#sql {SELECT edad INTO :laEdad
FROM Alumno where dni = :elDni}
?Si SELECT devuelve un conjunto de valores.
?El resultado se guarda en un CURSOR
• Si una variable de tipo primitivo recibe null se
genera el error SQLNullException
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
Desarrollo de Bases de Datos
Cursores identificados por posición
? Un cursor es un objeto de la clase “iterator”
? El nº de columnas es igual al de la pregunta
? Se especifica el tipo de los atributos de la pregunta
#sql public iterator iteAlumno (Integer, String); // 1.- define el tipo “iteAlumno”
iteAlumno unCursor;
// 2.- se introduce variable de este tipo
Integer elDni;
String elNombre;
#sql unCursor = {select dni, nombre from Alumno}; // 3.- se abre el cursor
while (true) {
// 4.- se itera sobre el cursor
#sql {fetch :unCursor into :elDni, :elNombre};
if (un_cursor.endFetch()) break; // true si no hay más tuplas
System.out.println (elDni, elNombre); }
un_cursor.close();
// 4.- se cierra el cursor
Tratamiento de excepciones
?Excepción
? es un objeto de tipo SQLException
? se crea cuando se produce una excepción
? métodos: getMessage, getErrorCode, getSQLState
try{ #sql {select nombre into :elNombre from Alumno where dni = :elDni};}
catch( SQLNullException ne ){
Cursores identificados por el nombre
(recomendado)
? Un iterador especifica el nombre y tipo de los atributos de la pregunta
? Los valores de los atributos del registro se obtienen con métodos con
nombre el del atributo
#sql public iterator iteAlumno (Integer el_dni, String el_nombre);
iteAlumno unCursor;
// variable de tipo la clase anterior
Integer elDni;
String elNombre;
#sql unCursor = {select nombre as el_nombre,
dni as el_dni from Alumno}; // asignación cjto. tuplas
while (unCursor.next()) {
// avanza a la sgte. tupla. ( false, si no hay más)
elDni = unCursor.el_dni();
// obtiene el valor del atributo de la tupla
elNombre = unCursor.el_nombre();
System.out.println (elDni, elNombre);}
unCursor.close();
// liberación del recurso
Contexto de conexión
? Una instrucción SQL se ejecuta en un contexto de conexión
? #sql [contexto] { update Alumno set nota= :la_notawhere dni = :el_dni}
? Este contexto indica
? el SGBD,
? la base de datos
? usuario y password
? modo “autocommit”
con el que se ejecutará la instrucción SQL
System.out.println(“ Se ha encontrado un valor null: “ + ne. getErrorCode());}
catch( SQLException e ){
System.out.println(“ Error: ” + e.getMessage() + e.getErrorCode());}
Clase DefaultContext
? static DefaultContext DefaultContext(java.lang.String url,
java.lang.String user, java.lang.String password, boolean
autoCommit)
? Crea el contexto por defecto
? static DefaultContext getDefaultContext()
? Devuelve el contexto por defecto
? Este contexto se define como una instancia de la clase
sqlj.runtime.DefaultContext
Ejemplo
DefaultContext miEjemplo = new DefaultContext (
“jdbc:oracle:oci8:@midb”,
“unusuario”, “secreto”, false );
DefaultContext.setDefaultContext ( miEjemplo );
#sql [miEjemplo] {update ...}; //no sería necesario poner el contexto
? static void setDefaultContext(DefaultContext ctx)
? Establece el contexto por defecto
miEjemplo.close();
? public void close()
? Cierra el actual contexto
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
Desarrollo de Bases de Datos
Varios contextos de conexión simultáneos
? Necesidad de usar en la aplicación SGBDs distintos
? Necesidad de usar BD diferentes
? Necesidad de añadir más funcionalidades a la clase contexto de conexión
DefaultContext miEjemplo = new DefaultContext (
“ jdbc:oracle:oci8:@midb ”, “ unusuario ”, “ secreto ”, false );
DefaultContext otroEjemplo = new DefaultContext (
“ jdbc:oracle:oci8:@midb ”, “ otrousuario”, “ misecreto”, false );
DefaultContext.setDefaultContext ( miEjemplo );
#sql {select ...};
// utiliza el contexto por defecto
#sql [otroEjemplo] {update ...};
Contexto de ejecución
? Una instrucción SQL se ejecuta en un contexto de ejecución:
#sql [unCtxCon, unCtxEje] {update Alumno set nota = nota + 1 where curso = 5};
? Este contexto es una zona compartida por el runtime del SGBD y
el programa, para intercambiar información sobre
? MaxRows: máximo nº de tuplas que puede guardar un cursor
? MaxFieldSize: máximo nº de bytes de un atributo
? QueryTimeout: segundos de espera a una sentencia SQL
? UpdateCount: nº tuplas afectadas con última sentencia SQL
? SQLWarnings : texto error generado en la ejecución
? Estos atributos se guardan como una instancia de la clase
sqlj.runtime.ExecutionContext
miEjemplo.close(); otroEjemplo.close( );
Ejemplo
// Crea un contexto de ejecución donde guarda las incidencias
ExecutionContext unCtxEje = new ExecutionContext();
Tratamiento
fichero .sqlj
Código fuente: Java + SQLJ
.....
Pre-compilador SQLJ
• comprobación de sintaxis
• comprobación de tipos
• comprobación de esquema
#sql [contexto conexión] {select ...};
>>sqlj mifichero.sqlj
Código fuente: Java + JDBC
#sql [unCtxCon, unCtxEje] {delete from Alumno where curso = 5};
Compilador Java
System.out.println(“Se han borrado” + unCtxEje.getUpdateCount() + “ alumnos”);
>>javac mifichero.java
Código byte: Java + llamadas al controlador JDBC
>>java mifichero.class
// Espera 3 segundos a que se ejecute la sentencia SQL
unCtxEje.setQueryTimeout(3);
Controlador JDBC
#sql [unCtxCon, unCtxEje] {update Alumno set curso = 5};
Sistema
Base de Datos
Configuración de la pre-compilación
Conexión durante la pre-compilación
?Algunos parámetros de configuración
SQLJ
mifichero.java
Compilador
Java
miE
jem
plo
mifichero.sqlj
?Pueden indicarse
?explícitamente:
mifichero.class
plo
Ejem
otro
? dir : directorio de los ficheros .java generados
? user y password : nombre de usuario, y su clave, para conectarse a
la bd. (si no es null, el sistema realiza comprobación online)
? url: indica dónde establecer la conexión
? driver: controladores JDBC
? offline/online: comprobación sin/con conexión a la bd.
>> sqlj -user=unusuario -password=secreto mifichero.sqlj
?en el fichero sqlj.properties, consultado al invocar a sqlj
sqlj.user =unusuario
sqlj.password=secreto
Conexiones en la compilación
Conexiones en la ejecución
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
Desarrollo de Bases de Datos
public class top5 {
#sql static iterator top5It (String unAlumno, Integer notaMedia);
Ejercicio
void listarTop5() throws Exception {
top5It losTop5;
String elAlumno = null;
Integer laNotaMedia = null;
int contador = 0;
#sql losTop5 = { SELECT elAlumno AS unAlumno, avg(nota) AS notaMedia
FROM AluAsi
GROUP BY elAlumno
ORDER BY 2 DESC};
System.out.println("ALUMNO
" + "SU NOTA MEDIA");
while (losTop5.next() && contador < 5) {
elAlumno = losTop5.unAlumno();
laNotaMedia = losTop5.notaMedia();
System.out.println(elAlumno + " " + laNotaMedia);
contador = contador + 1;
}
losTop5.close();}
? La casa discográfica VIRGIN desea crear una base de datos
sobre las canciones, los autores y los cantantes que hacen
distintas versiones de dichas canciones. Un autor puede
componer distintas canciones y una canción puede tener
distintos compositores (tabla Aut_Can).
? Por otro lado, los cantantes pueden realizar distintas
versiones de una determinada canción. Las canciones están
agrupadas en álbumes (tabla Can_Can_Al). En un álbum una
misma canción puede ser cantada por distintos cantantes,
pero un cantante no puede tener diferentes versiones de la
misma canción en el mismo álbum. El diagrama E/R y las
tablas correspondientes son estas:
top5() {ConnectionManager.initContext();}}
Esquema
Esquema
Autor
Cantante
M
N
AUT_CAN
Fecha
CAN_CAN_AL
Duración
N
Canción
M
P
?AUTOR (NomAut, Tfno, Cuota)
?CANCION (Título, Estilo)
?CANTANTE (NomCan, Tfno, País)
?ALBUM (Código, DiscosPlatino)
?AUT_CAN (ElAutor, LaCanción)
?CAN_CAN_AL (LaCanción, ElCantante, ElAlbum,
Fecha, Duración)
Álbum
Ejercicio 1
Ejercicio 1
?Expresar en SQLJ un programa que cree un nuevo
album recopilatorio con las canciones 1º) de
cualquier estilo 2º) existan más de dos versiones de
las mismas, y 3º) cuyos autores hayan compuesto
alguna canción de estilo “Jazz”.
?Expresar en SQLJ un programa que cree el album
“XXX The BEST” que contenga para cada autor sus
5 canciones de más éxito, es decir, aquellas que
aparezcan en más álbumes.
?Conseguir todas las canciones
?Para cada canción
?Comprobar que si es de algún autor de Jazz
?Comprobar número de versiones
?Si se cumplen las dos anteriores
?Insertar en la BD (número de álbum y cantante fijos que
deberíamos saber)
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
Desarrollo de Bases de Datos
Ejercicio 1
Otras opciones del lenguaje
?Conseguir todas las canciones
?Borrar o modificar la tupla actual
?Select titulo from cancion
?Comprobar que si es de algún autor de Jazz
?Select 2
FROM AUT_CAN AS AC1 NJ Autor NJ AUT_CAN AS
AC2 NJ Canción
WHERE AC1.título=:título AND C2.Estilo=‘Jazz’
?(si devuelve tuplas es que sí tiene autor de Jazz)
#sql [ctx] {delete from tabla
WHERE CURRENT OF :variableIteradoranfitrión};
#sql [ctx] {update tabla set atributo = valor
WHERE CURRENT OF : variableIteradoranfitrión};
#sql iterator UnIterador(String, String);
UnIterador iter; …
#sql iter = { select nombre, dir from cliente where ciudad= ‘Donostia’};
while (true) {
?Comprobar número de versiones
#sql {fetch :iter into :nombre, :dir};
if (iter.endFetch()) break;
System.out.println (nombre+ " " + dir + " ¿Borrar (S/N)?");
entrada= new BufferedReader (new InputStreamReader (System.in));
?Select COUNT (Distinct Album) INTO :numversiones
from CAN-CAN-AL WHERE título=:titulo
?(si >2, entonces insertar en la BD)
tecla = entrada.readLine();
if (tecla.equals(“S"))
#sql {delete from cliente where current of :iter };
}
Procedimientos almacenados
Transacción
?Los definen los usuarios.
?Son objetos del esquema
?Se ejecutan en el SGBD
?La sintaxis de las llamadas depende del SGBD. Por
ejemplo, en Oracle
?Comienzo de la transacción:
?Al realizar una operación SQL sobre tuplas de la BD
?El control de concurrencia se basa en reservas
?A nivel de tupla
?Reserva de tupla: lo hace el sistema al escribir
?Para leer no se hace reserva
#sql [ctx] { CALL procedimiento(:arg1, :arg2) };
#sql [ctx] var= { VALUES funcion(:arg1, :arg2) };
?Liberar la reserva:
?Automáticamente
?Manualmente
AutoCommit
#sql {commit};
#sql {rollback};
AutoCommit
Autocommit
?Se puede definir cuando se crea el contexto de
conexión:
?También se puede cambiar a
través del contexto de conexión:
?Autocommit=false
DefaultContext ctx1= new DefaultContext (
“jdbc:oracle:oci8:@mibd”, “Jon”, “secreto”, false);
?Las transacciones se deben terminar manualmente
ctx.getConnection().setAutoCommit (true);
Tiene que ser la primera operación de la transacción
?Autocommit=true
DefaultContext ctx2= new DefaultContext (
“jdbc:oracle:oci8:@mibd”, “Nerea”, “asaber”, true);
?Las transacciones se terminan automáticamente en cuanto
terminan sus operaciones
?NO hay posibilidad de hacer ROLLBACK
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
Desarrollo de Bases de Datos
Recomendaciones para el diseño
de transacciones
Reducir el tráfico de red
#sql public iterator IteBDNotas(int nota);
IteBDNotas bdNotas;
...
#sql bdNotas = {select nota from Matricula where codAlum = 787};
#sql media = {select avg(nota) from Matricula where codAlum = 787};
while (bdNotas.next()) {
nota = bdNotas.nota();
...
if (nota > media) { System.out.println(... );}
}
#sql public iterator iteBDNotas (int nota);
iteBDNotas bdNotas;
...
// Solo se obtienen las notas que son superiores a la media
#sql bdNotas = {select nota from Matricula
where codAlum = 787 and nota > ( select avg(nota) from Matricula where codAlum = 787
)};
while (bdNotas.next()) {
nota = bdNotas.nota();
...
System.out.println(... );
}
Reducir el tráfico de red.
Row Prefetching
?El estándar JDBC trae las tuplas del resultado de una
consulta de una en una
?Para cada tupla hace falta un acceso a la BD
?Con la opción DefaultRowPrefetch las tuplas traidas se
pueden agrupar
?Se ahorran accesos a la BD
?El valor por defecto es 10 (Oracle)
?Se debe indicar el valor a cada instancia del contexto de
conexión
Reducir el tráfico de red
Update batching
?Las operaciones UPDATE, DELETE, INSERT se
pueden agrupar (en un proceso batch) para que la
ejecución sea más rápida (ahorrando accesos a la
BD)
?Las instrucciones en modo batch deben ser del mismo
tipo
?Esta característica se aplica a cada contexto de
ejecución
Reducir el tráfico de red
Row prefetching
?Cambiar el valor por defecto a 20 tuplas en un
contexto concreto (ctx)
((OracleConnection)ctx.getConnection()).getDefaultRowPrefetch()
((OracleConnection)ctx.getConnection()).setDefaultRowPrefetch(20)
?Cambiarlo en el contexto por defecto
((OracleConnection)DefaultContext.getDefaultContext().getConnection()).get
DefaultRowPrefetch()
((OracleConnection)DefaultContext.getDefaultContext().getConnection()).set
DefaultRowPrefetch(20)
Reducir el tráfico de red
Update batching
ExecutionContext ctxEje = new ExecutionContext();
ctxEje.setBatching(true);
ctxEje.setBatchLimit(limite);
for (int j=1; i<=limite; i++) {
// meter las instrucciones en un “lote”
#sql [ctxEje ] { INSERT INTO Tabla VALUES(:i) };
}
//Ejecución explícita de todas las inserciones a la vez
int[ ] kop = ctxEje.executeBatch();
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
Desarrollo de Bases de Datos
Reducir el tráfico de red
Update batching
Reducir el tráfico de red
Update batching
?las instrucciones de un lote se ejecutan de manera
implícita:
ctxEje.setBatching(true);
?Antes de ejecutar una instrucción de otro tipo
?Cuando se ejecuta commit
?Cuando se llega al límite de instrucciones batch
?Otras instrucciones
ExecutionContext ctxEje = new ExecutionContext ();
ctxEje.setBatchLimit( 3);
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where dni=1};
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where dni=2};
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where dni=3};
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where dni=4};
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where dni=5};
?ctxEje.isBatching()
?ctxEje.getBatchLimit()
?ctxEje.getBatchUpdateCounts()
?ctxEje.cancel()
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where categoria=10};
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where categoria=20};
#sql [ctxEje] {commit};
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where categoria=20};
ctxEje.executeBatch
¿Cuántos lotes hay y cuándo se ejecutan?
Reducir el tráfico de red
Update batching
ExecutionContext ctxEje = new ExecutionContext ();
ctxEje.setBatching(true);
ctxEje.setBatchLimit( 3);
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where na=1};
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where na=2};
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where na=3}; // llegado al límite
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where na=4};
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where na=5};
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where categoria=10}; // límite =3
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where categoria=20};
#sql [ctxEje] {commit}; // se ha llegado ha terminado la transacción
#sql [ctxEje] {update Empleado set sueldo=sueldo+100 where categoria=20};
Niveles de aislamiento en transac.
?Priorizar transacciones
?Es posible hacer operaciones de lectura y escritura
?Cuando se compromete una transacción se liberan las
reservas (protocolo estricto de dos fases)
?Garantizar la serialización empeora el nivel de
concurrencia ? Para mejorar la concurrencia se
propone relajar las reglas definiendo niveles de
aislamiento
?Se pueden ejecutar concurrentemente las transacciones
que tienen distintos niveles de aislamiento
ctxEje.executeBatch(); // petición de ejecución explícita
Niveles de aislamiento en transac.
?Para definir las características de la transacción se
debe utilizar como primera instrucción:
set transaction
[read only | read write]
[isolation level [read uncommitted | read committed |
| repeatable read | serializable]]
[diagnostics size <valor>]
Read uncommited
?Solo operaciones de lectura
?Recomendable solo para transacciones que tienen
funciones estadísticas
?Las transacciones (Tj) pueden leer datos sin
comprometer
?Puede aparecer el problema de la lectura sucia (dirty
read)
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
Desarrollo de Bases de Datos
Read commited
Read uncommitted (dirty read)
Transacción T1
Transacción T2
...
#sql {update cuenta
#sql iterator MiIter(int numcta);
#sql {set transaction
set saldo= saldo- :cant
where numcta= :ctax};
Transacción T2
...
#sql {update cuenta
isolation level read uncommitted};
MiIter iter;
?
#sql iter = { select numcta from cuenta
where saldo<0};
while (iter.next( )) {
set saldo = saldo+ :cant
where numcta= :ctay };
?La transacción (Tj) no puede leer ni escribir un dato
modificado por otra transacción (Ti) hasta que éste
se comprometa
?Evita la lectura sucia (dirty read)
?La transacción Tk puede leer o modificar un dato
leido antes por Tj antes de comprometerlo
?Puede ocurrir el problema de la lectura irrepetible
(unrepeatable read)
ctax = iter.numcta( );
mandar_carta(ctax);}
#sql {commit};
...
if (...) # sql {rollback};
Read committed
(unrepeatable read)
Repeatable read
?Se aplica el protocolo de reserva de dos fases con
todo
?Se evita la lectura sucia (dirty read)
?Se evita la lectura irrepetible (unrepeatable read)
?Puede aparecer el problema de la modificación fantasma
cuando hay transacciones que introducen nuevas tuplas. El
predicado no se tiene en cuenta
Transacción T1
#sql iterator MiIter(int dni);
#sql {set transaction
isolation level read committed};
MiIter iter;
#sql iter = { select dni from cuenta
where saldo> 10.000.000};
...
a = iter.dni( );
Transacción T2
...
#sql iter = { select dni from cuenta
where saldo> 10.000.000};
...
Transacción T2
?
#sql {update cuenta
set saldo= saldo - :cant
where numcta= A2345};
#sql {commit};
Repeatable read (ghost update)
Transacción T1
#sql iterator MiIter(int dni);
#sql {set transaction
isolation level repeatable read};
MiIter iter;
#sql iter = { select dni from cuenta
where saldo> 10.000.000};
...
a = iter.dni( );
Transacción T2
...
#sql iter = { select dni from cuenta
where saldo> 10.000.000};
...
Transacción T2
#sql {insert into cuenta values
(A2565, 37,12.000.000, ‘98-4-20’, 2, ‘Matia’)};
#sql {commit};
Serializable
?Se evita la lectura sucia
?Se evita la lectura irrepetible
?Se evita la modificación fantasma
?En el grafo de prioridad, también se almacena
información acerca de los predicados utilizados
?En oracle se usan rollback segments y marcas de tiempo
?Consistencia a nivel de transacción: los datos
utilizados a lo largo de la transacción, son los
comprometidos al comienzo de la misma.
?
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
Desarrollo de Bases de Datos
Serializable
Niveles de aislamiento. Resumen
Reserva de
exclusi ón larga
sobre las tuplas
Transacción T1
update cuenta set saldo= saldo * 2 where numcta= 2
Transacción T2
set transaction isolation level serializable
update cuenta set saldo = saldo + 20 where numcta= 1
Reserva
compartida larga
sobre las tuplas
Reservas de exc.,
compart. y sobre
predicados largas
Read uncommited
NO
NO
Read commited
SI
NO
NO
select * from cuenta
Repeatable read
SI
SI
NO
commit
Serializable
SI
SI
NO
insert into cuenta values (4, …)
update cuenta set saldo = saldo + 30 where numcta = 3
select * from cuenta
update cuenta set saldo = saldo + 30 where numcta = 2
Reserva larga = al comprometerse la transacción se libera la reserva (vs se
libera la reserva nada m ás terminar de usar el dato)
Error de pérdida de la serialización:
ORA-08177
No todos los SGBD ofrecen todos los niveles de aislamiento
Oracle: Read committed, Serializable
DB2: Read uncommited, Read commited, repeatable
read & serializable
Reservas explícitas
LOCK TABLE
Reservas explícitas
SELECT…FOR UPDATE
? Sintaxis:
?Sintaxis:
LOCK TABLE Tabla/Vista IN modo -reserva MODE [NOWAIT]
?Reserva explícita de una tabla completa
?Sin NOWAIT la transacción se queda en espera
hasta lograr la reserva
SELECT … FOR UPDATE [OF tabla] [NOWAIT]
? Nivel de consistencia de transacciones
? Las tuplas encontradas se reservan una a una, pero todas a la vez y
en modo exclusivo
? Si una tupla ya está reservada
? Con NOWAIT ? Se envía un mensaje de error al momento
? Sin NOWAIT? La transacción se queda en espera hasta que se libera la reserva
? Si es en un iterador al llenarlo se reservan las tuplas (y no cuando se hace
next)
Clave
Otras reservas
compatibles
Consistencia nivel de
transacción
ROW SHARE
IS
IS, IX, S, SIX
?
ROW EXCLUSIVE
IX
IS, IX
?
SHARE
S
IS, S
?
SIX
IS
?
X
--
?
Modos de reserva
SHARE ROW EXCLUSIVE
EXCLUSIVE
SELECT ... FOR UPDATE.
Ejemplo
#sql libres = {select asientos from espectaculo where cod = 34
System.out.println (libres + “ asientos disponibles. “+
”¿Cuántas entradas quiere?”);
cant = entrada.readLine( );
if (cant<= libres)
#sql {update espectáculo
set asientos = asientos - :cant
where cod = 34};
else { … }
#sql {commit};
select nombre, saldo
from cuenta natural join cliente
where ciudad= ‘Durango’
for update of Cuenta
for update
}
? Para liberar la reserva, se espera al commit o al rollback
de trabajar con el iterador)
(y no cuando se acaba
? No se pueden utilizar: funciones agregadas, la cláusula group by, ni
distinct
? Se pueden reservar varias tablas de una consulta con Join
Definición y verificación de
restricciones
CONSTRAINT nombre-restricción
...
[NOT] DEFERRABLE [INITIALLY [DEFERRED | IMMEDIATE] ]
? Not Deferrable (No diferible)
? La comprobación de la restricción se realiza cada vez que se ejecuta una
sentencia SQL en la transacci ón.
? Deferrable (Diferible)
? La comprobación de la restricción se puede diferir hasta el punto en el
que se compromete la transacción
? initially deferred, initially immediate:
? Se indica cuándo se realizará la comprobación de las restricciones
diferibles
? Initially immediate
? Se comprueba cada vez que se ejecuta una sentencia SQL
Reserva las cuentas de los clientes de Durango
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
Desarrollo de Bases de Datos
Cambio de las definiciones de
restricciones
SET CONSTRAINTS [ALL | murriztapen_izena {, urriztapen_izena}]
[DEFERRED | IMMEDIATE]
? En general las restricciones serán diferibles
? La comprobación de las restricciones diferidas se retrasa
hasta que se haga explícito #sql {set ... immediate} o hasta
comprometer la transacción.
? Al comprometer una transacción que tiene las
restricciones diferidas, el sistema las pasa al estado
immediate y se hace la comprobación.
?Si se viola una restricción, se termina la transacción (rollback) y
se envía un mensaje de error
Restricciones. Ejemplos
#sql {insert into alumno values (23, …)};
...
#sql {commit};
create table alumno(…
constraint matriculado check dni in (select dni from matricula)
not deferrable)
insert ...
commit
create table alumno(…
constraint matriculado check dni in (select dni from matricula)
deferrable initially immediate )
insert ...
Restricciones. Ejemplos
#sql {insert into alumno values (23, …)};
...
#sql {commit};
create table alumno(…
constraint matriculado check dni in (select dni from matricula)
deferrable initially deferred )
insert ...
commit
insert ...
set constraint …
immediate
commit
Oscar Díaz - Facultad de Informática - Universidad del País Vasco / Euskal Herriko
Unibertsitatea
commit