Si spera che una semplice domanda, ma per la quale non ho trovato una risposta decente. Sono informato in modo affidabile che le stored procedure (funzioni DB definite dall'utente) in PostgreSQL (in particolare, versione 9.0.4) sono intrinsecamente transazionali, in quanto vengono chiamate attraverso un'istruzione SELECT che a sua volta è una transazione. Quindi, come si sceglie il livello di isolamento della stored procedure? Credo che in altri DBMS il blocco transazionale desiderato sia racchiuso in un blocco START TRANSACTION per il quale il livello di isolamento desiderato è un parametro facoltativo.imposta il livello di isolamento per le stored procedure postgresql
Come esempio specifico made-up, dire che voglio fare questo:
CREATE FUNCTION add_new_row(rowtext TEXT)
RETURNS VOID AS
$$
BEGIN
INSERT INTO data_table VALUES (rowtext);
UPDATE row_counts_table SET count=count+1;
END;
$$
LANGUAGE plpgsql
SECURITY DEFINER;
E immaginate io voglio assicurarmi che questa funzione viene sempre eseguita come una transazione serializzabile (sì, sì, PostgreSQL isn SERIALIZABLE È corretto serializzabile, ma non è questo il punto). Non voglio richiedere che venga chiamato come
START TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT add_new_row('foo');
COMMIT;
Quindi, come si inserisce il livello di isolamento richiesto nella funzione? Credo che non si può semplicemente mettere il livello di isolamento nella dichiarazione BEGIN
, come the manual says
E 'importante non confondere l'uso di BEGIN/END per raggruppare dichiarazioni in PL/pgSQL con il nome simile SQL comandi per il controllo delle transazioni. BEGIN/END PL/pgSQL sono solo per il raggruppamento ; non avviano o terminano una transazione . Funzioni e innescare procedure vengono sempre eseguiti all'interno una transazione stabilita da un esterno interrogazione - non possono iniziare o commettere tale operazione, dal momento che non ci sarebbe alcun contesto per loro di eseguire in
La più ovvia. approccio per me sarebbe quella di utilizzare SET TRANSACTION
da qualche parte nella definizione della funzione, ad esempio ,:
CREATE FUNCTION add_new_row(rowtext TEXT)
RETURNS VOID AS
$$
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
INSERT INTO data_table VALUES (rowtext);
UPDATE row_counts_table SET count=count+1;
END;
$$
LANGUAGE plpgsql
SECURITY DEFINER;
Anche se questo sarebbe stato accettato, non è chiaro di quanto io possa contare su questo per lavorare. Il documentation per SET TRANSACTION
dice
Se SET TRANSACTION viene eseguito senza uno START prima transazione o BEGIN, apparirà avere alcun effetto, dal momento che la transazione immediatamente fine.
Il che mi lascia perplesso, dal momento che se chiamo un solitario SELECT add_new_row('foo');
dichiarazione mi aspetterei (fornito non ho disabilitato autocommit) SELECT essere in esecuzione come una transazione singola linea con il livello di isolamento sessione predefinita.
Il manual dice anche: livello di isolamento
La transazione non può essere modificato dopo la prima query o dichiarazione di modifica dati (SELECT, INSERT, DELETE, UPDATE, FETCH o COPIA) di una transazione è stata eseguita .
Che cosa succede se la funzione viene chiamata dall'interno di una transazione con un livello di isolamento più basso, per esempio,:.
START TRANSACTION ISOLATION LEVEL READ COMMITTED;
UPDATE row_counts_table SET count=0;
SELECT add_new_row('foo');
COMMIT;
Per una domanda bonus: non il linguaggio della funzione fa alcuna differenza? Si potrebbe impostare il livello di isolamento in modo diverso in PL/pgSQL rispetto a SQL semplice?
Sono un fan degli standard e delle best practice documentate, quindi qualsiasi riferimento decente sarebbe apprezzato.
Che cosa è successo quando si è tentato di utilizzare 'SET TRANSACTION' all'interno della funzione? –
@a_horse_with_no_name: come ho detto, immagino che "SET TRANSACTION" sia ciò di cui ho bisogno e le funzioni con esso sono accettate, ma a volte ciò non significa molto (alcune opzioni vengono ingoiate a volte), quindi sto cercando un approccio documentato piuttosto che qualcosa che sembra funzionare. – beldaz
Postgres ingerisce raramente quello che gli dici di fare - e quando lo fa mi aspetterei che emettesse un avvertimento. –