sábado, abril 21, 2007

un bloqueo en postgresql

Al revisar el blog de CarlosAL, en específico la entrada indices-y-foreign-keys me entró la duda de que pasa con postgreSQL, claro que solo revise el caso de los bloqueos, me parece que en postgres también es bueno crear índices por cada llave foránea que se tenga.

contexto:
miguel@asakura:~$ psql postgres
Bienvenido a psql 8.1.8, la terminal interactiva de PostgreSQL.

Digite: \copyright para ver los términos de distribución
\h para ayuda de comandos SQL
\? para ayuda de comandos psql
\g o or termine con punto y coma para ejecutar una consulta
\q para salir

postgres=# \d prueba01;
Tabla «public.prueba01»
Columna | Tipo | Modificadores
---------+-------------------+---------------
id_n | integer | not null
c_txt | character varying |
Índices:
«idx_id_n» PRIMARY KEY, btree (id_n)

postgres=# \d prueba04;
Tabla «public.prueba04»
Columna | Tipo | Modificadores
---------+---------+---------------
id_n | integer |
upper | text |
Restricciones de llave foránea:
«fdx_id_n» FOREIGN KEY (id_n) REFERENCES prueba01(id_n)

postgres=# SELECT * from prueba01;
id_n | c_txt
------+--------------
1 | uno
2 | dos
3 | tres
4 | cuatro
5 | cinco
6 | seis
11 | once
21 | veintiuno
23 | veintitres
24 | veinticuatro
25 | veinticinco
30 | treinta
(12 filas)

postgres=# SELECT * from prueba04;
id_n | upper
------+--------
1 | UNO
2 | DOS
3 | TRES
4 | CUATRO
5 | CINCO
6 | SEIS
(6 filas)

sesión 1
postgres=# BEGIN ;
BEGIN

sesión 2
postgres=# BEGIN ;
BEGIN
postgres=# INSERT into prueba04 VALUES (30,'TREINTA');
INSERT 0 1

sesión 1

postgres=# DELETE FROM prueba01 WHERE id_n = 30;
En este caso espera, porque la sesión 2 está haciendo uso de la fila que tiene id_n = 30 en prueba01

sesión 2
postgres=# commit;
COMMIT

sesión 1
inmediatamente despues del commit de la sesión 2
ERROR: update o delete en «prueba01» viola la llave foránea «fdx_id_n» en «prueba04»
DETAIL: La llave (id_n)=(30) todavía es referida desde la tabla «prueba04».
postgres=# end;
ROLLBACK
al hacer commit se compromete esta transacción y se procede al rollback.

Ahora intentaremos borrar una tupla que no este ocupada por la sesión 2 ni por alguna referencia en prueba04
sesión 2
postgres=# begin;
BEGIN
postgres=# INSERT into prueba04 VALUES (21,'VEINTIUNO');
INSERT 0 1

session 1
postgres=# BEGIN;
BEGIN
postgres=# DELETE FROM prueba01 WHERE id_n =25;
DELETE 1
postgres=# end;
COMMIT
Como vemos en este caso ni siquiera espero, se puede hacer el commit de inmediato.

session 2
postgres=# end;
COMMIT

3 comentarios:

Anónimo dijo...

Hombre!

Ya que prácticamente COPIAS mi artículo (nombres de tablas, columnas e incluso datos incluidos), podrías indicar de dónde y de quién has sacado la 'inspiración' para escribirlo.

Saludos.

Carlos.

Unknown dijo...

oh, bueno, aunque lo dije, creo que trataré de ser más explicito, y disculpa si lo tomaste a mal.
Y si, la intención era copiar para reproducir el mismo comportamieton en postgresql, cosa que no se logra...

Anónimo dijo...

OK.

Sin problemas.

Gracias por indicar mi 'link' más explícitamente.

Saludos.

Carlos.