
ã³ã³ãã¥ãŒã¿ãŒã³ã³ãã¥ãŒãã£ã³ã°ã®åæå®è¡æ§ã®åé¡ã¯éåžžã«è€éã§ãïŒ éåžžã«è€éãªçç±ã¯ã䞊åããã°ã©ã ãéçºãããšãã«èæ
®ããå¿
èŠãããèšå€§ãªæ°ã®è©³çްã«ãããŸãã ããã°ã©ãã³ã°ã§ã¯ããšã©ãŒã®åºç€ãäœæããå€ãã®è©³çŽ°ãæ¢ã«ãããŸããã䞊ååŠçã¯ããã«è¿œå ããŸãã
ãªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ãžã®ç«¶äºåã®ããã¢ã¯ã»ã¹ã®åé¡ã¯ãã¢ããªã±ãŒã·ã§ã³ãœãããŠã§ã¢éçºè
ã ãã§ãªããã»ãšãã©ãã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ãœãããŠã§ã¢éçºè
ãçŽé¢ããŠããŸãã ãã®é åã«å¯Ÿãããã®éèŠã®çµæã¯ã倿°ã®äœæãããã¢ãŒããã¯ãã£ãã¿ãŒã³ã®ååšã§ãã ããã«ããããã®ãããªããã°ã©ã ã®éçºã®å€§ããªè€éãã«ããŸã察åŠã§ããŸãã 以äžã§ã¯ããã®ãããªã¬ã·ããšããããã®å®è£
ãåºã¥ããŠããã¡ã«ããºã ã«ã€ããŠèª¬æããŸãã ç©èªã¯Javaã³ãŒãã®äŸã§èª¬æãããŸãããã»ãšãã©ã®è³æã¯èšèªåºæã§ã¯ãããŸããã ãã®èšäºã®ç®çã¯ããããã¯ãå®å
šã«ç¶²çŸ
ããã®ã§ã¯ãªããäž»é¡ã®ç޹ä»ãšããŠããªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ãžã®ç«¶åã¢ã¯ã»ã¹ã®åé¡ã説æããããšã§ãã
ç«¶äºåã®ããã¢ã¯ã»ã¹ã®åé¡
ç¶æ³ãèæ
®ããŠãã ããã ç¹å®ã®äŒèšã·ã¹ãã ã§ã¯ãæžé¡ã®ä¿ç®¡äžã«ååã®æ®é«ã®å€åãåæ ããå¿
èŠããããŸãã è°è«ãããå®è³ªçã«ããããã«ãPostgreSQLã§å®è¡ããäŸãæäŸããŸãã äŒèšã·ã¹ãã ãšãã¹ãããŒã¿ã®ããŒã¿ããŒã¹æ§é ã¯æ¬¡ã®ãšããã§ãã
CREATE TABLE stocks ( id integer PRIMARY KEY, name varchar(256) NOT NULL, quantity decimal(10,2) NOT NULL DEFAULT 0.0 ); CREATE TABLE documents ( id integer PRIMARY KEY, quantity decimal(10,2) NOT NULL DEFAULT 0.0, processed boolean NOT NULL DEFAULT false, stock integer REFERENCES stocks ); INSERT INTO stocks (id, name, quantity) VALUES (1, '', 56.4), (2, '', 26.8); INSERT INTO documents (id, quantity, stock) VALUES (1, 15.6, 1), (2, 26.1, 1);
ç§ãã¡ã®ããã¥ã¡ã³ããå庫ããååãååŽãã責任ããããšããŸãããã ã¢ããªã±ãŒã·ã§ã³ã³ãŒãã¯ããã¥ã¡ã³ããšæ®ãã®ããŒã¿ãããŒãããèšç®ãå®è¡ããŠãããŒã¿ããŒã¹ã«ããŒã¿ãä¿åããŸãã ãã®ã¢ã¯ã·ã§ã³ã1ã€ã®ã¢ããªã±ãŒã·ã§ã³ã«ãã£ãŠå®è¡ãããå Žåããã¹ãŠãæ£åžžã«è¡ãããŸãã
SELECT quantity, processed, stock FROM documents WHERE id = 1;
quantity | processed | stock ----------+-----------+------- 15.60 | f | 1
SELECT name, quantity FROM stocks WHERE id = 1;
name | quantity ------+---------- | 56.40
èå¥åã1ã®ããã¥ã¡ã³ãã®ããŒã¿ãšã察å¿ããããã¥ã¡ã³ãã®æ®ãã®ããŒã¿ãããŒããããŸãã æ®ãã®æ°ããå€ã¯ã56.40-15.60 = 40.80ãæžãèœãšããŠèšç®ãããããŒã¿ã¯ææžã®åŠçã«é¢ããã¡ã¢ãšãšãã«ä¿åãããŸããã
UPDATE stocks SET quantity = 40.80 WHERE id = 1; UPDATE documents SET processed = true WHERE id = 1;
ããããã·ã³ã°ã«ãŠãŒã¶ãŒã·ã¹ãã ã¯é·ãéå»ã§ãã çŸåšããŠãŒã¶ãŒã䞊ã¶ã¹ãããžãã¹ã¢ããªã±ãŒã·ã§ã³ãæ³åããããšã¯äžå¯èœã§ãã ãããã£ãŠã2ã€ã®ããã¥ã¡ã³ããåæã«åŠçãããç¶æ³ãèããŠã¿ãŸãããã æåã®å Žåãšåæ§ã«ãã¢ããªã±ãŒã·ã§ã³ã¯ããŒã¿ããŒã¹ããããŒã¿ãèªã¿åããŸãã
æåã®ã¢ããªã±ãŒã·ã§ã³
SELECT quantity, processed, stock FROM documents WHERE id = 1;
quantity | processed | stock ----------+-----------+------- 15.60 | f | 1
SELECT name, quantity FROM stocks WHERE id = 1;
name | quantity ------+---------- | 56.40
2çªç®ã®ã¢ããªã±ãŒã·ã§ã³
SELECT quantity, processed, stock FROM documents WHERE id = 2;
quantity | processed | stock ----------+-----------+------- 26.10 | f | 1
SELECT name, quantity FROM stocks WHERE id = 1;
name | quantity ------+---------- | 56.40
ãããŠãããã§æãããªåé¡ãçºçããŸããæåã®ã¢ããªã±ãŒã·ã§ã³ã¯56.40-15.60 = 40.80ãèšç®ãã2çªç®ã®ã¢ããªã±ãŒã·ã§ã³ã¯56.40-26.10 = 30.30ãèšç®ããŸãã ãããŠããããã®çµæã®ãããããããŒã¿ããŒã¹ã«æžã蟌ãŸããŸãã æåŸã®æŽæ°èŠæ±ãå®è¡ããã察象ã ããã¯æããã«ãŠãŒã¶ãŒãæåŸ
ãããã®ã§ã¯ãããŸããã ãã®çš®ã®åé¡ã¯ã䞊åããã°ã©ãã³ã°ã§ããç¥ãããŠãããç«¶åç¶æ
ãšåŒã°ããŸãã ãã®ã±ãŒã¹ã¯ãäžè¬åãread-modify-writeã®è€åã¢ã¯ã·ã§ã³ã§ãã
åŠçããããã¥ã¡ã³ãïŒåŠçæžã¿ãã£ãŒã«ãïŒããã§ãã¯ããå®éã®ã¢ããªã±ãŒã·ã§ã³ã§ãããè¡ããªããã°ãªããªãå Žåããã§ãã¯ã«ãããããããããã¥ã¡ã³ãã2ååŠçãããå¯èœæ§ããããŸãã ãã¹ãŠãç«¶åç¶æ
ã§ããããŸãããç°ãªãçš®é¡ã®check-then-actæäœã§ãã ããã«ãæŽæ°èŠæ±ã®ééã§ã¯ãããŒã¿ããŒã¹ã¯äžè²«æ§ã®ãªãç¶æ
ã«ãããŸããã€ãŸããããã¥ã¡ã³ãã¢ã¯ã·ã§ã³ã¯æ¢ã«å®äºããŠããŸãããããã¥ã¡ã³ãã¯åŠçæžã¿ãšããŠããŒã¯ãããŠããŸããã
ãã®çµæãããŒã¿ããŒã¹ãžã®äžæ£ãªç«¶åã¢ã¯ã»ã¹ã§çºçããæãäžè¬çãªåé¡ã2ã€ãããŸãã ããã¯ãèªã¿åã/倿Ž/æžã蟌ã¿ã®ç«¶åç¶æ
ãçºçããå Žåã«çºçãã倿Žã®æå€±ã§ãã ãããŠãæŽæ°ãªã¯ãšã¹ãéã®ããŒã¿ã®äžè²«æ§ã®ãªãç¶æ
ã
DBMSã¡ã«ããºã
ãªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ãžã®ç«¶äºåã®ããã¢ã¯ã»ã¹ã®ããã®ç¹å®ã®ã¬ã·ããè°è«ããã«ã¯ãDBMSãšããã°ã©ãã³ã°ããŒã«ãæäŸããäœã¬ãã«ã®ã¡ã«ããºã ã«ç²ŸéããŠããå¿
èŠããããŸãã ãããã¯ãå®è£
ã®ããŒã¹ãšãªãæè¡èŠçŽ ã§ãã äž»ãªèŠçŽ ã¯ããã©ã³ã¶ã¯ã·ã§ã³ãšããã¯ã§ãã ãããã«ã€ããŠããã«èª¬æããŸãã
ãã©ã³ã¶ã¯ã·ã§ã³ãšåé¢ã¬ãã«
ãã©ã³ã¶ã¯ã·ã§ã³ã¯ããã©ã³ã¶ã¯ã·ã§ã³ãããŒã«ããã¯ãŸãã¯ç¢ºèªããæ©èœãåããããŒã¿ããŒã¹ãšå¯Ÿè©±ããããã®åäžã®æäœã·ãŒã±ã³ã¹ã§ãã ãã©ã³ã¶ã¯ã·ã§ã³ã¯ã倿Žã®äžè²«æ§ã®åé¡ã解決ããææ®µã«ãªãå¯èœæ§ããããã¬ãŒã¹ã®ç¶æ³ãèš±å¯ããŸããã æåãŸãã¯äž¡æ¹ã®åé¡ã解決ããããã®ãã©ã³ã¶ã¯ã·ã§ã³ã®é©åæ§ã¯ãåé¢ã¬ãã«ã«ãã£ãŠç°ãªããŸãã åé¢ã¯ãåäžã®æäœã«ãã£ãŠè¡ããã倿Žãç«¶åããæäœã«ã©ã®ããã«/ãã€è¡šç€ºãããããå®çŸ©ããããããã£ã§ãã
SQLæšæºã§ã¯ãéã³ãããèªã¿åããã³ãããèªã¿åããç¹°ãè¿ãèªã¿åããã·ãªã¢ã«åã®4ã€ã®åé¢ã¬ãã«ãå®çŸ©ããŠããŸãã ãããã¯ãã¹ãŠãæäœèš±å®¹ã¬ãã«ã®æç±æãåããŠããŸãã ãããã®ã¬ãã«ã®åºæ¬çãªããããã£ã¯ãååããæãããªã¯ãã§ãã ããŸããŸãªDBMSããããŸããŸãªæ¹æ³ã§åé¢ã¿ã€ãã®ãµããŒããå®è£
ããå ŽåããããŸãã äž»ãªããšã¯ãåå®è£
ã§ã¯ãã¬ãã«ã§èŠå®ãããŠãããããå³ãããªãåé¢ãèš±å¯ããªãããšã§ãã ããšãã°ãPostgreSQLã¯å
éšã§2ã€ã®åé¢ã¬ãã«ã®ã¿ããµããŒãããŸãïŒã³ãããã®èªã¿åããšã·ãªã¢ã©ã€ãºå¯èœã§ãã ãããã®åé¢ã¬ãã«ã䜿çšããŠãäžèšã®äŸã§èª¬æããåé¡ã解決ããããšãæ€èšããŠãã ããã
Read Committed Isolation LevelïŒPostgreSQLã§ããã©ã«ãã§äœ¿çšïŒã䜿çšãããšãããŒã¿ç¶æ
ã®äžè²«æ§ã®åé¡ã解決ã§ããŸãã ããã¯ããã©ã³ã¶ã¯ã·ã§ã³å
ã§è¡ããããã¹ãŠã®å€æŽããçŸåšã®ãã©ã³ã¶ã¯ã·ã§ã³ã®åŸãç«¶åãããã©ã³ã¶ã¯ã·ã§ã³ããèŠããããã«ãªããšããäºå®ã«ããéæãããŸãã
BEGIN; SELECT quantity, processed, stock FROM documents WHERE id = 1; SELECT name, quantity FROM stocks WHERE id = 1;
ãããããã®ãããªãã©ã³ã¶ã¯ã·ã§ã³ã¯ãç«¶äºåã®ãããªãã¬ãŒã·ã§ã³ã®å®è¡ã«ãããç«¶åã®ç¶æ
ã«é¢ããåé¡ã解決ããŸããã ãã®ãããªç¶æ³ã§ã¯ãå¥ã®ã¬ãã«ã®åé¢ã圹ç«ã¡ãŸã-ã·ãªã¢ã©ã€ãºå¯èœã ããã¯å¯èœãªè§£æ±ºçã§ãããããã ãã§ã¯ãããŸããã PostgreSQLã®Serializableåé¢ã¬ãã«ã®å®è£
ã®åäœã¯ãååãšå®å
šã«ã¯äžèŽããŠããŸããã ã€ãŸããSerializableåé¢ã¬ãã«ãæã€ãã¹ãŠã®ãã©ã³ã¶ã¯ã·ã§ã³ã¯é 次å®è¡ãããŸããã 代ããã«ããã©ã³ã¶ã¯ã·ã§ã³ãã³ããããããšãã«ãããŒã¿ã倿Žããããšãã«ç«¶åããã§ãã¯ãããç«¶åãããã©ã³ã¶ã¯ã·ã§ã³ã«ãã£ãŠããŒã¿ãæ¢ã«å€æŽãããŠããå ŽåãçŸåšã®ãã©ã³ã¶ã¯ã·ã§ã³ã¯å€±æããŸãã
BEGIN ISOLATION LEVEL SERIALIZABLE; SELECT quantity, processed, stock FROM documents WHERE id = 1; SELECT name, quantity FROM stocks WHERE id = 1;
äžèšã®ãã©ã³ã¶ã¯ã·ã§ã³ã¯ãã¬ãŒã¹ã®ç¶æ³ãšããŒã¿ã®äžè²«æ§ã®äž¡æ¹ã«é¢ããåé¡ã解決ããŸãã ãã®ã¢ãããŒãã®ç¹åŸŽã¯ããã®ãã©ã³ã¶ã¯ã·ã§ã³ãå®è¡ããã³ãŒããããã©ã³ã¶ã¯ã·ã§ã³ã®å®äºåŸã«ã®ã¿æåã«ã€ããŠåŠç¿ããããšã§ãã ãããŠã倱æã®çµæãšããŠããã©ã³ã¶ã¯ã·ã§ã³ãæåããããã¢ã¯ã·ã§ã³ã®å®è¡ãæåŠããæ±ºå®ãäžããããŸã§ããã¹ãŠã®ã¢ã¯ã·ã§ã³ãšèšç®ãç¹°ãè¿ãå¿
èŠããããŸãã ç¹°ãè¿ãã®ããã«å€§éã®ãªãœãŒã¹ãæ¶è²»ãããããããã®åäœã¯å€§ããªç«¶åè² è·ã§ã¯äžååã§ãã ãã®åäœã¯ã楜芳çåæå®è¡å¶åŸ¡ãšåŒã°ããŸãã
äžèšã®äŸã¯ãããžãã¹ããžãã¯ãã¢ããªã±ãŒã·ã§ã³ã³ãŒãã«å®å
šã«å®è£
ãããããŒã¿ããŒã¹ãã¹ãã¬ãŒãžãšããŠã®ã¿æ©èœãããšããåæã«åºã¥ããŠããŸãã
ããã©ãŒãã³ã¹ã«åœ±é¿ãããã©ã³ã¶ã¯ã·ã§ã³ã®äœ¿çšã«ãããéèŠãªè©³çްã¯ããã®é·ãã§ãã ãã©ã³ã¶ã¯ã·ã§ã³ã¯é·ãããŠã¯ãªããŸããããã©ã³ã¶ã¯ã·ã§ã³ãéãå®äºããã»ã©ãã·ã¹ãã ã®ããã©ãŒãã³ã¹ãåäžããŸãã ãã®ã³ã¡ã³ãã¯ãå°æ°ã®ãŠãŒã¶ãŒãããã¢ããªã±ãŒã·ã§ã³ã§ããã¥ã¡ã³ãã®ç·šéãå®è¡ããã³ãŒãã«ãšã£ãŠéèŠã§ã¯ãªãå ŽåããããŸãã ãã ããããšãã°ãããŒã¿ããŒã¹ãšå¯Ÿè©±ãã倿°ã®ã¯ã©ã€ã¢ã³ãã§äœ¿çšãããWebãµãŒãã¹ã®ç¶æ³ã§ã¯ãããã¯éèŠã§ãã
ããã¯
䞊åããã°ã©ãã³ã°ã§ã¯ãããã¯ã¡ã«ããºã ã䜿çšããŠå®è¡ã¹ã¬ãããå¶åŸ¡ããŸãã ããã¯ã䜿çšãããšãç¹å®ã®é åãžã®ã¢ã¯ã»ã¹ãã·ãªã¢ã«åã§ããŸãã DBMSã¯ãããŒã¿ãžã®ã¢ã¯ã»ã¹ãå¶åŸ¡ããããã¯ã¡ã«ããºã ããµããŒãããŠããŸãã PostgreSQLã®äŸã䜿çšããŠããã®ã¡ã«ããºã ã®å¯èœæ§ãèããŠã¿ãŸãããã
PostgreSQLã¯å€ãã®çš®é¡ã®ããã¯ããµããŒãããŠããŸãã äž»ãªç¹åŸŽã¯ãçŸåšã®çš®é¡ã®ããã¯ãšç«¶åããå€ãã®çš®é¡ã®ããã¯ã§ãã ç«¶åãšã¯ãç«¶åããã¿ã€ãã®ããã¯ãšäžç·ã«çŸåšã®ããã¯ããã£ããã£ã§ããªãããšãæå³ããŸãã ããã«ãããã¯ã¯æç€ºçãšæé»çã«åããããŸãã æç€ºçããã¯ãšã¯ãlockããŒã¯ãŒããšãæŽæ°ãŸãã¯å
±æãã€ãŸããŠãŒã¶ãŒãæå®ããå
±æã®ããã®ã¯ãšãªä¿®é£Ÿåã䜿çšããŠãã¯ãšãªã§å®è¡ãããããã¯ã§ãã æé»çããã¯ã¯ãããŸããŸãªèŠæ±ïŒéžæãæŽæ°ãæ¿å
¥ã倿Žãªã©ïŒã®éã«ãã£ããã£ãããããã¯ã§ãã PostgerSQLã¯ãã¢ããã€ã¶ãªããã¯ãšåŒã°ããå¥ã®çš®é¡ã®ããã¯ããµããŒãããŠããŸãã
ããã¯ã¯ããªã¯ãšã¹ããå®è¡ãããŠããçŸåšã®ãã©ã³ã¶ã¯ã·ã§ã³ãçµäºãããŸã§ãã£ããã£ãããŸãã ããšãã°ãä»®æ³äŒèšã·ã¹ãã ã§ã¯ãæäœãå®è¡ãããæ®ãã®éšåã«å¯Ÿå¿ããstocksããŒãã«ã®è¡ãšããã¥ã¡ã³ãããŒãã«ã®è¡ã§æä»ããã¯ãååŸããããšãå¯èœã§ãããããã«ãã£ãŠçŸåšã®ãã©ã³ã¶ã¯ã·ã§ã³ã®ã¿ããã®ããŒã¿ã«ã¢ã¯ã»ã¹ã§ããããšãä¿èšŒããŸãã
BEGIN; SELECT quantity, processed, stock FROM documents WHERE id = 1 FOR UPDATE; SELECT name, quantity FROM stocks WHERE id = 1 FOR UPDATE;
äžèšã®ã³ãŒãã¯ãããã¥ã¡ã³ãããã³æ ªåŒããŒãã«ã®è¡ã®ããã¯ããã£ããã£ããŸãã ãã®å ŽåãæŽæ°çšã®ããŒã¯ãŒããã¯ãšãªã«è¿œå ãããéžæããŒã¿ãéžæãããŸãã ããã¯ãæŽæ°ã®ããã®è¡ã®æç€ºçãªãããã¯ã§ãã ãã®å ŽåãããŒãã«å
šäœããããã¯ããŠã广ã¯ãããŸããã äžè¬ã«ãããŒãã«ãããã¯ããå¿
èŠãããã®ã¯ãããŒã¿ãå«ãå€§èŠæš¡ãªæäœã®å Žåã®ã¿ã§ããããããã¯éåžžã«ãŸããªã±ãŒã¹ã§ãã ããããªããšããã¹ãŠã®åŒã³åºããã·ãªã¢ã«åããããããç«¶åã¢ã¯ã»ã¹ã§ããã©ãŒãã³ã¹ã®åé¡ãçºçããŸãã
ãã§ã«ããã¯ãããŠããé åã®ããã¯ããã£ããã£ããããšãããšãããã¯ãè§£é€ããããŸã§ãªã¯ãšã¹ãããããã¯ãããŸãïŒããã©ã«ãïŒããŸãã¯ããããããã¯ã®å Žåããšã©ãŒã¡ãã»ãŒãžãè¿ãããŸãã ãããã¯ãããèŠæ±ããå¶åŸ¡ãè¿ãééãèšå®ããããšããããã¯ãååŸã§ããªãããšã«é¢ããã¡ãã»ãŒãžãããã«åä¿¡ããããšãã§ããŸãïŒnowaitïŒã
ç«¶äºã³ã³ãããŒã«ã®çš®é¡
ç«¶åå¶åŸ¡ã¯ãç«¶åãµã€ãã§ã®äžŠåå®è¡ã¹ã¬ãããçžäºäœçšããã«ãŒã«ã§ãã ç«¶äºç®¡çã¯ãèšç®çµæã®æ£ç¢ºæ§ãä¿èšŒããå¿
èŠããããŸãã 远å ã®ç®æšã¯ãç¹å®ã®ã±ãŒã¹ã§å¯èœãªéãè¿
éã«çµæãååŸããããšã§ãã ç«¶åå¶åŸ¡ã¯éåžžãç«¶ååŠçã®æéã«å¿ããŠã楜芳çïŒæ¥œèгçïŒãæ²èгçïŒæ²èгçïŒãããã³éšåçæ¥œèгçïŒå楜芳çïŒã®ã¿ã€ãã«åé¡ãããŸãã
楜芳çãªç«¶äºå¶åŸ¡ã«ã¯ãã¢ã¯ã·ã§ã³ã®æœåšçãªç«¶åã®ãã§ãã¯ãå«ãŸããŸãã ããšãã°ããŠãŒã¶ãŒã¯ãªããžããªã«ããŒã¿ãèŠæ±ããŠå€æŽãããã®åŸã倿Žãä¿åããããšããŸãã ãªããžããªå
ã®ããŒã¿ã®çŸåšã®ããŒãžã§ã³ãã倿Žãè¡ãããããŒã¿ã®ããŒãžã§ã³ã«å¯Ÿå¿ããå Žåãç«¶åã¯çºçãããããŒã¿ãä¿åã§ããŸãã å察ã®å Žåãç«¶åãçºçããã¢ã¯ã·ã§ã³ãåå®è¡ããããã¢ã¯ã·ã§ã³ãæåŠããããšã§åŠçãããŸãã æ¥œèгçãªç«¶äºå¶åŸ¡ã¯ãç«¶äºåã®ããã¢ã¯ã»ã¹ã«å¯Ÿããç«¶äºãæ¯èŒçå°ãªãè¯å¥œãªããã©ãŒãã³ã¹ãæäŸããŸãã
æ²èгçãªç«¶äºç®¡çã«ã¯ãã¢ã¯ã·ã§ã³ãå®è¡ããåã«æœåšçãªç«¶åããã§ãã¯
ããããšãå«ãŸããŸãã ã€ãŸããä¿è·ãããé åã§ç«¶åããå®è¡ã¹ã¬ãããã·ãªã¢ã«åãããŸãã ããã«ãããç«¶äºåã®ããã¢ã¯ã»ã¹ã®ããã®é«ãç«¶äºåã§çç£æ§ãåäžããŸãã
éšåçã«æ¥œèгçã¯ãäž¡æ¹ã®ã¢ãããŒããåæã«é©çšãããæ··ååã§ãã
建ç¯ãã¿ãŒã³
ãã®æç¹ã§ãèªè
ã¯ç«¶åã¢ã¯ã»ã¹ã®åé¡ãšãããã解決ããDBMSã¡ã«ããºã ã®äžè¬çãªæŠå¿µãçè§£ããŠããã¯ãã§ãã ãã®ã»ã¯ã·ã§ã³ã§ã¯ãããŒã¿ããŒã¹ãžã®ç«¶äºçã¢ã¯ã»ã¹ã®åé¡ã«å¯Ÿãããœãªã¥ãŒã·ã§ã³ã衚ãã¢ãŒããã¯ãã£ãã¿ãŒã³ã«çŠç¹ãåœãŠãŸãã 以äžã¯å®å
šãªèª¬æã§ã¯ãªããäžè¬çãªã¢ã€ãã¢ãšäŸã§ãã 詳现ãªèª¬æã«ã€ããŠã¯ãèšäºã®äžéšã«ãããªã³ã¯ãã¯ãªãã¯ããŠãã ããã
DBMSã䜿çšããå ŽåãããŒã¿ã¯ã¢ããªã±ãŒã·ã§ã³ã®ã¡ã¢ãªã«èªã¿èŸŒãŸãããããã䜿çšããŠããŸãã¯ããããä»ããŠã¢ã¯ã·ã§ã³ãå®è¡ãããŸããã¢ã¯ã·ã§ã³ã®çµæã¯ãååãšããŠä¿åãçŽãå¿
èŠããããŸãã ãã®éãäœã倿Žãããããç¥ãããã«ãããŒã¿ã®å€æŽã«é¢ããæ
å ±ãä¿åããå¿
èŠããããŸãã ããã«ãäœæããã³åé€ããããªããžã§ã¯ãã«é¢ããæ
å ±ãä¿åããå¿
èŠããããŸãã ãã¡ãããããŒã¿ããŒã¹å
ã®ãã¹ãŠã®å€æŽãããã«åæ ã§ããŸãã ãã®å Žåãæ¬¡ã®åé¡ãçºçããŸããã·ã¹ãã ãã©ã³ã¶ã¯ã·ã§ã³ã«ã¯éåžžã«é·ãæéãããããããŒã¿ããŒã¹ãžã®å€æŽã«å¯Ÿããããã¯ããã©ã³ã¶ã¯ã·ã§ã³å
šäœã«ããã£ãŠä¿æããããããç«¶åã¢ã¯ã»ã¹äžã«ç«¶åãçºçããŸãã ããŒã¿ããŒã¹ãšã®å¯Ÿè©±ã¯å€ãã®å°ããªéšåã«åå²ãããŸãããããã广ããããŸããã ããŒã¿å€æŽã®è¿œè·¡ã®åé¡ã解決ããããã«ãäœæ¥åäœãã¿ãŒã³ã«ã€ããŠèª¬æããŸãã ãã®ãã¿ãŒã³ã¯ããã¹ãŠã®å€æŽã远跡ãã倿ŽãããŒã¿ããŒã¹ã«é©çšããŠããã®ç¶æ
ãè¡ã£ã倿ŽãšäžèŽããããªããžã§ã¯ããèšè¿°ããŸãã
public class UnitOfWork { private List<DomainObject> newObjects; private List<DomainObject> updatedObjects; private List<DomainObject> deletedObjects; public DomainObject create() { DomainObject domainObject = new DomainObject(); newObjects.add(domainObject); return domainObject; } public void update(DomainObject domainObject) { updatedObjects.add(domainObject); } public void remove(DomainObject domainObject) { deletedObjects.add(domainObject); } public void commit() {
äžèšã¯ãäœæ¥åäœãã¿ãŒã³ã®æãåçŽãªå®è£
ã§ãã DomainObjectsã¯ãé©åãªã¢ã¯ã·ã§ã³ãå®è¡ããããšãã«UnitOfWorkãªããžã§ã¯ãã«ç»é²ã§ããŸãã ããžãã¹ãã©ã³ã¶ã¯ã·ã§ã³ãå®äºããåŸãã¢ããªã±ãŒã·ã§ã³ã¯UnitOfWorkãªããžã§ã¯ãã®commitã¡ãœãããåŒã³åºããŸãã
éåžžãããžãã¹ãã©ã³ã¶ã¯ã·ã§ã³ã«ã¯é·ãæéãããããŸãã ååãšããŠãè€æ°ã®ã·ã¹ãã ãã©ã³ã¶ã¯ã·ã§ã³ã«æ¡åŒµãããŸãã ãã®çç±ã¯ãã§ã«äžã§è¿°ã¹ã-é·ãããã¯ãã£ããã£ã®åé¡ã DBMSåæã¡ã«ããºã ã¯1ã€ã®ã·ã¹ãã ãã©ã³ã¶ã¯ã·ã§ã³å
ã§ã®ã¿æ©èœãããããç¬èªã®åæã¡ã«ããºã ãå®è£
ããå¿
èŠããããŸããããã¯ãããã€ãã®ã·ã¹ãã ãã©ã³ã¶ã¯ã·ã§ã³ã®äžã§åäœããŸãã ãã®åé¡ã解決ããããã«ã楜芳çããã³æ²èгçãªã¿ã€ãã®ç«¶åå¶åŸ¡ãå®è£
ãã2ã€ã®æ¥œèгçãªãã©ã€ã³ããã¯ããã³æ²èгçãªãã©ã€ã³ããã¯ãã¿ãŒã³ã«ã€ããŠèª¬æããŸãã
ãŠãŒã¶ãŒãç·šéãã©ãŒã ãéããŠãããã¥ã¡ã³ãã§æ°åéäœæ¥ããçµæãä¿åãããšããŸãã ããã¯ãããžãã¹ãã©ã³ã¶ã¯ã·ã§ã³ã®å
žåçãªäŸã§ãã
楜芳çãªç«¶äºç®¡çã®ç¶æ³ãèæ
®ããŠãã ããã ç·šéçµæã®ä¿åäžã«ç«¶åãæ€åºãããå ŽåããŠãŒã¶ãŒã«ã¯å€æŽãããããŒã¿ãšè¿œå ã®ã¢ã¯ã·ã§ã³ãéžæãããã€ã¢ãã°ãéç¥ãããŸãã Optimistic Offline Lockãã¿ãŒã³ã¯ãäžè¬çãªå ŽåãããŒãžã§ã³ç®¡çãããããŒã¿ã¡ã«ããºã ã«äŸåãã倿Žå¶åŸ¡ã¡ã«ããºã ãèšè¿°ããŸãã 倿Žãä¿åããããã³ã«ãããŒã¿ããŒã¹å
ã®ããŒã¿ã®ããŒãžã§ã³ãã倿Žãè¡ãããããŒãžã§ã³ãšæ¯èŒãããŸãã ãããã®ããŒãžã§ã³ãçããå ŽåãçŸåšã®ããŒãžã§ã³ã倿Žãããçµæãä¿åãããŸããããã§ãªãå Žåãç«¶åãçºçããã¢ã¯ã·ã§ã³ãç¹°ãè¿ãããã£ã³ã»ã«ããããšã§åŠçãããŸãã
public class DomainObject { private Integer id; private Integer version; private Object data;
äžèšã®ã³ãŒãã¯ãäžèšã®Optimistic Offline Lockãã¿ãŒã³ã䜿çšããupdateã¡ãœããã®å®è£
ã瀺ããŠããŸãã ãã®å®è£
ã§ã¯ã倿Žããããªããžã§ã¯ãã®ãªã¹ãã¯ããŒãžã§ã³æ€èšŒãšãšãã«ä¿åãããŸãã ããŒãžã§ã³ã倿Žãããå ŽåãããŒãã«ã®åäžã®ã¬ã³ãŒãã¯æŽæ°ãããããã®äŸã§ã¯äŸå€ãã¹ããŒãããŸãã ãã®äŸå€ã¯ãç«¶åããå®è¡ã¹ã¬ããã«ãã£ãŠã¬ã³ãŒããæ¢ã«æŽæ°ãããŠããç«¶åã«å¯Ÿå¿ããŠããŸãã
æ²èгçãªç«¶åå¶åŸ¡ã®å Žåãæ²èŠ³çãªãªãã©ã€ã³ããã¯ãã¿ãŒã³ã®å®è£
ã以äžã«ç€ºããŸãã
class DomainObject { private Integer id; private Boolean blocked; private Object data;
æç€ºãããã³ãŒãã§ã¯ãããŒã¿ããŒã¹ããããŒã¿ãåä¿¡ãããšããããã¯ããããã£ãŒã«ãã«ããã¯ãèšå®ãããŸãã æ¢ã«èšå®ãããŠããå Žåã¯äŸå€ãã¹ããŒãããããã§ãªãå Žåã¯çµæãè¿ãããŸãã ããã«ããªããžã§ã¯ããæŽæ°ãããšãããã¯ããªã»ãããããŸãã ãã®å®è£
ã¯ããã¹ãŠã®ã¬ãã«ã®ãã©ã³ã¶ã¯ã·ã§ã³åé¢ã§æ©èœããŸãã ããã¯ã®ãã£ããã£åŸã«ããŒã¿ãä¿åãããå Žåã
æç€ºãããå®è£
ã¯ã説æã説æããã ãã§ãããå®éã®ã¢ããªã±ãŒã·ã§ã³ã§ã®äœ¿çšãç®çãšããŠããŸããïŒããžãã¹ã¬ãã«ã®ããã¯ã¢ãŠãããªã·ãŒ
ããããã³ã°ããªã·ãŒã¯ãããŒã¿ãžã®åæã¢ã¯ã»ã¹ã管çããã«ãŒã«ã§ãã ãã®æ®µèœã§ã¯ãDBMSããã³ãã©ãããã©ãŒã åæã¡ã«ããºã ãžã®ã¯ãšãªã®ã¬ãã«ã§ã¯ãªããããžãã¹ã¬ãã«ã§ããã¯ã®ããªã·ãŒãæ±ããŸãã ããã¯ããªã·ãŒã¯ããžãã¹ããžãã¯ã«é¢é£ããŠããå¿
èŠãããããšã«æ³šæããŠãã ããã ãããŠãããªãã¯ç«¶äºã®ããã«åŸã§è³ªåããããšã¯ã§ããŸããã
ããšãã°ãç¹å®ã®ããã¥ã¡ã³ããåç¬ã§ç·šéããå¿
èŠãããããšãã¹ã³ãŒãã瀺ãã·ã¹ãã ã§ã¯ãããžãã¹ããžãã¯ããã®èŠä»¶ã®ç¥èãæã£ãŠããå¿
èŠããããŸããããžãã¹ãšãªã¢ã®ãã®ãããªèŠä»¶ã®å®è£
ã®å Žåãåæã¡ã«ããºã ã®å©ããåããŠã®ã¿ãã¢ããªã±ãŒã·ã§ã³ã§ã®ããžãã¹ã¬ãã«ã®å®è£
ã¯ããã€ãã®éšåã«åå²ãããŸãããããã¯ããŸãè¯ããããŸããããŸãããã®ãããªã·ã¹ãã ã®ãµããŒãã¯è€éã§ãããããçµã¿èŸŒã¿ã®DBMSããã·ãŒãžã£ã䜿çšããŠããã©ãŒãã³ã¹ãæé©åãããªãã·ã§ã³ã¯éåžžã«äžè¬çã§ããã第äºã«ãé·ãã·ã¹ãã ãã©ã³ã¶ã¯ã·ã§ã³ã«ã¯åé¡ããããŸããã€ãŸããã¢ããªã±ãŒã·ã§ã³ãããžãã¹ãã©ã³ã¶ã¯ã·ã§ã³ãšåæã«ã·ã¹ãã ãã©ã³ã¶ã¯ã·ã§ã³ãéãããŸãŸã«ã§ããªãããã«ããããšãã§ããŸãããããžãã¹ãã©ã³ã¶ã¯ã·ã§ã³ã®è²¬ä»»ç¯å²ã¯ãã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ã«ãããŸãããããã£ãŠãããžãã¹ãã©ã³ã¶ã¯ã·ã§ã³ã®ããã¯ããªã·ãŒã¯ãããžãã¹ããžãã¯ãšã¯å¥ã«èæ
®ããããšã¯ã§ããŸããã(en)
Patterns of Enterprise Application Architecture (Martin Fowler, David Rice, Matthew Foemmel, Edward Hieatt, Robert Mee, Randy Stafford)PostgreSQL Concurrency ControlConcurrency controlIsolation level