42.9. ЯвнÑе подÑÑанзакÑии в PL/Tcl
ÐеÑÐµÑ Ð²Ð°Ñ Ð¾Ñибок, пÑоизоÑедÑÐ¸Ñ Ð¿Ñи обÑаÑении к базе даннÑÑ , как опиÑано в Разделе 42.8, Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑивеÑÑи к нежелаÑелÑной ÑиÑÑаÑии, когда ÑаÑÑÑ Ð¾Ð¿ÐµÑаÑий бÑÐ´ÐµÑ ÑÑпеÑно вÑполнена, пÑежде Ñем пÑоизойдÑÑ Ñбой. ÐаннÑе оÑÑанÑÑÑÑ Ð² неÑоглаÑованном ÑоÑÑоÑнии поÑле обÑабоÑки Ñакой оÑибки. PL/Tcl пÑÐµÐ´Ð»Ð°Ð³Ð°ÐµÑ ÑеÑение ÑÑой пÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ð² ÑоÑме ÑвнÑÑ Ð¿Ð¾Ð´ÑÑанзакÑий.
РаÑÑмоÑÑиÑе ÑÑнкÑиÑ, ÑеализÑÑÑÑÑ Ð¿ÐµÑевод денег Ð¼ÐµÐ¶Ð´Ñ Ð´Ð²ÑÐ¼Ñ ÑÑеÑами:
CREATE FUNCTION transfer_funds() RETURNS void AS $$
if [catch {
spi_exec "UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'"
spi_exec "UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'"
} errormsg] {
set result [format "error transferring funds: %s" $errormsg]
} else {
set result "funds transferred successfully"
}
spi_exec "INSERT INTO operations (result) VALUES ('[quote $result]')"
$$ LANGUAGE pltcl; ÐÑли вÑоÑой опеÑаÑÐ¾Ñ UPDATE вÑдаÑÑ Ð¸ÑклÑÑение, ÑÑа ÑÑнкÑÐ¸Ñ Ð·Ð°Ð¿Ð¸ÑÐµÑ Ð² жÑÑнал ÑообÑение об оÑибке, но ÑезÑлÑÑÐ°Ñ Ð¿ÐµÑвого UPDATE бÑÐ´ÐµÑ Ñем не менее заÑикÑиÑован. ÐÑÑгими Ñловами, денежнÑе ÑÑедÑÑва бÑдÑÑ ÑпиÑÐ°Ð½Ñ Ñо ÑÑÑÑа Ðжо, но не поÑÑÑпÑÑ Ð½Ð° ÑÑÑÑ ÐеÑи. ÐÑо пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð¿Ð¾ÑомÑ, ÑÑо каждÑй вÑзов spi_exec вÑполнÑеÑÑÑ Ð² оÑделÑной подÑÑанзакÑии, а оÑкаÑÑваеÑÑÑ ÑолÑко одна из подÑÑанзакÑий.
Ð ÑакиÑ
ÑлÑÑаÑÑ
Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе обеÑнÑÑÑ Ð½ÐµÑколÑко опеÑаÑий Ñ Ð±Ð°Ð·Ð¾Ð¹ даннÑÑ
в Ð¾Ð´Ð½Ñ ÑвнÑÑ Ð¿Ð¾Ð´ÑÑанзакÑиÑ, коÑоÑÐ°Ñ Ð±ÑÐ´ÐµÑ Ð²Ñполнена ÑÑпеÑно или оÑменена как единое Ñелое. ÐÐ»Ñ ÑÑого в PL/Tcl еÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° subtransaction. С ней Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ пеÑепиÑаÑÑ Ð½Ð°ÑÑ ÑÑнкÑÐ¸Ñ Ñак:
CREATE FUNCTION transfer_funds2() RETURNS void AS $$
if [catch {
subtransaction {
spi_exec "UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'"
spi_exec "UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'"
}
} errormsg] {
set result [format "error transferring funds: %s" $errormsg]
} else {
set result "funds transferred successfully"
}
spi_exec "INSERT INTO operations (result) VALUES ('[quote $result]')"
$$ LANGUAGE pltcl; ÐамеÑÑÑе, ÑÑо и в ÑÑом ÑлÑÑае нÑжно иÑполÑзоваÑÑ catch. РпÑоÑивном ÑлÑÑае оÑибка ÑаÑпÑоÑÑÑаниÑÑÑ Ð½Ð° веÑÑ
ний ÑÑÐ¾Ð²ÐµÐ½Ñ ÑÑнкÑии, ÑÑо не даÑÑ Ð¿ÑоизвеÑÑи желаемое добавление запиÑи в ÑаблиÑÑ operations. Ðоманда subtransaction не пеÑеÑ
ваÑÑÐ²Ð°ÐµÑ Ð¾Ñибки, она ÑолÑко обеÑпеÑÐ¸Ð²Ð°ÐµÑ Ð¾ÑÐºÐ°Ñ Ð²ÑеÑ
опеÑаÑий Ñ Ð±Ð°Ð·Ð¾Ð¹ даннÑÑ
в Ñвоей облаÑÑи дейÑÑÐ²Ð¸Ñ Ð² ÑлÑÑае оÑибки.
ÐÑÐºÐ°Ñ Ñвной подÑÑанзакÑии пÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð² ÑлÑÑае лÑбÑÑ
оÑибок, ÑгенеÑиÑованнÑÑ
вложеннÑм кодом Tcl, а не ÑолÑко оÑибок, возникаÑÑиÑ
пÑи обÑаÑении к базе даннÑÑ
. Таким обÑазом, обÑÑное иÑклÑÑение Tcl, возникÑее внÑÑÑи ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ subtransaction, Ñакже пÑиведÑÑ Ðº оÑкаÑÑ Ð¿Ð¾Ð´ÑÑанзакÑии. Ðднако пÑи вÑÑ
оде из вложенного кода Tcl без оÑибки (напÑимеÑ, Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ return) оÑÐºÐ°Ñ Ð½Ðµ пÑоизводиÑÑÑ.