32.5. ÐонвейеÑнÑй Ñежим #
ÐонвейеÑнÑй Ñежим libpq даÑÑ Ð¿ÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¾ÑпÑавиÑÑ Ð·Ð°Ð¿ÑоÑ, не полÑÑÐ°Ñ ÑезÑлÑÑÐ°Ñ Ð¿ÑедÑдÑÑего. ÐÑполÑзÑÑ Ð¿ÑеимÑÑеÑÑва конвейеÑного Ñежима, ÐºÐ»Ð¸ÐµÐ½Ñ Ð±ÑÐ´ÐµÑ Ð¼ÐµÐ½ÑÑе ждаÑÑ ÑеÑвеÑ, поÑколÑÐºÑ Ð½ÐµÑколÑко запÑоÑов/ÑезÑлÑÑаÑов могÑÑ Ð±ÑÑÑ Ð¾ÑпÑавленÑ/полÑÑÐµÐ½Ñ Ð² одной ÑеÑевой ÑÑанзакÑии.
ХоÑÑ ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑнÑй Ñежим обеÑпеÑÐ¸Ð²Ð°ÐµÑ Ð·Ð½Ð°ÑиÑелÑнÑй пÑиÑоÑÑ Ð¿ÑоизводиÑелÑноÑÑи, ÑазÑабаÑÑваÑÑ ÐºÐ»Ð¸ÐµÐ½ÑÑкие пÑиложениÑ, иÑполÑзÑÑÑие ÑÑÐ¾Ñ Ñежим, гоÑаздо Ñложнее, Ñак как ÑÑебÑеÑÑÑ ÑеализовÑваÑÑ Ð¾ÑеÑеди ожидаÑÑÐ¸Ñ Ð·Ð°Ð¿ÑоÑов и ÑопоÑÑавлÑÑÑ ÑезÑлÑÑаÑÑ Ñ Ð·Ð°Ð¿ÑоÑами в оÑеÑеди.
ÐÐ»Ñ ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑного Ñежима Ñакже обÑÑно ÑÑебÑеÑÑÑ Ð±Ð¾Ð»ÑÑе памÑÑи как на ÑÑоÑоне клиенÑа, Ñак и на ÑÑоÑоне ÑеÑвеÑа, Ñ Ð¾ÑÑ ÑÑаÑелÑное и агÑеÑÑивное ÑпÑавление оÑеÑедÑÑ Ð¾ÑпÑавки/полÑÑÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ ÑÑо нивелиÑоваÑÑ. ÐÑо не завиÑÐ¸Ñ Ð¾Ñ Ñого, в каком Ñежиме â блокиÑÑÑÑем или Ð½ÐµÑ â ÑÑÑанавливаеÑÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑÑение.
ХоÑÑ ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑнÑй API в libpq поÑвилÑÑ Ñ Ð²ÑÑ Ð¾Ð´Ð¾Ð¼ Postgres Pro 14, ÑÑо клиенÑÑÐºÐ°Ñ ÑÑнкÑионалÑноÑÑÑ, коÑоÑÐ°Ñ Ð½Ðµ ÑÑебÑÐµÑ ÑпеÑиалÑной поддеÑжки на ÑÑоÑоне ÑеÑвеÑа и ÑабоÑÐ°ÐµÑ Ñ Ð»ÑбÑм ÑеÑвеÑом, поддеÑживаÑÑем 3-Ñ Ð²ÐµÑÑÐ¸Ñ ÑаÑÑиÑенного пÑоÑокола запÑоÑов. Ðа дополниÑелÑнÑми ÑведениÑми обÑаÑиÑеÑÑ Ðº ÐодÑазделÑ 53.2.4.
32.5.1. ÐÑполÑзование конвейеÑного Ñежима #
ÐÐ»Ñ Ð·Ð°Ð¿ÑÑка конвейеÑов пÑиложение должно пеÑеклÑÑиÑÑ Ñоединение в конвейеÑнÑй Ñежим поÑÑедÑÑвом ÑÑнкÑии PQenterPipelineMode. Ðожно пÑовеÑиÑÑ, вклÑÑÑн ли даннÑй Ñежим, иÑполÑзÑÑ ÑÑнкÑÐ¸Ñ PQpipelineStatus. РконвейеÑном Ñежиме ÑазÑеÑÐµÐ½Ñ ÑолÑко аÑинÑ
ÑоннÑе опеÑаÑии, иÑполÑзÑÑÑие ÑаÑÑиÑеннÑй пÑоÑокол запÑоÑов, а ÑÑÑоки команд, ÑодеÑжаÑие неÑколÑко SQL-команд, и команда COPY запÑеÑенÑ. ÐÑполÑзоваÑÑ ÑÑнкÑии ÑинÑ
Ñонного вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´, Ñакие как PQfn, PQexec, PQexecParams, PQprepare, PQexecPrepared, PQdescribePrepared, PQdescribePortal, PQclosePrepared, PQclosePortal в ÑÑом Ñежиме нелÑзÑ. ФÑнкÑÐ¸Ñ PQsendQuery пÑименÑÑÑ Ñакже нелÑзÑ, Ñак как она иÑполÑзÑÐµÑ Ð¿ÑоÑÑой пÑоÑокол запÑоÑов. ÐбÑабоÑав ÑезÑлÑÑаÑÑ Ð²ÑеÑ
оÑпÑавленнÑÑ
команд и иÑоговÑй ÑезÑлÑÑÐ°Ñ ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑа, пÑиложение Ð¼Ð¾Ð¶ÐµÑ Ð²ÐµÑнÑÑÑÑÑ Ð² обÑÑнÑй Ñежим, вÑзвав PQexitPipelineMode.
ÐÑимеÑание
ÐонвейеÑнÑй Ñежим ÑекомендÑеÑÑÑ Ð¸ÑполÑзоваÑÑ Ð¿Ñи ÑабоÑе libpq в неблокиÑÑÑÑем Ñежиме. РблокиÑÑÑÑем Ñежиме Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñ Ð²Ð·Ð°Ð¸Ð¼Ð¾Ð±Ð»Ð¾ÐºÐ¸Ñовки на ÑÑовне клиенÑ-ÑеÑвеÑ. [15]
32.5.1.1. ÐÑпÑавка запÑоÑов #
ÐеÑÐµÐ¹Ð´Ñ Ð² конвейеÑнÑй Ñежим, пÑиложение оÑпÑавлÑÐµÑ Ð·Ð°Ð¿ÑоÑÑ, вÑзÑÐ²Ð°Ñ PQsendQueryParams или ÑодÑÑвеннÑÑ ÐµÐ¹ ÑÑнкÑÐ¸Ñ PQsendQueryPrepared, ÑабоÑаÑÑÑÑ Ñ Ð¿Ð¾Ð´Ð³Ð¾ÑовленнÑми запÑоÑами. ÐаннÑе запÑоÑÑ ÑÑавÑÑÑÑ Ð² оÑеÑÐµÐ´Ñ Ð½Ð° ÑÑоÑоне клиенÑа, а заÑем ÑбÑаÑÑваÑÑÑÑ Ð½Ð° ÑеÑвеÑ; ÑÑо пÑоиÑÑ
одиÑ, когда вÑзÑваеÑÑÑ PQpipelineSync, ÑÑÑанавливаÑÑÐ°Ñ ÑоÑÐºÑ ÑинÑ
ÑонизаÑии в конвейеÑе, или когда вÑзÑваеÑÑÑ PQflush. РконвейеÑном Ñежиме Ñакже ÑабоÑаÑÑ ÑÑнкÑии PQsendPrepare, PQsendDescribePrepared, PQsendDescribePortal, PQsendClosePrepared и PQsendClosePortal. ÐбÑабоÑка ÑезÑлÑÑаÑов опиÑана ниже.
СеÑÐ²ÐµÑ Ð²ÑполнÑÐµÑ Ð¾Ð¿ÐµÑаÑоÑÑ Ð¸ в поÑÑдке иÑ
поÑÑÑÐ¿Ð»ÐµÐ½Ð¸Ñ Ð¾Ñ ÐºÐ»Ð¸ÐµÐ½Ñа возвÑаÑÐ°ÐµÑ ÑезÑлÑÑаÑÑ. СеÑÐ²ÐµÑ Ð½Ð°ÑнÑÑ Ð²ÑполнÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð² конвейеÑе немедленно, не дожидаÑÑÑ ÐºÐ¾Ð½Ñа конвейеÑа. ÐбÑаÑиÑе внимание, ÑÑо ÑезÑлÑÑаÑÑ Ð±ÑÑеÑизÑÑÑÑÑ Ð½Ð° ÑÑоÑоне ÑеÑвеÑа; ÑеÑÐ²ÐµÑ ÑбÑаÑÑÐ²Ð°ÐµÑ ÑÑÐ¾Ñ Ð±ÑÑеÑ, когда ÑÑнкÑией PQpipelineSync или PQsendPipelineSync ÑÑÑанавливаеÑÑÑ ÑоÑка ÑинÑ
ÑонизаÑии или когда вÑзÑваеÑÑÑ ÑÑнкÑÐ¸Ñ PQsendFlushRequest. ÐÑли пÑи вÑполнении какого-либо опеÑаÑоÑа Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÐµÑ Ð¾Ñибка, ÑеÑÐ²ÐµÑ Ð¿ÑеÑÑÐ²Ð°ÐµÑ ÑекÑÑÑÑ ÑÑанзакÑÐ¸Ñ Ð¸ не вÑполнÑÐµÑ Ð½Ð¸ÐºÐ°ÐºÑÑ ÑледÑÑÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð² оÑеÑеди до ÑледÑÑÑей ÑоÑки ÑинÑ
ÑонизаÑии; Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ Ñакой ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð²ÑдаÑÑÑÑ ÑезÑлÑÑÐ°Ñ PGRES_PIPELINE_ABORTED. (ÐÑо ÑпÑаведливо и Ñогда, когда в конвейеÑе пеÑедаÑÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ, коÑоÑÑе могли Ð±Ñ Ð¾ÑкаÑиÑÑ ÑÑанзакÑиÑ.) ÐбÑабоÑка запÑоÑа возобновлÑеÑÑÑ Ð¿Ð¾Ñле ÑоÑки ÑинÑ
ÑонизаÑии.
Ðдна опеÑаÑÐ¸Ñ Ð²Ð¿Ð¾Ð»Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð·Ð°Ð²Ð¸ÑеÑÑ Ð¾Ñ ÑезÑлÑÑаÑов пÑедÑдÑÑей; напÑимеÑ, в одном запÑоÑе Ð¼Ð¾Ð¶ÐµÑ ÑоздаваÑÑÑÑ ÑаблиÑа, коÑоÑÑÑ Ð±ÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑ ÑледÑÑÑий запÑÐ¾Ñ Ð² Ñом же конвейеÑе. ТоÑно Ñак же пÑиложение Ð¼Ð¾Ð¶ÐµÑ ÑоздаÑÑ Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð½Ñй подгоÑовленнÑй опеÑаÑÐ¾Ñ Ð¸ вÑполниÑÑ ÐµÐ³Ð¾ Ñ Ð¿Ð¾ÑледÑÑÑими опеÑаÑоÑами в Ñом же конвейеÑе.
32.5.1.2. ÐбÑабоÑка ÑезÑлÑÑаÑов #
ЧÑÐ¾Ð±Ñ Ð¾Ð±ÑабоÑаÑÑ ÑезÑлÑÑÐ°Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ запÑоÑа в конвейеÑе, пÑиложение многокÑаÑно вÑзÑÐ²Ð°ÐµÑ PQgetResult и обÑабаÑÑÐ²Ð°ÐµÑ ÐºÐ°Ð¶Ð´Ñй ÐµÑ ÑезÑлÑÑаÑ, пока PQgetResult не вÑдаÑÑ NULL. ÐаÑем Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÑÑен ÑезÑлÑÑÐ°Ñ ÑледÑÑÑего запÑоÑа в конвейеÑе, Ñакже Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ PQgetResult, и веÑÑ Ñикл повÑоÑÑеÑÑÑ. РезÑлÑÑаÑÑ Ð¾ÑделÑнÑÑ
запÑоÑов пÑиложение обÑабаÑÑÐ²Ð°ÐµÑ Ð¾Ð±ÑÑнÑм обÑазом. ÐоÑле Ñого, как бÑдÑÑ Ð²ÑÐ´Ð°Ð½Ñ ÑезÑлÑÑаÑÑ Ð²ÑеÑ
запÑоÑов в конвейеÑе, PQgetResult вÑдаÑÑ ÑезÑлÑÑÐ°Ñ Ñо знаÑением ÑÑаÑÑÑа PGRES_PIPELINE_SYNC.
ÐÐ»Ð¸ÐµÐ½Ñ Ð¼Ð¾Ð¶ÐµÑ Ð¾ÑложиÑÑ Ð¾Ð±ÑабоÑÐºÑ ÑезÑлÑÑаÑов до ÑÐµÑ Ð¿Ð¾Ñ, пока веÑÑ ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑ Ð½Ðµ бÑÐ´ÐµÑ Ð¾ÑпÑавлен, или ÑеÑедоваÑÑ ÐµÑ Ñ Ð¾ÑпÑавкой далÑнейÑÐ¸Ñ Ð·Ð°Ð¿ÑоÑов в конвейеÑе; Ñм. ÐодÑаздел 32.5.1.4.
ФÑнкÑÐ¸Ñ PQgetResult ÑабоÑÐ°ÐµÑ Ñак же, как и пÑи обÑÑной аÑинÑ
Ñонной обÑабоÑке, но Ð¼Ð¾Ð¶ÐµÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑно вÑдаваÑÑ ÑезÑлÑÑаÑÑ Ð½Ð¾Ð²ÑÑ
Ñипов PGRES_PIPELINE_SYNC и PGRES_PIPELINE_ABORTED. PGRES_PIPELINE_SYNC вÑдаÑÑÑÑ Ñовно один Ñаз Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ вÑзова PQpipelineSync или PQsendPipelineSync в ÑооÑвеÑÑÑвÑÑÑей ÑоÑке конвейеÑа. PGRES_PIPELINE_ABORTED вÑдаÑÑÑÑ Ð²Ð¼ÐµÑÑо обÑÑного ÑезÑлÑÑаÑа запÑоÑа Ð´Ð»Ñ Ð¿ÐµÑвой оÑибки и вÑеÑ
поÑледÑÑÑиÑ
ÑезÑлÑÑаÑов до ÑледÑÑÑего PGRES_PIPELINE_SYNC; Ñм. ÐодÑаздел 32.5.1.3.
ФÑнкÑии PQisBusy, PQconsumeInput и Ñ. п. ÑабоÑаÑÑ ÐºÐ°Ðº обÑÑно пÑи обÑабоÑке ÑезÑлÑÑаÑов конвейеÑа. Ð ÑаÑÑноÑÑи, вÑзов PQisBusy в ÑеÑедине конвейеÑа возвÑаÑÐ°ÐµÑ 0, еÑли бÑли обÑабоÑÐ°Ð½Ñ ÑезÑлÑÑаÑÑ Ð²ÑеÑ
вÑполненнÑÑ
на даннÑй Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð·Ð°Ð¿ÑоÑов.
libpq не пÑедоÑÑавлÑÐµÑ Ð¿ÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ð¸ÐºÐ°ÐºÐ¾Ð¹ инÑоÑмаÑии о запÑоÑе, обÑабаÑÑваемом в даннÑй Ð¼Ð¾Ð¼ÐµÐ½Ñ (за иÑклÑÑением Ñого, ÑÑо PQgetResult возвÑаÑÐ°ÐµÑ NULL, ÑÑÐ¾Ð±Ñ ÑказаÑÑ, ÑÑо далее вÑдаÑÑÑÑ ÑезÑлÑÑаÑÑ ÑледÑÑÑего запÑоÑа). ÐÑиложение должно оÑÑлеживаÑÑ Ð¿Ð¾ÑÑдок оÑпÑавки запÑоÑов, ÑÑÐ¾Ð±Ñ ÑвÑзаÑÑ Ð¸Ñ
Ñ ÑооÑвеÑÑÑвÑÑÑими ÑезÑлÑÑаÑами. ÐÐ»Ñ ÑÑого пÑиложение обÑÑно иÑполÑзÑÐµÑ ÐºÐ¾Ð½ÐµÑнÑй авÑÐ¾Ð¼Ð°Ñ Ð¸Ð»Ð¸ оÑеÑедÑ.
32.5.1.3. ÐбÑабоÑка оÑибок #
С ÑоÑки зÑÐµÐ½Ð¸Ñ ÐºÐ»Ð¸ÐµÐ½Ñа, поÑле Ñого, как PQresultStatus возвÑаÑÐ°ÐµÑ PGRES_FATAL_ERROR, ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑ Ð¿Ð¾Ð¼ÐµÑаеÑÑÑ ÐºÐ°Ðº неÑабоÑий. PQresultStatus бÑÐ´ÐµÑ Ð²ÑдаваÑÑ ÑезÑлÑÑÐ°Ñ PGRES_PIPELINE_ABORTED Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ оÑÑавÑейÑÑ Ð² оÑеÑеди опеÑаÑии в неÑабоÑем конвейеÑе. ФÑнкÑÐ¸Ñ PQpipelineSync или PQsendPipelineSync вÑдаÑÑ ÑезÑлÑÑÐ°Ñ PGRES_PIPELINE_SYNC, ÑигнализиÑÑÑ Ð¾ возвÑаÑении конвейеÑа в ÑабоÑее ÑоÑÑоÑние и возобновлении ноÑмалÑной обÑабоÑки ÑезÑлÑÑаÑов.
ÐÐ»Ð¸ÐµÐ½Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ обÑабаÑÑваÑÑ ÑезÑлÑÑаÑÑ, вÑзÑÐ²Ð°Ñ PQgetResult во вÑÐµÐ¼Ñ Ð²Ð¾ÑÑÑÐ°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñле оÑибки.
ÐÑли в конвейеÑе пеÑедавалаÑÑ Ð½ÐµÑÐ²Ð½Ð°Ñ ÑÑанзакÑиÑ, Ñо опеÑаÑии, коÑоÑÑе Ñже бÑли вÑполненÑ, оÑкаÑÑваÑÑÑÑ, а опеÑаÑии, коÑоÑÑе бÑли поÑÑÐ°Ð²Ð»ÐµÐ½Ñ Ð² оÑеÑÐµÐ´Ñ Ð¿Ð¾Ñле неÑдаÑной опеÑаÑии, полноÑÑÑÑ Ð¿ÑопÑÑкаÑÑÑÑ. То же Ñамое пÑоиÑÑ
одиÑ, еÑли в конвейеÑе запÑÑкаеÑÑÑ Ð¸ ÑикÑиÑÑеÑÑÑ Ð¾Ð´Ð½Ð° ÑÐ²Ð½Ð°Ñ ÑÑанзакÑÐ¸Ñ (Ñ. е. пеÑвÑй опеÑаÑÐ¾Ñ â BEGIN, а поÑледний â COMMIT), за иÑклÑÑением Ñого, ÑÑо ÑÐµÐ°Ð½Ñ Ð¾ÑÑаÑÑÑÑ Ð² ÑоÑÑоÑнии пÑеÑванной ÑÑанзакÑии в конÑе конвейеÑа. ÐÑли ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑ ÑодеÑÐ¶Ð¸Ñ Ð½ÐµÑколÑко ÑвнÑÑ
ÑÑанзакÑий, вÑе ÑÑанзакÑии, заÑикÑиÑованнÑе до оÑибки, оÑÑаÑÑÑÑ Ð·Ð°ÑикÑиÑованнÑми, ÑекÑÑÐ°Ñ ÑÑанзакÑÐ¸Ñ Ð¿ÑеÑÑваеÑÑÑ, а вÑе поÑледÑÑÑие опеÑаÑии полноÑÑÑÑ Ð¿ÑопÑÑкаÑÑÑÑ, вклÑÑÐ°Ñ ÑÑанзакÑии. ÐÑли вÑполнÑеÑÑÑ ÑоÑка ÑинÑ
ÑонизаÑии, когда ÑвнÑй блок ÑÑанзакÑии наÑ
одиÑÑÑ Ð² пÑеÑванном ÑоÑÑоÑнии, ÑледÑÑÑий ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑ ÑÑÐ°Ð·Ñ Ð¶Ðµ ÑÑановиÑÑÑ Ð½ÐµÑабоÑим, еÑли ÑледÑÑÑÐ°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð° (ROLLBACK) не пеÑеклÑÑÐ°ÐµÑ ÐµÐ³Ð¾ в обÑÑнÑй Ñежим.
ÐÑимеÑание
ÐÐ»Ð¸ÐµÐ½Ñ Ð½Ðµ должен ÑаÑÑÑиÑÑваÑÑ Ð½Ð° Ñо, ÑÑо вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð½Ð°Ñ ÑабоÑа заÑикÑиÑована ÑÑÐ°Ð·Ñ Ð¿Ð¾Ñле Ñого, как бÑл оÑпÑавлен COMMIT; ÑолÑко полÑÑение ÑооÑвеÑÑÑвÑÑÑего ÑезÑлÑÑаÑа даÑÑ ÑакÑÑ Ð³Ð°ÑанÑиÑ. ÐоÑколÑÐºÑ Ð¾Ñибки поÑÑÑпаÑÑ Ð°ÑинÑ
Ñонно, пÑиложение должно ÑмеÑÑ Ð²Ð¾Ð·Ð²ÑаÑаÑÑÑÑ Ðº моменÑÑ Ð¿Ð¾Ñледнего подÑвеÑждÑнного заÑикÑиÑованного Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸ повÑоÑно оÑпÑавлÑÑÑ ÑабоÑÑ, вÑполненнÑÑ Ð¿Ð¾Ñле ÑÑого моменÑа, еÑли ÑÑо-Ñо пойдÑÑ Ð½Ðµ Ñак.
32.5.1.4. ЧеÑедование обÑабоÑки ÑезÑлÑÑаÑов и оÑпÑавки запÑоÑов #
Ðо избежание взаимоблокиÑовок Ñ Ð±Ð¾Ð»ÑÑими конвейеÑами, ÐºÐ»Ð¸ÐµÐ½Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ бÑÑÑ Ð¿Ð¾ÑÑÑоен вокÑÑг неблокиÑÑÑÑего Ñикла ÑобÑÑий, Ñеализованного Ñ Ð¸ÑполÑзованием ÑакиÑ
меÑ
анизмов опеÑаÑионной ÑиÑÑемÑ, как select, poll, WaitForMultipleObjectEx и Ñ. д.
ÐлиенÑÑкое пÑиложение, как пÑавило, должно поддеÑживаÑÑ Ð¾ÑеÑÐµÐ´Ñ ÐµÑÑ Ð½Ðµ оÑпÑавленной ÑабоÑÑ Ð¸ оÑеÑÐµÐ´Ñ ÑабоÑÑ, коÑоÑÐ°Ñ Ñже оÑпÑавлена, но ÐµÑ ÑезÑлÑÑаÑÑ ÐµÑÑ Ð½Ðµ обÑабоÑанÑ. Ðогда ÑÐ¾ÐºÐµÑ Ð´Ð¾ÑÑÑпен Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи, в него ÑледÑÐµÑ Ð¾ÑпÑавлÑÑÑ Ð¾ÑеÑедной обÑÑм ÑабоÑÑ. Ðогда он доÑÑÑпен Ð´Ð»Ñ ÑÑениÑ, из него ÑледÑÐµÑ Ð¿ÑоÑиÑаÑÑ Ð¸ обÑабоÑаÑÑ ÑезÑлÑÑаÑÑ, ÑопоÑÑавив Ð¸Ñ Ñо ÑледÑÑÑей запиÑÑÑ Ð² оÑеÑеди Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ ÑезÑлÑÑаÑов. ÐÑли обÑÑм памÑÑи позволÑеÑ, ÑезÑлÑÑаÑÑ ÑледÑÐµÑ ÑиÑаÑÑ Ð´Ð¾ÑÑаÑоÑно ÑаÑÑо â дожидаÑÑÑÑ Ð¾ÐºÐ¾Ð½ÑÐ°Ð½Ð¸Ñ ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑа не ÑÑебÑеÑÑÑ. ÐонвейеÑÑ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð¾Ð³ÑаниÑÐµÐ½Ñ Ð»Ð¾Ð³Ð¸ÑеÑкими единиÑами ÑабоÑÑ, обÑÑно (но не обÑзаÑелÑно) по одной ÑÑанзакÑии на конвейеÑ. ÐÐµÑ Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ÑÑи вÑÑ Ð¾Ð´Ð¸ÑÑ Ð¸Ð· конвейеÑного Ñежима и возвÑаÑаÑÑÑÑ Ð² него Ð¼ÐµÐ¶Ð´Ñ ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑами, Ñак же как не нÑжно дожидаÑÑÑÑ Ð·Ð°Ð²ÐµÑÑÐµÐ½Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ конвейеÑе, пÑежде Ñем пеÑедаваÑÑ ÑабоÑÑ Ð² дÑÑгой.
32.5.2. ФÑнкÑии, ÑвÑзаннÑе Ñ ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑнÑм Ñежимом #
PQpipelineStatus#ÐозвÑаÑÐ°ÐµÑ ÑекÑÑее ÑоÑÑоÑние конвейеÑного Ñежима Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑÑÐµÐ½Ð¸Ñ libpq.
PGpipelineStatus PQpipelineStatus(const PGconn *conn);
PQpipelineStatusÐ¼Ð¾Ð¶ÐµÑ Ð²ÑдаваÑÑ Ð¾Ð´Ð½Ð¾ из ÑледÑÑÑÐ¸Ñ Ð·Ð½Ð°Ñений:-
PQ_PIPELINE_ON ÐодклÑÑение libpq Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð² конвейеÑном Ñежиме.
-
PQ_PIPELINE_OFF ÐодклÑÑение libpq не Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð² конвейеÑном Ñежиме.
-
PQ_PIPELINE_ABORTED Соединение libpq Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð² конвейеÑном Ñежиме, и пÑи обÑабоÑке ÑекÑÑего конвейеÑа пÑоизоÑла оÑибка. Флаг пÑеÑÑÐ²Ð°Ð½Ð¸Ñ ÑбÑаÑÑваеÑÑÑ, когда
PQgetResultвозвÑаÑÐ°ÐµÑ ÑезÑлÑÑÐ°Ñ ÑипаPGRES_PIPELINE_SYNC.
-
PQenterPipelineMode#ÐеÑÐµÐ²Ð¾Ð´Ð¸Ñ Ð¿Ð¾Ð´ÐºÐ»ÑÑение в конвейеÑнÑй Ñежим, еÑли оно в даннÑй Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð² Ñежиме Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ Ñже Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð² конвейеÑном Ñежиме.
int PQenterPipelineMode(PGconn *conn);
ÐозвÑаÑÐ°ÐµÑ 1 в ÑлÑÑае ÑÑÐ¿ÐµÑ Ð°. ÐозвÑаÑÐ°ÐµÑ 0 и ниÑего не делаеÑ, еÑли Ñоединение в наÑÑоÑÑий Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð½Ðµ пÑоÑÑаиваеÑ, Ñ. е. еÑли Ñ Ð½ÐµÐ³Ð¾ еÑÑÑ Ð³Ð¾ÑовÑй ÑезÑлÑÑаÑ, или оно Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ Ð¿Ð¾ÑÑÑÐ¿Ð»ÐµÐ½Ð¸Ñ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑÑ Ð´Ð°Ð½Ð½ÑÑ Ð¾Ñ ÑеÑвеÑа и Ñ. д. ÐÑа ÑÑнкÑÐ¸Ñ Ð½Ð° Ñамом деле ниÑего не оÑпÑавлÑÐµÑ ÑеÑвеÑÑ, а пÑоÑÑо изменÑÐµÑ ÑоÑÑоÑние ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ libpq.
PQexitPipelineMode#ÐÑÐ²Ð¾Ð´Ð¸Ñ Ð¿Ð¾Ð´ÐºÐ»ÑÑение из конвейеÑного Ñежима, еÑли подклÑÑение Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð² нÑм и его оÑеÑеди пÑÑÑÑ.
int PQexitPipelineMode (PGconn * conn);
ÐозвÑаÑÐ°ÐµÑ 1 в ÑлÑÑае ÑÑÐ¿ÐµÑ Ð°. Ðе в конвейеÑном Ñежиме возвÑаÑÐ°ÐµÑ 1 и не вÑполнÑÐµÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ñ Ð´ÐµÐ¹ÑÑвий. ÐÑли обÑабоÑка ÑекÑÑего опеÑаÑоÑа не завеÑÑена или
PQgetResultне бÑла вÑзвана Ð´Ð»Ñ ÑбоÑа ÑезÑлÑÑаÑов вÑÐµÑ Ñанее оÑпÑавленнÑÑ Ð·Ð°Ð¿ÑоÑов, возвÑаÑÐ°ÐµÑ 0 (в ÑÑом ÑлÑÑае иÑполÑзÑйÑеPQerrorMessage, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¾ пÑоблеме).PQpipelineSync#ÐÑмеÑÐ°ÐµÑ ÑоÑÐºÑ ÑÐ¸Ð½Ñ ÑонизаÑии в конвейеÑе, оÑпÑавлÑÑ ÑообÑение ÑÐ¸Ð½Ñ ÑонизаÑии и оÑиÑÐ°Ñ Ð±ÑÑÐµÑ Ð¾ÑпÑавки. ÐÑа ÑоÑка ÑлÑÐ¶Ð¸Ñ Ð¾Ð³ÑаниÑиÑелем неÑвной ÑÑанзакÑии и ÑоÑкой воÑÑÑÐ°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñле оÑибки; Ñм. ÐодÑаздел 32.5.1.3.
int PQpipelineSync(PGconn *conn);
ÐозвÑаÑÐ°ÐµÑ 1 в ÑлÑÑае ÑÑÐ¿ÐµÑ Ð°. ÐозвÑаÑÐ°ÐµÑ 0, еÑли Ñоединение не Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð² конвейеÑном Ñежиме или ÑообÑение ÑÐ¸Ð½Ñ ÑонизаÑии оÑпÑавиÑÑ Ð½Ðµ ÑдалоÑÑ.
PQsendPipelineSync#ÐÑмеÑÐ°ÐµÑ ÑоÑÐºÑ ÑÐ¸Ð½Ñ ÑонизаÑии в конвейеÑе, оÑпÑавлÑÑ ÑообÑение ÑÐ¸Ð½Ñ ÑонизаÑии, но не оÑиÑÐ°Ñ Ð±ÑÑÐµÑ Ð¾ÑпÑавки. ÐÑа ÑоÑка ÑлÑÐ¶Ð¸Ñ Ð¾Ð³ÑаниÑиÑелем неÑвной ÑÑанзакÑии и ÑоÑкой воÑÑÑÐ°Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñле оÑибки; Ñм. ÐодÑаздел 32.5.1.3.
int PQsendPipelineSync(PGconn *conn);
ÐозвÑаÑÐ°ÐµÑ 1 в ÑлÑÑае ÑÑÐ¿ÐµÑ Ð°. ÐозвÑаÑÐ°ÐµÑ 0, еÑли Ñоединение не Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð² конвейеÑном Ñежиме или ÑообÑение ÑÐ¸Ð½Ñ ÑонизаÑии оÑпÑавиÑÑ Ð½Ðµ ÑдалоÑÑ. ÐбÑаÑиÑе внимание, ÑÑо ÑообÑение не ÑÐ¾Ñ ÑанÑеÑÑÑ Ð½Ð° ÑеÑвеÑе авÑомаÑиÑеÑки. ÐÑи Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ÑÑи иÑполÑзÑйÑе ÑÑнкÑиÑ
PQflush.PQsendFlushRequest#ÐÑпÑавлÑÐµÑ ÑеÑвеÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ ÑбÑоÑиÑÑ ÐµÐ³Ð¾ бÑÑÐµÑ Ð²Ñвода.
int PQsendFlushRequest(PGconn *conn);
ÐозвÑаÑÐ°ÐµÑ 1 в ÑлÑÑае ÑÑÐ¿ÐµÑ Ð°. ÐозвÑаÑÐ°ÐµÑ 0 в ÑлÑÑае лÑбой оÑибки.
СеÑÐ²ÐµÑ ÑбÑаÑÑÐ²Ð°ÐµÑ Ñвой бÑÑÐµÑ Ð²Ñвода авÑомаÑиÑеÑки, когда вÑзÑваеÑÑÑ
PQpipelineSyncили пеÑедаÑÑÑÑ Ð»Ñбой запÑÐ¾Ñ Ð½Ðµ в конвейеÑном Ñежиме; ÑÑа ÑÑнкÑÐ¸Ñ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð° в конвейеÑном Ñежиме: она позволÑÐµÑ ÑбÑоÑиÑÑ ÑеÑвеÑнÑй бÑÑеÑ, не ÑÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°Ñ ÑоÑÐºÑ ÑÐ¸Ð½Ñ ÑонизаÑии. ÐбÑаÑиÑе внимание, ÑÑо Ñам ÑÑÐ¾Ñ Ð·Ð°Ð¿ÑÐ¾Ñ Ð½Ðµ пеÑедаÑÑÑÑ ÑеÑвеÑÑ Ð°Ð²ÑомаÑиÑеÑки; ÑÑÐ¾Ð±Ñ Ð¿ÐµÑедаÑÑ ÐµÐ³Ð¾ немедленно, вÑзовиÑеPQflush.
32.5.3. Ðогда иÑполÑзоваÑÑ ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑнÑй Ñежим #
Ðак и в ÑлÑÑае Ñ Ð°ÑÐ¸Ð½Ñ ÑоннÑм Ñежимом запÑоÑов, пÑи иÑполÑзовании конвейеÑного Ñежима Ð½ÐµÑ Ð·Ð½Ð°ÑиÑелÑнÑÑ Ð¸Ð·Ð´ÐµÑжек пÑоизводиÑелÑноÑÑи. ÐÑполÑзование конвейеÑного Ñежима ÑвелиÑÐ¸Ð²Ð°ÐµÑ ÑложноÑÑÑ ÐºÐ»Ð¸ÐµÐ½ÑÑкого пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸ ÑÑебÑÐµÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑной оÑÑоÑожноÑÑи во избежание взаимоблокиÑовок клиенÑ-ÑеÑвеÑ, но Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑедложиÑÑ Ð·Ð½Ð°ÑиÑелÑное ÑлÑÑÑение пÑоизводиÑелÑноÑÑи в обмен на ÑвелиÑение обÑÑма иÑполÑзÑемой памÑÑи из-за более длиÑелÑного вÑÑ Ð¾Ð´Ð° из ÑоÑÑоÑниÑ.
ÐонвейеÑнÑй Ñежим наиболее полезен, когда ÑеÑÐ²ÐµÑ Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑÑ Ð½Ð° болÑÑом ÑаÑÑÑоÑнии Ð¾Ñ ÐºÐ»Ð¸ÐµÐ½Ñа, Ñ. е. когда ÑеÑÐµÐ²Ð°Ñ Ð·Ð°Ð´ÐµÑжка («ping time») велика, а Ñакже когда много неболÑÑÐ¸Ñ Ð¾Ð¿ÐµÑаÑий вÑполнÑÑÑÑÑ Ð² бÑÑÑÑой поÑледоваÑелÑноÑÑи. Ðак пÑавило, иÑполÑзование конвейеÑнÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´ даÑÑ Ð¼ÐµÐ½ÑÑе пÑеимÑÑеÑÑв, когда вÑполнение каждого запÑоÑа Ð·Ð°Ð½Ð¸Ð¼Ð°ÐµÑ Ð² неÑколÑко Ñаз болÑÑе вÑемени, Ñем пеÑедаÑа даннÑÑ ÐºÐ»Ð¸ÐµÐ½Ñ-ÑеÑÐ²ÐµÑ Ð¸ обÑаÑно. ÐпеÑаÑÐ¸Ñ Ð¸Ð· 100 опеÑаÑоÑов, вÑполнÑÐµÐ¼Ð°Ñ Ð½Ð° ÑеÑвеÑе за 300 миллиÑекÑнд, без конвейеÑизаÑии займÑÑ 30 ÑекÑнд из-за одной ÑолÑко ÑеÑевой задеÑжки; Ñ ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑизаÑией Ð´Ð°Ð½Ð½Ð°Ñ Ð¾Ð¿ÐµÑаÑÐ¸Ñ Ð¿Ð¾ÑÑаÑÐ¸Ñ Ð½Ðµ более 0,3 ÑекÑÐ½Ð´Ñ Ð½Ð° ожидание ÑезÑлÑÑаÑов Ð¾Ñ ÑеÑвеÑа.
ÐÑполÑзÑйÑе конвейеÑнÑе командÑ, когда ваÑе пÑиложение вÑполнÑÐµÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑво неболÑÑиÑ
опеÑаÑий INSERT, UPDATE и DELETE, коÑоÑÑе нелегко пÑеобÑазоваÑÑ Ð² набоÑÑ Ð¾Ð¿ÐµÑаÑий или в опеÑаÑÐ¸Ñ COPY.
ÐонвейеÑнÑй Ñежим беÑполезен, когда инÑоÑмаÑÐ¸Ñ Ð¸Ð· одной опеÑаÑии ÑÑебÑеÑÑÑ ÐºÐ»Ð¸ÐµÐ½ÑÑ Ð´Ð»Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÑледÑÑÑей опеÑаÑии. Ð ÑÐ°ÐºÐ¸Ñ ÑлÑÑаÑÑ ÐºÐ»Ð¸ÐµÐ½ÑÑ Ð¿ÑидÑÑÑÑ Ð²Ð²ÐµÑÑи ÑоÑÐºÑ ÑÐ¸Ð½Ñ ÑонизаÑии и дождаÑÑÑÑ Ð¿Ð¾Ð»Ð½Ð¾Ð³Ð¾ Ñикла пеÑедаÑи даннÑÑ ÐºÐ»Ð¸ÐµÐ½Ñ-ÑеÑвеÑ, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ ÑÑебÑемÑе ÑезÑлÑÑаÑÑ. Ðднако ÑаÑÑо можно наÑÑÑоиÑÑ ÐºÐ»Ð¸ÐµÐ½Ñ Ð´Ð»Ñ Ð¾Ð±Ð¼ÐµÐ½Ð° Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾Ð¹ инÑоÑмаÑией на ÑÑоÑоне ÑеÑвеÑа. Ð¦Ð¸ÐºÐ»Ñ ÑÑениÑ-изменениÑ-запиÑи оÑобенно Ñ Ð¾ÑоÑо Ð¿Ð¾Ð´Ñ Ð¾Ð´ÑÑ Ð´Ð»Ñ Ñакой наÑÑÑойки; напÑимеÑ:
BEGIN; SELECT x FROM mytable WHERE id = 42 FOR UPDATE; -- result: x=2 -- client adds 1 to x: UPDATE mytable SET x = 3 WHERE id = 42; COMMIT;
можно гоÑаздо ÑÑÑекÑивнее ÑделаÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ:
UPDATE mytable SET x = x + 1 WHERE id = 42;
ÐонвейеÑизаÑÐ¸Ñ Ð¼ÐµÐ½ÐµÐµ полезна и более Ñложна, когда один ÐºÐ¾Ð½Ð²ÐµÐ¹ÐµÑ ÑодеÑÐ¶Ð¸Ñ Ð½ÐµÑколÑко ÑÑанзакÑий (Ñм. ÐодÑаздел 32.5.1.3).
[15] ÐÐ»Ð¸ÐµÐ½Ñ Ð¼Ð¾Ð¶ÐµÑ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸ÑоваÑÑÑÑ, пÑÑаÑÑÑ Ð¿ÐµÑедаÑÑ Ð·Ð°Ð¿ÑоÑÑ ÑеÑвеÑÑ, а ÑеÑÐ²ÐµÑ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸ÑÑеÑÑÑ, пÑÑаÑÑÑ Ð²ÑдаÑÑ ÐºÐ»Ð¸ÐµÐ½ÑÑ ÑезÑлÑÑаÑÑ Ñже вÑполненнÑÑ Ð·Ð°Ð¿ÑоÑов. ÐÑо возможно, ÑолÑко когда ÐºÐ»Ð¸ÐµÐ½Ñ Ð¿ÐµÑедаÑÑ Ñак много запÑоÑов, ÑÑо заполнÑÐµÑ Ð¸ Ñвой вÑÑ Ð¾Ð´Ð½Ð¾Ð¹ бÑÑеÑ, и Ð²Ñ Ð¾Ð´Ð½Ð¾Ð¹ бÑÑÐµÑ ÑеÑвеÑа, и ÑолÑко заÑем пеÑеклÑÑаеÑÑÑ Ð½Ð° обÑабоÑÐºÑ Ð¿ÐµÑедаваемÑÑ ÑеÑвеÑом ÑезÑлÑÑаÑов, но пÑедÑказаÑÑ, когда ÑоÑно ÑÑо пÑоизойдÑÑ, Ñложно.