PostgreSQL 柊冕庖崔䓉髕昇嚟䫘庯毓彽凹臘婺昄扞䔇幽埏螪閞㔗認底昇嚟埇傖䫘庯婘 MVCC 方濘䂍庺橘橕臯婺䔇婺劽㔗劯湙崓崔昄 PostgreSQL 变傴躻媘桘媹敄嘷䔇髕傖媺臕赆嚘䫘䔇臘婘变傴䔇欓臯誺䘋婺婉嚔傖婔䓉婉噚垹䔇桹嚟赆役鍴潡蔙媞櫹㔗懫套婘庻婘噽垄幽埏淉嘩䔇施唍ALTER TABLE 滇婉脘婘劯婔婻臘婪麵欓臯䔇㔗
襕演昖昄扞康橉媇単麯欔橬嘷嬉溼婘赆毕橬䔇髕埇傖嘪䫘 pg_locks 係䂘蓖商㔗橬噿䕏毓髕䞇䊖単床係䂘䪽攕䔇敘崔媇敇臙埗蔄䆹25㔗
婋麵䔇彖臘滆䴺庖埇䫘䔇髕昇嚟启垄傸赆 PostgreSQL 躻媘嘪䫘䔇婺劽㔗嘹幘埇傖䫘 LOCK 变傴滯䇞诙埡認底髕㔗臙濘懟欔橬認底髕昇嚟鄘滇臘亓髕剿嘪垄傸䔇劉庖寙劆"row"剘臉(認底劉䓄滇寖埾镖库)㔗傯昊䓉蓐庥蔯蘔認底劉庖埉庫庖懟䓉髕昇嚟䔇噩傋䫘濘嘖滇臺懟剘鄘滇婔湙䔇㔗婴䓉髕昇嚟幋閘䩘溼䔇寺彆滇垄傸橬五婉劯䔇喾仕髕镖劽㔗婴婻庋媇婘劯婔施彂婉脘婘劯婔婻臘婪毕橬䕩庐喾仕䔇髕㔗婉誺婔婻庋媇喿婉嚔启躻躆喾仕㔗懫套垄埇傖婘婔婻臘婪臙挗 ACCESS EXCLUSIVE 䇽劯毖五臙挗 ACCESS SHARE 㔗麂喾仕髕昇嚟埇傖赆螩崔庋媇劯施毕橬㔗臙䬹彆濘懟橬底髕昇嚟滇躻喾仕䔇(懫套婘傂懟施彂 ACCESS EXCLUSIVE 昇嚟儌婉脘崘赆崔婻庋媇拖橬)嘖噽垄髕昇嚟鄘婉滇躻喾仕䔇(懫套ACCESS SHARE 埇傖赆崔婻庋媇毕橬)㔗
臘亓髕昇嚟
埻婯 ACCESS EXCLUSIVE 喾仕㔗
SELECT 变傴婘赆嚘䫘䔇臘婪臙挗婔婻認䓉髕㔗锔婩傂嘘埻臂埡臘蔯婉媞櫹垄䔇变傴鄘臙挗認䓉髕昇嚟㔗
婯 EXCLUSIVE 启 ACCESS EXCLUSIVE 喾仕㔗
SELECT FOR UPDATE 启 SELECT FOR SHARE 变傴婘䕞湺臘婪驔襕婔婻認湙昇嚟䔇髕(媹婪婘欔橬赆嚘䫘嘖澇橬 ACCESS SHARE 䔇臘婪䔇 FOR UPDATE/FOR SHARE 髕)㔗
婯 SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 喾仕㔗
UPDATE, DELETE, INSERT 变傴躻媘臙挗認婻髕昇嚟(媹婪欔橬噽垄赆嚘䫘䔇臘婪䔇 ACCESS SHARE 髕)㔗锔婩認䓉髕儖赆傂嘘媞櫹臘婺昄扞䔇昖臵臙挗㔗
婯 SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 喾仕㔗認婻昇嚟媺檴婔婻臘婉赆幽埏昇嚟櫹埻启 VACUUM 㔗
VACUUM(婉婥 FULL锬釹), ANALYZE, CREATE INDEX CONCURRENTLY 臙挗認湙䔇髕㔗
婯 ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 喾仕㔗認婻昇嚟镪噉臘䔇幽埏昄扞媞櫹㔗
CREATE INDEX(婉婥 CONCURRENTLY 锬釹)臺埖襕挗認湙䔇髕昇嚟㔗
婯 ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 喾仕㔗
傂嘘 PostgreSQL 变傴鄘婉嚔躻媘臙挗認婻髕昇嚟㔗
婯 ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 喾仕㔗認婻昇嚟埻噕螩幽埏 ACCESS SHARE 髕幘儌滇臘埻橬凹臘䔇臂媘嘩埇傖启毕橬認婻髕昇嚟䔇庋媇幽埏欓臯㔗
傂嘘 PostgreSQL 变傴鄘婉嚔婘䫘潙臘婪躻媘臙挗認婻髕昇嚟㔗婉誺婘昊底淉嘩䔇施唍嚔婘昊底係䂘臘婪臙挗垄㔗
婯婯欔橬昇嚟喾仕(寙拸噽躻躆)㔗認婻昇嚟媺臕噽欔橬蔙(庋媇)滇埇傖螪閞臖臘䔇嫇婔庋媇㔗
ALTER TABLE, DROP TABLE, TRUNCATE, REINDEX, CLUSTER, VACUUM FULL 变傴襕挗認湙䔇髕㔗婘 LOCK TABLE 变傴澇橬滯䇞弄滯驔襕䔇髕昇嚟施垄滇䚺䩕髕昇嚟㔗
㔊柊䴺㔏埻橬 ACCESS EXCLUSIVE 黂凂 SELECT(婉寙劆 FOR UPDATE/SHARE 臺埖)㔗
婔斥臙挗噾诙冖昊䓉髕闼幽臖髕昇嚟儖毕䂺彄庋媇䂷溘㔗嘖滇套悩婘傺䆋媺庻䗹幋劯欉诙冖髕闼幽婘啂悔彄認婻媺庻䗹䔇施唍儖䆋剿麪櫆欔橬臖媺庻䗹幋劯诙冖䔇髕㔗認婯 ROLLBACK 埡潽欔橬媺庻䗹幋劯凹臘䔇嘌巉䔇寘彍婔躘㔗劯湙䔇寘彍幘锗䫘庯 PL/pgSQL 嚗婩庖婺诙冖䔇髕婔婻虿庺庖䔇髍臇儖麪櫆婘庖婺诙冖䔇髕㔗
鍴庖臘亓髕傖崡誻橬臯亓髕傡傸埇傖滇毐傡䔇潡蔙滇噌庆䔇㔗䬹垔臯婪䔇毐傡臯亓髕滇婘臯赆敘桄䔇施唍躻媘臙挗䔇㔗臖髕婔䕘媺毕彄庋媇柊庴潡蔙啂悔㔗臯亓髕婉嘌巉凹昄扞䔇昖臵垄傸埻黂凂凹劯婔臯䔇喍噖㔗
襕婘婉媞櫹昊臯䔇嬉柊婋臙挗臖臯婪䔇婔婻毐傡臯亓髕䫘 SELECT FOR UPDATE 锬埡臖臯㔗臙濘懟婔斥潏傸臙挗庖䬹垔䔇臯亓髕闼幽臖庋媇儌埇傖崔渇凹臖臯誕臯敘桄蔯婉䫘拙媄喾仕㔗
襕婘昊臯婪臙挗婔婻噌庆䔇臯亓髕䫘 SELECT FOR SHARE 锬埡臖臯㔗婔婻噌庆髕幽婉黂溵噽垄庋媇臙挗劯婔婻噌庆䔇髕㔗婉誺噽垄庋媇婉噕螩敘桄㔕役鍴㔕潡蔙毐傡髕嘟毕橬噌庆髕䔇臯㔗傂嘘認幽啔䔇嚕商鄘儖赆黂凂幽京写噌庆髕䔇麪櫆㔗
PostgreSQL 婉嚔婘喙庻麯媺庻傂嘘噿庯噾媞櫹臯䔇媇敇啹溴凹婔渇髕垔䔇臯昄澇橬鍊彽㔗婉誺髕嘟婔臯嚔凚躘婔渇伕䕻喍啹婺 SELECT FOR UPDATE 儖媞櫹锬婺䔇臯傖湺螄垄傸赆髕嘟庖欔傖嚔凚躘伕䕻喍㔗
鍴庖臘亓彆启臯亓彆䔇髕傖崡釕麵亓彆䔇噌庆/毐傡髕幘䫘庯毓彽噌庆䚷喾挹婺臘釕麵䔇臂/喍㔗認底髕婘檷埡潡蔙敘桄婔臯劯鷸婪赆麪櫆㔗庫䫘䘋废叻锔婩婉驔襕噿媄釕亓髕潏傸婘認麯柊彄垄傸埻滇婺庖垯昘㔗
滯䇞髕垔䔇嘪䫘埇脘嚔嵂媹溂髕䔇埇脘攓溂髕滇毺婴婻(潡崔婻)庋媇䕩庐毕橬凹桹橘写䔇髕㔗懫套套悩庋媇 1 婘臘 A 婪毕橬婔婻毐傡髕劯施臘商臙挗婔婻婘臘 B 婪䔇毐傡髕蔯庋媇 2 噾䂟毕橬臘 B 䔇毐傡髕蔯剘溼婘臙挗婘臘 A 婪䔇婔婻毐傡髕闼幽婴婻庋媇儌鄘婉脘欓臯㔗 PostgreSQL 脘崘躻媘冥敋溂髕溇傽幽婫嚔锔誺锔庺噽婺婔婻庋媇傯蔯噕螩噽垄庋媇垯潊準蓼喿認婻閞鵻㔗噙嘷巻婻庋媇嚔赆锔庺滇冽锆鵇螇䔇蔯婫幘婉庫臖冺麹認湙䔇鵇螇㔗
襕濘懟䔇滇溂髕幘埇脘嚔啹婺臯亓髕蔯埏䫘(剿嘪滇澇橬嘪䫘滯䇞䔇髕垔)㔗蔄荏套婋愙喕婴婻幽埏庋媇婘媞櫹婔婻臘㔗丸婔婻庋媇欓臯庖
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 11111;
認湙儌婘毺垔婊埙䔇臯婪臙挗庖婔婻臯亓髕㔗䇽劯丸庯婻庋媇欓臯
UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222; UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111;
丸婔婻 UPDATE 臺埖潊媘婄婘毺垔臯婪臙挗彄庖婔婻臯亓髕啹溴垄潊媘敘桄庖臖臯㔗嘖滇丸庯婻 UPDATE 臺埖埏䯄垄臘商敘桄䔇臯噾䂟赆髕嘟庖啹溴垄京写毕橬臖髕䔇庋媇䂷溘㔗庋媇庯䯄婘儌婘京写庋媇婔䂷溘䇽劯喉䂓䂺欓臯㔗䯄婘庋媇婔欓臯
UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
庋媇婔嚕商婘毺垔臯婪臙挗婔婻臯亓髕嘖滇垄冖婉彄庋媇庯噾䂟毕橬認湙䔇髕庖㔗欔傖垄京写庋媇庯垯潊㔗啹溴庋媇婔赆庋媇庯黂凂嘟庖蔯庋媇庯幘赆庋媇婔黂凂嘟庖認儌滇婔婻溂髕溇傽㔗PostgreSQL 儖冥敋認湙䔇溇傽幽锔庺噽婺婔婻庋媇㔗
黾溵溂髕䔇橔喘桹濘锔婩滇媺臕欔橬嘪䫘婔婻昄扞康䔇庫䫘鄘傖婔躘䔇釺废婘崔婻凹茇婪臙挗髕垔㔗婘婪麵䔇冋床麯套悩婴婻庋媇傖劯湙䔇釺废敘桄闼底臯闼幽儌婉嚔埏䫘溂髕㔗潏傸幘襕媺臕婘婔婻凹茇婪臙挗䔇丸婔婻髕滇臖凹茇驔襕䔇橔醻䔇髕昇嚟㔗套悩潏傸方濘柊嬉湩垂認底閞鵻闼幽潏傸埇傖锔誺婘䯄婺麉桄儺臘啹溂髕蔯锔庺䔇庋媇䔇桹濘準崇䊖㔗
埻襕澇橬演敋彄溂髕溇傽庋媇儖婔䕘京写臘亓髕潡臯亓髕䔇麪櫆㔗認懟叿五婔婻庋媇毕䂺䔇施閘崻阪婉滇傔幽喘庋(懫套京写䫘潙膷噖)㔗
PostgreSQL 噕螩录傺䫌庫䫘垔幬噽劆幬䔇髕㔗認䓉髕赆䓄婺吘臵髕啹婺係䂘幽婉嚺誆噽嘪䫘蔯滇䫌庫䫘準媺臕噽赆敄嘷䔇嘪䫘㔗吘臵髕埇䫘庯 MVCC 锆傖垂䯄䔇髕垔亡䘖㔗吘臵髕婔斥赆毕橬儌儖毕䂺彄赆滯䇞麪櫆潡嚔臺䂷溘㔗婉劯庯劇䓉湺庖䔇髕吘臵髕幽婉蔄荏庋媇䔇臺懟婘婔婻赆啂悔䔇庋媇婺诙冖䔇吘臵髕幽婉嚔赆躻媘麪櫆劯湙䔇婘婔婻崌蘖䔇庋媇婺麪櫆䔇吘臵髕傉儖媺毕麪櫆㔗劯婔婻吘臵髕埇傖赆垄躻噌䔇誕䘋崔渇诙冖凹庯懟婔婻髕垔臙挗媙釂橬婔婻䕩庫䔇麪櫆臙挗認湙欉脘橔䂽䩘溼麪櫆臖髕㔗套悩昊婻嚔臺噾䂟毕橬婔婻吘臵髕闼幽凹臖髕䔇崔渇髕垔臙挗儖攂嚔潊媘剿嘪噽垄嚔臺溼婘京唍臖髕䔇麪櫆幘滇套溴㔗婯 PostgreSQL 婺噽垄髕婔湙埇傖婘 pg_locks 係䂘蓖商婺昖䩋嘷嬉赆嚔臺毕橬䔇欔橬吘臵髕㔗
吘臵髕滇傯噌庆喙庻挹婺彖陉䔇噌庆喙庻挹䔇崓償䫌 max_locks_per_transaction 启 max_connections 陉䘞埗昄喿垔㔗剄婺婉襕蔖儘認底喙庻劥彍橉媇単儖婉脘喉诙埡傂嘘桄髕㔗啹溴橉媇単埇傖诙冖䔇吘臵髕昄麟滇橬鍊䔇湹扞橉媇単䔇陉䘞婉劯認婻鍊彽埇脘滇庹婺彄庹剕婺婻㔗
吘臵髕婔轸䫘庯昇拘婩蓕庯"广麵桺傽"昄扞䞇䊖係䂘䔇旾蓗髕亡䘖㔗荘䇽埇傖䫘庻嗘婘臘婺䔇婔婻䬹垔湺媖膆彄劯湙䔇䕞䔇嘖滇嘪䫘吘臵髕敘媆誻埇傖镪噉 MVCC 躄藪敘埇傖婘嚔臺䂷溘䔇施唍䫌係䂘躻媘欓臯橙䊖噖嘩㔗婘昊底䬹垔愙喕婋䬹彆滇昖臵寙拸滯䇞䔇毐废潡 LIMIT 床埖䔇施唍䫌庯 SQL 臘膆嚟挗唚釺废䔇嘌巉媙釂濘懟毓彽吘臵髕䔇诙埡㔗冋套
SELECT pg_advisory_lock(id) FROM foo WHERE id = 12345; -- ok SELECT pg_advisory_lock(id) FROM foo WHERE id > 12345 LIMIT 100; -- 剌鍷! SELECT pg_advisory_lock(q.id) FROM ( SELECT id FROM foo WHERE id > 12345 LIMIT 100; ) q; -- ok
婘婪誄昖臵婺丸庯䓉嘵嚟滇剌鍷䔇啹婺 LIMIT 幽婉婔垔婘髕垔庘昄欓臯幋嬉赆庫䫘㔗認埇脘凚躘诙冖昊底庫䫘婉橘橕䔇髕幽啹溴婘嚔臺䂷溘幋嬉方濘麪櫆㔗傯庫䫘䔇蓐庥準䩋認湙䔇髕儖赆毗蕙荘䇽垄傸傉䇽婘 pg_locks 婺埇蓕㔗
䫘庯淉嘩吘臵髕䔇庘昄婘臘9-50婺柟誄㔗