MySQLã®INSERT/UPDATEæã«ãããä¸æ´å対ç
å æ¥ãä½ã£ã¦ããã¢ããªã±ã¼ã·ã§ã³ã«ãã°ãçºçãã¾ããããã°ã®å 容ã¯æ¬¡ã®ãããªãã®ã§ããã
- åæã«åå¨ãã¦ã¯ãããªãã¯ãã®ãã¼ã¿ããDB ã«åå¨ãã
- æ´åæ§ã®ãã§ãã¯ã¯ã¢ããªã±ã¼ã·ã§ã³ã¬ãã«ã§è¡ã£ã¦ãã
- ä¸æå¶ç´ã®ãããªåç´ãªãã®ã§ã¯ãªãã®ã§ãã¢ããªã±ã¼ã·ã§ã³ã¬ãã«ã§å®è£
- æ´åæ§ã®ãã§ãã¯ãã¸ãã¯ã¯æ£ãã
ããã«å¯¾ãããã°ã¯æ¬¡ã®ãããªç¶æ³ã§çºçããã¨ä»®èª¬ãç«ã¦ã¾ããã
- ã¦ã¼ã¶ãã¬ã³ã¼ããä¸æ¬ç»é²ãããã¨ãã
- ç»é²ãã¿ã³ãæ¼ãããã¬ã¹ãã³ã¹ãé
ã
- ãã®éãæ´åæ§ãã§ãã¯ãèµ°ã£ã¦ãã
- ã¦ã¼ã¶ã¯ããä¸åº¦ç»é²ãã¿ã³ãæ¼ãã
- 2åç®ã®ç»é²ã®æ´åæ§ãã§ãã¯ãèµ°ãå§ãã
- 1åç®ã®ç»é²ã®æ´åæ§ãã§ãã¯ãå®äºãINSERTãå§ã¾ã
- 2åç®ã®ç»é²ã®æ´åæ§ãã§ãã¯ãå®äºãINSERTãå§ã¾ã
- 2åç®ã®ç»é²ã®æ´åæ§ãã§ãã¯ã®éãDBã«ã¯ã¾ã 1åç®ã®ç»é²ã«ããINSERTãå®è¡ããã¦ããªãã®ã§ããã§ãã¯ãééãã
- çµæãæ¬æ¥åæã«åå¨ãã¦ã¯ãããªãã¯ãã®ãã¼ã¿ãDB ã«ç»é²ããã¦ãã¾ã£ã
ãã®åé¡ã«å¯¾å¿ããããã«ã¯ãããã¯æ©æ§ãå¿
è¦ã«ãªãã¾ãã
(js ã§ããã«ãã¹ãã§ããªãããã«ããã¨ãã¯ãããã©ãè¤æ°äººã®ã¦ã¼ã¶ãåæã«ç»é²ãèµ°ãããå ´åãããããããã£ã¦ãä»åjs äºã
ã®è©±ã¯ãã·)
åèªèº«ãMySQLã®ããã¯ã®ç解ãæµ
ãã£ãã®ã§ãå°ã調ã¹ããã¨ã«ãã¾ãããä»åã¯ãã®èª¿æ»å
容ã®ã¾ã¨ãã«ãªãã¾ãã
主ãªå
容ã¯ã
- ä¸æå¶ç´ã®ä¿è¨¼
- ãã以å¤ã®å¶ç´ã«ãããæ´åæ§ã®ä¿è¨¼
- update ã®å ´å
- 楽観çããã¯ã¨æ²è¦³çããã¯
- MyISAM, InnoDBã«ããã対å¿æ¹æ³ã®éã
- insert ã®å ´å
- ãã©ã³ã¶ã¯ã·ã§ã³åé¢ã¬ãã«ã«ããã対å¿æ¹æ³ã®éã
ã§ãã
åé¡ã®å®ç¾©
ä»åã®åé¡ãèããã«ããã£ã¦ãä¸æ´åãçºçãã¦ããä¾ã3ã¤æãã¾ãã
ããã¦ãããããã®åé¡å¯¾ãã対å¿æ¹æ³ã示ãã¾ãã
1. éè¤ãã¼åé¡
å¦çã¯åãé¨æ´»ã«ã¯æå±ã§ããªãã¯ããªã®ã«ãè±éåããã¹ã±é¨ã¨ãã¹ã±é¨ã«æå±ãã¦ãã > <
ããããç¶æ
ã
student_id | name | student_id | club_id | club_id | name | ||||||||||||
1 | è±é | 1 | 1 | 1 | ãã¹ã±é¨ | ||||||||||||
1 | 1 |
2. ãã¹ãã¢ãããã¼ãåé¡
ãããã©ã³ã¶ã¯ã·ã§ã³ã®èª¬æã«ç¨ããããéè¡åå¼ã®ä¾ã
- ã¨ãã¹ãã¼ãã®ããã®MySQLãéç¨+管çããã©ãã«ã·ã¥ã¼ãã£ã³ã°ã¬ã¤ã(奥éå¹¹ä¹ è) p.143 å³2-4 ããå¼ç¨
BEGIN; SELECT b INTO @x FROM lost_upd WHERE a = 1; ãããããããããããããããããBEGIN; ãããããããããããããããããSELECT b INTO @x ãããããããããããããããããFROM lost_upd WHERE a = 1; # å¦çã«æéãããã ãããããããããããããããããUPDATE lost_upd SET b = @x + 100 ãããããããããããããããããWHERE a = 1; ãããããããããããããããããCOMMIT; UPDATE lost_upd SET b = @x + 10 WHERE a = 1; COMMIT;
ãb = @x + 100ãã®æ´æ°ããªãã£ããã¨ã«ãªã£ã¦ãã¾ã > <
3. ãã¡ã³ãã ãªã¼ãåé¡
ä»ååãééããåé¡ãå°ãæ¹å¤ããä¾ã¨ãã¦ãä¼è°å®¤ã®äºç´ã·ã¹ãã ãèãã¾ãã
- 1ã³ã2æéåä½ã§äºç´å¯è½
- éå§æéã¨ãã¦æå®ã§ããã®ã¯æ¥æã®ã¿(å以ä¸ã¯æå®ä¸è½)
BEGIN; SELECT * FROM reservations WHERE started_at BETWEEN '2011-01-23 13:00' AND '2011-01-23 15:00' AND room_id = 1; ãããããããããããããããããããããBEGIN; ãããããããããããããããããããããSELECT * ãããããããããããããããããããããFROM reservations ãããããããããããããããããããããWHERE started_at = '2011:01:23 14:00' AND '2011:01:23 16:00' ããããããããããããããããããããã AND room_id = 1; ããããããããããããããããããããã ããããããããããããããããããããã# => Empty set ãããããããããããããããããããããINSERT INTO reservations ããããããããããããããããããããã(room_id, started_at) ãããããããããããããããããããããVALUES (1, '2011:01:23 15:00'); ãããããããããããããããããããããCOMMIT; # å¦çã«æéãããã # => Empty set INSERT INTO reservations (room_id, started_at) VALUES (1, '2011:01:23 14:00'); COMMIT;
15æã16æéãéè¤ãã¦ããäºç´ãç»é²ããã¦ãã¾ã£ã > <
ã§ã¯ãããããã®åé¡ã¸ã®å¯¾æ¹æ³ãè¦ã¦ããã¾ãã
1. éè¤ãã¼åé¡ã¸ã®å¯¾å¿
- ä¸æå¶ç´ãã¤ãã
- ããã«ãã£ã¦éè¤ç»é²ãçºçããã¨ã¨ã©ã¼ãã
- MySQL ã¬ãã«ã§ä¿è¨¼ãã¦ãããã®ã§å®å¿
CREATE UNIQUE INDEX clubs_students_index ON clubs_students (club_id, student_id);
2. ãã¹ãã¢ãããã¼ãåé¡ã¸ã®å¯¾å¿
楽観çããã¯ã¾ãã¯ãæ²è¦³çããã¯ã使ããã¨ã«ãã£ã¦å¯¾å¿ããã
- 楽観çããã¯ã使ã
- Version ãã¿ã¼ã³
- ããã«ãã£ã¦ãå¾çºã®UPDATEã失æãã
- 失æããæ´æ°ãæ£ããåæ ããããããå度å¾çºã®UPDATEãå®è¡ãã
- æ²è¦³çããã¯ã使ã
- SELECTã®ä»£ããã«ãSELECT ... LOCK IN SHARE MODEã使ã
- ããã«ãã£ã¦
-
-
- å çºã®UPDATEãå¾ ã¡ç¶æ ã«ãªã
- å¾çºã®UPDATEæã«ãããããã¯ãçºçãå çºã®UPDATE ãå®è¡ããã
-
-
- 楽観çããã¯ã®å ´åã¨åæ§ã失æããå¾çºã®ã¯ã¨ãªãå度å®è¡ãã
楽観çããã¯ã¨æ²è¦³çããã¯
- 楽観çããã¯
- æ示çãªããã¯ããããªã
- æ´æ°ãããã¼ã¿ãè¡ã«æ¸ãæ»ãåã«ããã®è¡ãèªã¿åã£ãå¾ã«ä»ã®èª°ãããã®è¡ã«å¤æ´ãå ãã¦ããªãã確èªããæ¹æ³
- Version ãã¿ã¼ã³ã¨å¼ã°ãã
- INSERTã«ãã£ã¦çºçããä¸æ´åãé²æ¢ãããã¨ã¯ã§ããªã
- ãã¼ã¸ã§ã³çªå·ã表ãã«ã©ã ããã¼ãã«ã«è¿½å
- SELECTããæã®ãã¼ã¸ã§ã³çªå·ãè¨æ¶ãã¦ãã
- UPDATEæã«ã
- ãã¼ã¸ã§ã³çªå·ã2ã§åå¾ããçªå·ã¨çããããã§ãã¯ãã(UPDATE ... WHERE ... AND lock_version = 1;)
- ãã¼ã¸ã§ã³çªå·ãã¤ã³ã¯ãªã¡ã³ããã
- æ´æ°ãããè¡æ°ãã
- 0ã ã£ããã¨ã©ã¼ãè¡ãèªãã§ããæ´æ°ããåã«ä»ã®èª°ããè¡ãæ´æ°ããã¨ãããã¨
- 1ã ã£ããæ´æ°æå
- æ²è¦³çããã¯
- æ示çã«ããã¯ãããã
- ããã¯ãéæ¾ãããã¾ã§ãããã¯ãä¿æãã¦ããªãã¦ã¼ã¶ã¯ãã¼ã¿ãæä½ã§ããªã
- å ´åã«ãã£ã¦ã¯å¦çãé·æéæ»ã£ã¦ãã¾ããã¢ããªã±ã¼ã·ã§ã³ã®ããã©ã¼ãã³ã¹ãèããä½ä¸ããã
- MySQL ã§ã¯ãLOCK TABLESãSELECT ... LOCK IN SHARE MODE, SELECT ... FOR UPDATE çã«ãã£ã¦å®ç¾
MySQL ã®æ²è¦³çããã¯
- LOCK TABLES
- ãã¼ãã«ããã¯ãåå¾ãã
- èªã¿åãããã¯ãæ¸ãè¾¼ã¿ããã¯ã©ã¡ããåå¾ãããé¸æå¯è½
- SELECT ... LOCK IN SHARE MODE
- æ¤ç´¢ããè¡ã«èªã¿åãããã¯ãããã
- å¥ãã©ã³ã¶ã¯ã·ã§ã³ãããããã¯ã®ããã£ãè¡ãèªã¿åããã¨ãã§ãã
- å¥ãã©ã³ã¶ã¯ã·ã§ã³ãããããã¯ã®ããã£ãè¡ã«æ¸ãè¾¼ããã¨ã¯ã§ããªã
- InnoDBãSELECTæã«å é¨çã«ãããã¤ã³ãã³ã·ã§ã³ããã¯ã¨ã¯å¥ç©
- ã¤ã³ãã³ã·ã§ã³ããã¯ã«ã¤ãã¦ã¯ã奥éããã®æ¬ã®p.255ãã詳ããã§ã
- SELECT ... FOR UPDATE
- æ¤ç´¢ããè¡ã«æ¸ãè¾¼ã¿ããã¯ãããã
- å¥ãã©ã³ã¶ã¯ã·ã§ã³ãããããã¯ã®ããã£ãè¡ãèªã¿åããã¨ã¯ã§ããªã
- å¥ã ã®SELECT FOR UPDATEãåãè¡ãæ¤ç´¢ãããã¨ããå ´åãå¾çºã®SELECTã¯ãå çºã®ãã©ã³ã¶ã¯ã·ã§ã³ãå®äºããã¾ã§å¾ ã¡ç¶æ ã«ãªã
- å¥ãã©ã³ã¶ã¯ã·ã§ã³ãããããã¯ã®ããã£ãè¡ã«æ¸ãè¾¼ããã¨ã¯ã§ããªã
注æï¼MyISAM ã使ã£ã¦ããå ´å
- MyISAM ã使ã£ã¦ããå ´åãæ²è¦³çããã¯ã¨ãã¦SELECT ... LOCK IN SHARE MODE/FOR UPDATEã使ããã¨ã¯ã§ããªã
- ãã©ã³ã¶ã¯ã·ã§ã³æ©æ§ããªããã
- 楽観çããã¯ã使ãããLOCK TABLESã§ãã¼ãã«å ¨ä½ãããã¯ããå¿ è¦ããã
LOCK TABLES accounts READ; SELECT ... UPDATE ... UNLOCK TABLES;
3. ãã¡ã³ãã ãªã¼ãåé¡ã¸ã®å¯¾å¿
- æ²è¦³çããã¯ã使ã
- SELECTã®ä»£ããã«ãSELECT ... LOCK IN SHARE MODEã使ã
- ããã«ãã£ã¦ã
-
-
- å çºã®INSERTãå¾ ã¡ç¶æ ã«ãªã
- å¾çºã®INSERTæã«ãããããã¯ãçºçãå çºã®INSERTãå®è¡ããã
-
-
- æ´æ°å¦çãã£ã¦çºçããä¸æ´åã¨ã¯ç°ãªãããã¡ã³ãã ãªã¼ãåé¡ã楽観çããã¯ã§é²æ¢ãããã¨ã¯ã§ããªã
- MyISAM ã使ã£ã¦ããå ´åã¯ãLOCK TABLES ã使ã
注æï¼InnoDB ã®ãã©ã³ã¶ã¯ã·ã§ã³åé¢ã¬ãã«ãrepeatable readããä½ãå ´å
- SELECT ... LOCK IN SHARE MODEã«ãã£ã¦INSERTããããã¯ãããã®ã¯ããã¯ã¹ããã¼ããã¯ã¨ããä»çµã¿ã®ããã
- ãã¯ã¹ããã¼ããã¯ã¨ã¯
ãã¡ã³ãã ãªã¼ããé²æ¢ããããã®æ©æ§- ãã¡ã¸ã¼ãªã¼ãã¨ãã¡ã³ãã ãªã¼ããé²æ¢ããããã®æ©æ§(ä¿®æ£ï¼sh2 ããããツッコミãããã ãä¿®æ£)
- SELECTã§æ¤ç´¢ããã¬ã³ã¼ããåå¨ãã¦ããªãã¦ãããã®ã¬ã³ã¼ãã«ããã¯ãããããã¨ãã§ãã(ネクストキーロックによるファントム問題の回避)
- ãã¯ã¹ããã¼ããã¯ãæå¹ã«ãªãã®ã¯ããã©ã³ã¶ã¯ã·ã§ã³åé¢ã¬ãã«ããrepeatable read以ä¸ã®å ´å
- ãã©ã³ã¶ã¯ã·ã§ã³åé¢ã¬ãã«ãrepeatable readããä½ãå ´åããã¡ã³ãã ãªã¼ãåé¡ã«å¯¾å¿ããã«ã¯LOCK TABLESã³ãã³ãã«ãã£ã¦æ²è¦³çããã¯ããããå¿
è¦ããã
- InnoDB ã®repeatable read ã§ãã¡ã³ãã ãªã¼ãåé¡ã«å¯¾å¿ã§ããã®ã¯ãrepeatable readã¯ãã¡ã¸ã¼ãªã¼ãã ãé²ãã°ãããããã®ããã®ä»çµã¿ã¨ãã¦ãã¯ã¹ããã¼ããã¯ãç¨ãã¦ãããã(追è¨ï¼sh2 ããããツッコミãããã ã追å )
- ä»ã®RDBMSã使ãå ´åã¯åé¢ã¬ãã«ãserializable ã«ããå¿ è¦ããã
- ãã¡ã¸ã¼ãªã¼ãã«ã¤ãã¦ã¯DBの「トランザクション分離レベル」が必要な理由 (PostgreSQLで,ファントム・リードを防止すべきサンプル事例) - 主に言語とシステム開発に関してãåç §
- InnoDB ã®repeatable read ã§ãã¡ã³ãã ãªã¼ãåé¡ã«å¯¾å¿ã§ããã®ã¯ãrepeatable readã¯ãã¡ã¸ã¼ãªã¼ãã ãé²ãã°ãããããã®ããã®ä»çµã¿ã¨ãã¦ãã¯ã¹ããã¼ããã¯ãç¨ãã¦ãããã(追è¨ï¼sh2 ããããツッコミãããã ã追å )
注æï¼ãã¯ã¹ããã¼ããã¯ã«ãããããããã¯ã®å¼å®³(追è¨ï¼sh2 ããããツッコミãããã ã追å )
- ãã®ã±ã¼ã¹ãSELECT ... LOCK IN SHARE MODE ã§å¯¾å¿ããå ´åã13-15æï¼16-18æã®äºç´ã§ããããããã¯ãèµ·ããã¦ãã¾ã
- ãã¯ã¹ããã¼ããã¯ã¯ããã¯ã¹ãã®ãã¼ããªãã¨13-âæã¾ã§ããã¯ãã¦ãã¾ããã
- ãã¯ã¹ããã¼ããã¯ã«ããããã¯ã®æåã¯MySQL InnoDBのネクストキーロック おさらい - SH2の日記ãåç §
ã¾ã¨ã
MySQLã®INSERT/UPDATEæã«ãããä¸æ´å対çã¯ã次ã®ããã«ãªãã¾ãã
ã¹ãã¬ã¼ã¸ã¨ã³ã¸ã³ | MyISAM | InnoDB | ||
ãã©ã³ã¶ã¯ã·ã§ã³åé¢ã¬ãã« | - | repeatable read æªæº | repeatable read | serializable |
éè¤ãã¼åé¡ | ä¸æå¶ç´ | ä¸æå¶ç´ | ä¸æå¶ç´ | ä¸æå¶ç´ |
ãã¹ãã¢ãããã¼ãåé¡(UPDATE) | 楽観çãã㯠/ LOCK TABLES | 楽観çãã㯠/ LOCK TABLES | 楽観çãã㯠/ SELECT ... LOCK IN SHARE MODE | çºçããªã |
ãã¡ã³ãã ãªã¼ãåé¡(INSERT) | LOCK TABLES | LOCK TABLES | SELECT ... LOCK IN SHARE MODE | çºçããªã |