Database Administrators
Q&A for database professionals who wish to improve their database skills
Latest Questions
0
votes
1
answers
1022
views
How to gracefully handle MySQL deadlocks involving SAVEPOINT?
I have a concurrency problem where 2 (or more) processes are making inserts at the same time and are all locking the same index page (I guess) among with a on a `SELECT FOR UPDATE` clause Here is a reproducible sample: CREATE TABLE U ( -- user id int not null primary key, name varchar(222) ); CREATE...
I have a concurrency problem where 2 (or more) processes are making inserts at the same time and are all locking the same index page (I guess) among with a on a
SELECT FOR UPDATE
clause
Here is a reproducible sample:
CREATE TABLE U ( -- user
id int not null primary key,
name varchar(222)
);
CREATE TABLE O ( -- object
id int not null primary key,
name varchar(222)
);
CREATE TABLE OU ( -- user object
id int not null auto_increment primary key,
object_id int,
user_id int,
-- (object_id, user_id) should be UNIQUE (not enforced by a constraint)
CONSTRAINT fk_object_id FOREIGN KEY (object_id) REFERENCES O(id) ON DELETE CASCADE,
CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES U(id) ON DELETE CASCADE
);
INSERT INTO U VALUES (1, 'foo'), (2, 'bar');
-- Start 2 concurrent transactions (A, B)
BEGIN; -- A
BEGIN; -- B
INSERT INTO O VALUES (1, 'a'); -- A
INSERT INTO O VALUES (2, 'b'); -- B
SAVEPOINT s_a; -- A
SAVEPOINT s_b; -- B
SELECT * FROM OU WHERE object_id = 1 FOR UPDATE; -- A
SELECT * FROM OU WHERE object_id = 2 FOR UPDATE; -- B
INSERT INTO OU(object_id, user_id) VALUES (1, 1); -- A
INSERT INTO OU(object_id, user_id) VALUES (2, 1); -- B
one of the transactions will fail with a Deadlock found when trying to get lock; try restarting transaction
error.
The problem is that it rolls back the **whole** transaction without any way for me to gracefully handle the error.
In that example, the object 2
is lost. I would **really** like for it to still persist and handle the second insert a few seconds / minutes after another transaction.
The way the code is currently designed does not allow fine tuning of the transaction block (I cannot commit after the first insert then start another transaction)
Is there any way to tell MySQL to not rollback on that deadlock error, or to rollback specifically to the savepoint?
**edit** here is the innodb engine status
*** (1) TRANSACTION:
TRANSACTION 3727668996, ACTIVE 0 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1184, 2 row lock(s), undo log entries 1
MySQL thread id 20145497, OS thread handle 0x7f4fdba2b700, query id 15334836096 xxxxxxxxxxxxx.xxxx.xxx.xxxx.xxx 10.150.15.33 user1 update
INSERT INTO Tablename
(product_id, product_type_id, contact_id, last_transaction_id, creation_date) VALUES (655988, 1, 26399, NULL, '2017-04-20 19:04:21')
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 201 page no 1012 n bits 840 index product_id
of table dbname
.Tablename
trx id 3727668996 lock_mode X locks gap before rec insert intention waiting
*** (2) TRANSACTION:
TRANSACTION 3727668998, ACTIVE 0 sec inserting, thread declared inside InnoDB 5000
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1184, 2 row lock(s), undo log entries 1
MySQL thread id 20145647, OS thread handle 0x7f5d6d253700, query id 15334836100 xxxxxxxxxxxxx.xxxx.xxx.xxxx.xxx 10.150.15.35 user1 update
INSERT INTO Tablename
(product_id, product_type_id, contact_id, last_transaction_id, creation_date) VALUES (655991, 1, 26399, NULL, '2017-04-20 19:04:21')
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 201 page no 1012 n bits 840 index product_id
of table dbname
.Tablename
trx id 3727668998 lock_mode X locks gap before rec
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 201 page no 1012 n bits 840 index product_id
of table dbname
.Tablename
trx id 3727668998 lock_mode X locks gap before rec insert intention waiting
*** WE ROLL BACK TRANSACTION (2)
Romuald Brunet
(101 rep)
Apr 20, 2017, 01:00 PM
• Last activity: Aug 3, 2025, 10:04 AM
0
votes
1
answers
465
views
PostgreSQL driven by SQLAlchemy - Release Savepoint Idle in Transaction
While running PostgreSQL 13.12 (occurs in several versions of PG11/PG13) using SQLAlchemy 1.3, we are occasionally hitting issues where increased concurrency leaves certain transactions (and their nested transactions) in the "Idle in Transaction" state with the `RELEASE SAVEPOINT ...` query. Looking...
While running PostgreSQL 13.12 (occurs in several versions of PG11/PG13) using SQLAlchemy 1.3, we are occasionally hitting issues where increased concurrency leaves certain transactions (and their nested transactions) in the "Idle in Transaction" state with the
RELEASE SAVEPOINT ...
query.
Looking at the currently running queries, it is not clear why transactions have stopped moving forward. I have also observed this behavior without any hanging locks:
| pid | datname | duration | query | state | application_name | wait_event_type |
| --- | ------- | -------- | ----- | ----- | ---------------- | --------------- |
| 27662 | app | 22:22:37.429569 | select pg_advisory_xact_lock(resource_id) from resource where uuid = '018afcac-a5ab-7a5c-9eb4-2d8b0be4b556'
| active | http.api.1 | Lock |
| 25830 | app | 22:22:29.236398 | RELEASE SAVEPOINT sa_savepoint_5
| idle in transaction | http.api.0 | Client |
| 21490 | app | 22:22:29.015862 | select pg_advisory_xact_lock(resource_id)
from resource
where uuid = '018afcac-a5ab-7a5c-9eb4-2d8b0be4b556'
| active | http.api.0 | Lock |
| 27674 | app | 22:22:27.780581 | RELEASE SAVEPOINT sa_savepoint_3
| idle in transaction | http.api.2 | Client |
| 29120 | app | 22:22:26.053851 | select pg_advisory_xact_lock(resource_id)
from resource
where uuid = '018afcac-a5ab-7a5c-9eb4-2d8b0be4b556'
| active | http.api.2 | Lock |
Any way to debug this? This API call generally works, with the session being cleaned up and does not fail consistently. We are using SQL Alchemy's connection pooling to manage the connections - closed sessions will return the connection to the pool and issue a rollback to clean up the connection (when commit should have committed all other statements).
Justin Lowen
(68 rep)
Oct 8, 2023, 05:16 PM
• Last activity: Oct 9, 2023, 09:40 AM
0
votes
1
answers
1535
views
syntax error at or near TO (ROLLBACK TO SAVEPOINT)
The following sql is a part from a FUNCTION ,i want to rollback to rbk SAVEPOINT : ```sql for ptrEnt in entite loop -- positionnement du point de retour pour une entité savepoint rbk; -- purge de la table des redevances de l''entite test := pckg_activ.initredevanceentite(ptrEnt.cod...
The following sql is a part from a FUNCTION ,i want to rollback to rbk SAVEPOINT :
for ptrEnt in entite loop
-- positionnement du point de retour pour une entité
savepoint rbk;
-- purge de la table des redevances de l''entite
test := pckg_activ.initredevanceentite(ptrEnt.cod_ent);
-- calcul de la redevance
test := pckg_activ.calculredevanceentite(ptrEnt.cod_ent);
-- controle calcul de la bonne execution pour l''entité
if (test = 0) then
-- initialisation des departements associes a une entite
test := pckg_activ.initdepartement(ptrEnt.cod_ent);
-- validation des modifications
commit;
-- generation de l''etat recapitulatif
test := pckg_activ.recapentitegestionnaire(ptrEnt.cod_ent,ficHisto);
else
rollback TO SAVEPOINT rbk;
report := jour + 7;
update sav_rdv_date
set date_dem = report
where cod_ent = ptrEnt.cod_ent;
RAISE NOTICE '!!erreur de patrimoine => abandon du traitement pour cette entite';
commit;
end if;
end loop;
**entite** is a cursor that has been declared and the **for loop** is in a *BEGIN* bloc.
I get the error ERROR: error at or near "TO"
. I think that the syntax is correct , it it related to the cursor ?
unknownUser
(29 rep)
Apr 22, 2020, 03:58 PM
• Last activity: Aug 15, 2021, 02:12 PM
0
votes
2
answers
3501
views
ROLLBACK TO SAVEPOINT syntax error at or near "TO"
I am having trouble in executing the following FUNCTION in PostgreSQL ```sql CREATE OR REPLACE FUNCTION pckg_fcvoi.supprimer_voies_plus_42c (CodeEntite text) RETURNS VOID AS $body$ DECLARE cpt_voies_ACTIV numeric := 0; cpt_voies_User numeric := 0; cpt_voies_42C numeric := 0; cpt_voies_sup numeric :=...
I am having trouble in executing the following FUNCTION in PostgreSQL
CREATE OR REPLACE FUNCTION pckg_fcvoi.supprimer_voies_plus_42c (CodeEntite text) RETURNS VOID AS $body$
DECLARE
cpt_voies_ACTIV numeric := 0;
cpt_voies_User numeric := 0;
cpt_voies_42C numeric := 0;
cpt_voies_sup numeric := 0;
/*----------------------------------------------------------------*/
/* Liste des voies non importees de 42C, susceptibles d'etre */
/* supprimees. */
/*----------------------------------------------------------------*/
cursor_VOIES_PLUS_42C CURSOR FOR
SELECT com_commune.cod_ent,
com_voie.cod_insee,
com_voie.cod_rivoli,
com_voie.lib
FROM com_voie,
com_commune
WHERE com_commune.cod_insee = com_voie.cod_insee
AND com_commune.cod_ent = CodeEntite
AND com_voie.origine_voie = 'D';
BEGIN
-- DBMS_OUTPUT.ENABLE(1000000);
SELECT COUNT(*) INTO STRICT cpt_voies_ACTIV
FROM com_voie,
com_commune
WHERE com_commune.cod_insee = com_voie.cod_insee
AND com_commune.cod_ent = CodeEntite;
SELECT COUNT(*) INTO STRICT cpt_voies_User
FROM com_voie,
com_commune
WHERE com_commune.cod_insee = com_voie.cod_insee
AND com_commune.cod_ent = CodeEntite
and com_voie.origine_voie = 'U';
SELECT COUNT(*) INTO STRICT cpt_voies_42C
FROM com_voie,
com_commune
WHERE com_commune.cod_insee = com_voie.cod_insee
AND com_commune.cod_ent = CodeEntite
and com_voie.origine_voie = 'S';
SELECT COUNT(*) INTO STRICT cpt_voies_sup
FROM com_voie,
com_commune
WHERE com_commune.cod_insee = com_voie.cod_insee
AND com_commune.cod_ent = CodeEntite
and com_voie.origine_voie = 'D';
RAISE NOTICE ' - Nombre de voies dans la base ACTIV pour % : %', CodeEntite, cpt_voies_ACTIV;
RAISE NOTICE ' - Nombre de voies utilisateur pour % : %', CodeEntite, cpt_voies_User;
RAISE NOTICE ' - Nombre de voies importees de 42C pour % : %', CodeEntite, cpt_voies_42C;
RAISE NOTICE ' - Nombre de voies supprimables pour % : %', CodeEntite, cpt_voies_sup;
/*---------------------------------------------------------------------------------------*/
/* Pour toutes les voies susceptibles d'etre supprimees */
/* dont le cod_ent est a traiter : */
/* - Supprimer la voie */
/* - si la suppression echoue */
/* alors */
/* afficher la voie est supprimable mais dossier attache */
/* sinon */
/* afficher la voie est supprimee */
/* finsi */
/*---------------------------------------------------------------------------------------*/
RAISE NOTICE 'Voies ne pouvant etre supprimees de la base ACTIV pour % :', CodeEntite;
RAISE NOTICE '---------------------------------------------------------';
cpt_voies_sup := 0;
FOR enreg_VOIES_PLUS_42C IN cursor_VOIES_PLUS_42C LOOP
BEGIN
DELETE FROM com_voie
WHERE cod_insee = enreg_VOIES_PLUS_42C.cod_insee
AND cod_rivoli = enreg_VOIES_PLUS_42C.cod_rivoli;
/* DBMS_OUTPUT.PUT_LINE('Suppression de '||enreg_VOIES_PLUS_42C.COD_ENT||';'||enreg_VOIES_PLUS_42C.COD_INSEE||';'||enreg_VOIES_PLUS_42C.COD_RIVOLI||';'||enreg_VOIES_PLUS_42C.LIB);*/
cpt_voies_sup := cpt_voies_sup + 1;
EXCEPTION
/*-----------------------------------------------------------*/
/* La suppression de la voie a echoue */
/*-----------------------------------------------------------*/
WHEN OTHERS THEN
IF position('ACTIV.FK_CORRESP_VOIE' in SQLERRM) > 0
THEN
/*-------------------------------------------------------------*/
/* La suppression de la voie a echoue : */
/* supprimer la correspondance voie-gestionnaire, puis la voie */
/*-------------------------------------------------------------*/
BEGIN
/* DBMS_OUTPUT.PUT_LINE(enreg_VOIES_PLUS_42C.COD_ENT||';'||enreg_VOIES_PLUS_42C.COD_INSEE||';'||enreg_VOIES_PLUS_42C.COD_RIVOLI||';'||enreg_VOIES_PLUS_42C.LIB||'; Declaree dans SAV_CORRESP_VOIE_GEST');*/
SAVEPOINT SP_FK_CORRESP_VOIE;
DELETE FROM sav_corresp_voie_gest
WHERE cod_insee = enreg_VOIES_PLUS_42C.cod_insee
AND cod_rivoli = enreg_VOIES_PLUS_42C.cod_rivoli;
DELETE FROM com_voie
WHERE cod_insee = enreg_VOIES_PLUS_42C.cod_insee
AND cod_rivoli = enreg_VOIES_PLUS_42C.cod_rivoli;
/* DBMS_OUTPUT.PUT_LINE('Suppression de '||enreg_VOIES_PLUS_42C.COD_ENT||';'||enreg_VOIES_PLUS_42C.COD_INSEE||';'||enreg_VOIES_PLUS_42C.COD_RIVOLI||';'||enreg_VOIES_PLUS_42C.LIB);*/
cpt_voies_sup := cpt_voies_sup + 1;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK TO SAVEPOINT SP_FK_CORRESP_VOIE;
END;
ELSE
/*-----------------------------------------------------------*/
/* La suppression de la voie a echoue : afficher la cause */
/*-----------------------------------------------------------*/
RAISE NOTICE '%;%;%;%;%', enreg_VOIES_PLUS_42C.COD_ENT, enreg_VOIES_PLUS_42C.COD_INSEE, enreg_VOIES_PLUS_42C.COD_RIVOLI, enreg_VOIES_PLUS_42C.LIB, SUBSTR(SQLERRM, 1, 200);
END IF;
END;
END LOOP;
RAISE NOTICE ' - Nombre de voies supprimees pour % : %', CodeEntite, cpt_voies_sup;
EXCEPTION
WHEN OTHERS THEN
RAISE NOTICE 'Exception dans pckg_fcvoi.supprimer_voies_plus_42c(%) : %, %', CodeEntite, SQLSTATE, SUBSTR(SQLERRM, 1, 100);
RAISE NOTICE 'ARRET DU TRAITEMENT !';
ROLLBACK;
END;
I am having this error
> syntax error at or near "TO".
It is related to the exception block?
Any solutions?
unknownUser
(29 rep)
Mar 23, 2020, 03:51 PM
• Last activity: Mar 25, 2020, 08:38 AM
2
votes
2
answers
1462
views
Do Nested Transactions commit?
I am not happy with the [Wikipedia article about nested transactions][1]. I would not use the word "commit" for a nested transaction. For me "commit" means "durability". A nested transaction does not provide durability. 1. Is it ok to use the word "commit" for nested transactions? 2. What word could...
I am not happy with the Wikipedia article about nested transactions .
I would not use the word "commit" for a nested transaction.
For me "commit" means "durability". A nested transaction does not provide durability.
1. Is it ok to use the word "commit" for nested transactions?
2. What word could be used, if it is not ok?
guettli
(1591 rep)
Sep 1, 2015, 08:35 AM
• Last activity: Sep 1, 2015, 09:30 AM
1
votes
1
answers
477
views
SQLAnywhere: Savepoint for ROLLBACK not found
What is the correct way on setting and rolling back to savepoint on SQLAnywhere. Having this snippet: begin transaction; SAVEPOINT spt_abc; insert into eins (pl1) values (5); SAVEPOINT spt_123; UPDATE eins SET pl1 = 10 where pl1 = 5; ROLLBACK TO SAVEPOINT spt_abc; commit; Getting this error message...
What is the correct way on setting and rolling back to savepoint on SQLAnywhere. Having this snippet:
begin transaction;
SAVEPOINT spt_abc;
insert into eins (pl1) values (5);
SAVEPOINT spt_123;
UPDATE eins SET pl1 = 10 where pl1 = 5;
ROLLBACK TO SAVEPOINT spt_abc;
commit;
Getting this error message while running it in dbisql:
> Could not execute statement. Savepoint 'spt_abc' not found SQLCODE=-220, ODBC 3 State="HY000" Line 6, column 1 You can continue
> executing or stop.
>
> ROLLBACK TO SAVEPOINT spt_abc
the very same happens when trying to rollback to spt_123.
frlan
(495 rep)
Aug 28, 2015, 12:50 PM
• Last activity: Aug 30, 2015, 07:41 PM
Showing page 1 of 6 total questions