์ง๊ณ ๊ฒฐ๊ณผ๋ฅผ ๊ฐฑ์ ํ ๋ ์ง์ฐ๊ณ ๋ค์ ๋ฃ๊ณ ์์๋ค. ์ค๊ฐ์ ๋ฉ์ถ ๋ ํ๋ฉด์ด ํต์งธ๋ก ๋น์๋ค.
Table of contents
Open Table of contents
์ฆ์ โ ์ง์ฐ๊ณ ๋ฃ๊ณ ์์๋ค
๊ฐฑ์ ํ๋ ์๋ฆฌ๋ ๋ ์ค์ด์๋ค.
DELETE FROM stat_daily WHERE stat_date = '2018-09-27';
INSERT INTO stat_daily SELECT ... ;
DELETE ์ INSERT ๋ ์ค์ด๋ผ ๊ฐ๋จํ๊ณ ๋ค์ ๋๋ ค๋ ๊ฒฐ๊ณผ๊ฐ ๊ฐ์ ๋ณด์๋ค.
๋ฌธ์ ๋ DELETE ๋ค INSERT ์ ์ ๋ฉ์ถ๋ฉด ์๋ฌด๊ฒ๋ ์๋ค๋ ๊ฒ์ด์๋ค. stat_daily ์ ๊ฐฑ์ ์ ์คํจํ๋๋ฐ ๊ฐฑ์ ํ๊ธฐ ์ ๊ฐ๊น์ง ํจ๊ป ์์ ๊ฒ์ด๋ค.
์ฑ๊ณตํ๋ ๊ฒฝ๋ก๋ง ๋ณด๊ณ ๋ง๋ค๋ฉด ์คํจ ๊ฒฝ๋ก๊ฐ ๊ทธ๋๋ก ๋ฐฉ์น๋๋ค. ์คํจํ์ ๋ ์ด์ ์ํ๊ฐ ์ ์ง๋๋๋๊ฐ ์ด ์ข ๋ฅ ์ฒ๋ฆฌ์ ๊ธฐ์ค์ด์๋ค.
์กฐ์น โ ํ ํธ๋์ญ์ ์ ๋ฃ์๋ค
๋จผ์ ๋ ์ฟผ๋ฆฌ๋ฅผ ํ ํธ๋์ญ์ ์ผ๋ก ๊ฐ์๋ค.
$db->transaction(function () use ($date) {
$db->query("DELETE FROM stat_daily WHERE stat_date = ?", [$date]);
$db->query("INSERT INTO stat_daily SELECT ...", [$date]);
});
์ค๊ฐ์ ์คํจํ๋ฉด ROLLBACK ๋์ด ์ง์ด ๊ฒ๋ ํจ๊ป ๋๋์๊ฐ๋ค.
์ด ํ ์ค๋ก ์์ค ์์ฒด๋ ๋๋ถ๋ถ ํด๊ฒฐ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ง๊ณ ์์ฒด๊ฐ ์ค๋ ๊ฑธ๋ ค์ ๊ทธ๋์ stat_daily ๊ฐ ์ ๊ฒจ ์์๊ณ ํ๋ฉด์์ ๊ทธ ํ๋ฅผ ์ฝ๋ ๊ฒ์ด ๋ฐ๋ ธ๋ค.
์ค์ โ ์๋ก ๋ง๋ค๊ณ ๋ฐ๊ฟ์น๊ธฐ
์ ์ฒด๋ฅผ ๋ค์ ๋ง๋ค ๋๋ ํธ๋์ญ์ ์ผ๋ก ๊ฐ์ธ๋ ๊ฒ ๋์ ์๋ก ๋ง๋ค๊ณ ๋ฐ๊ฟ์น๊ธฐํ๋ ์ชฝ์ ๊ณจ๋๋ค. ์ด์ ๋ ๋ง๋๋ ๋์ ์ ํ๊ฐ ๊ทธ๋๋ก ์๋น์คํด์๋ค.
CREATE TABLE stat_daily_new LIKE stat_daily;
INSERT INTO stat_daily_new SELECT ...;
RENAME TABLE stat_daily TO stat_daily_old, stat_daily_new TO stat_daily;
DROP TABLE stat_daily_old;
stat_daily_new ์ ๋ค ๋ง๋ค๊ณ ๋์ ์ด๋ฆ๋ง ๋ฐ๊พธ๋๋ฐ RENAME TABLE ์ ์์๊ฐ์ด๋ค.
๋ง๋๋ ๋์ ์ ํ๊ฐ ๊ทธ๋๋ก ์๋น์คํ๋ค. ์คํจํ๋ฉด ์ ํ๋ง ๋ฒ๋ฆฌ๋ฉด ๋๊ณ ์ฝ๋ ์ชฝ์ ์ํฅ์ ์ ๋ฐ๋๋ค.
RENAME TABLE ์ ๋์ ๊ฐ์ด ์ด ๊ฒ์ ๊ทธ ์ฌ์ด์ stat_daily ๋ผ๋ ์ด๋ฆ์ด ์๋ ์๊ฐ์ ๋ง๋ค์ง ์๊ธฐ ์ํด์์๋ค. MySQL 5.7 ์ฐธ๊ณ ๋งค๋ด์ผ์ ์ด ๋ฌธ์ฅ์ด ์์์ ์ผ๋ก ์ํ๋ผ ๊ทธ๋์ ๋ค๋ฅธ ์ธ์
์ด ์ด๋ ํ์๋ ์ ๊ทผํ์ง ๋ชปํ๋ค๊ณ ์ ๋๋ค.
์ ํ์ง โ ์ผ๋ถ๋ง ๊ฐฑ์ ํ๋ ๊ฒฝ์ฐ
ํ๋ฃจ์น๋ง ๊ฐฑ์ ํ ๋๋ ํ๋ฅผ ํต์งธ๋ก ๋ฐ๊ฟ ์ ์์๋ค.
INSERT INTO stat_daily (stat_date, ...)
VALUES (?, ...)
ON DUPLICATE KEY UPDATE order_count = VALUES(order_count), amount = VALUES(amount);
ON DUPLICATE KEY UPDATE ๋ก ๋ฎ์ด์ฐ๋ฏ๋ก ์คํจํด๋ ์๋ ๊ฐ์ด ๋จ๋๋ค.
์ ์ผ ์ธ๋ฑ์ค๊ฐ ์์ด์ผ ๋์ํ๋ค.
ALTER TABLE stat_daily ADD UNIQUE KEY uk_date (stat_date);
uk_date ๋ก ์ด๋ค ๊ฐ์ด ๊ฐ์ผ๋ฉด ๊ฐ์ ํ์ธ์ง๊ฐ ์ ์๋๋ค. ์ค๊ฐ์ ๋ฉ์ถฐ๋ ์ฒ๋ฆฌ๋ ๋ ์ง๊น์ง๋ ๊ฐฑ์ ๋๊ณ ๋๋จธ์ง๋ ์ ๊ฐ์ด ๊ทธ๋๋ก ๋จ๋๋ค.
์ฃผ์ โ ์ด์ํ ๊ฐ์ ๊ฑฐ๋ฅด๋ ๊ฒ์ฌ
๋ฎ์ด์ฐ๊ธฐ ์ ์ ์ ๊ฐ์ด ๋ง์ด ๋๋์ง ๋ดค๋ค.
$new = $this->calculate($date);
$old = $this->repo->get($date);
if ($old && $new['order_count'] < $old['order_count'] * 0.5) {
log_error("์ง๊ณ ๊ฒฐ๊ณผ๊ฐ ์ด์ ์ ์ ๋ฐ ๋ฏธ๋ง์
๋๋ค. ๊ฐฑ์ ํ์ง ์์ต๋๋ค.");
notify("์ง๊ณ ํ์ธ ํ์: {$date}");
return;
}
$this->repo->upsert($date, $new);
order_count ๊ฐ ๊ฐ์๊ธฐ ์ ๋ฐ ์๋๋ก ์ค๋ฉด ์๋ณธ์ ๋ฌธ์ ๊ฐ ์์ ์ ์์ด upsert ๋ฅผ ๊ฑด๋๋ด๋ค.
์ค์ ๋ก ํ ๋ฒ ๊ฑธ๋ ธ๋๋ฐ ์๋ณธ ํ์ ์ผ๋ถ๊ฐ ์์ง ์ ๋ค์ด์ ์์๋ค. ๊ทธ๋๋ก ๋ฎ์์ผ๋ฉด ์ ๊ฐ๋ ํจ๊ป ์์์ ๊ฒ์ด๋ค.
๋ฐ๊พธ๊ธฐ ์ ๊ฐ๋ ๋จ๊ธฐ๊ฒ ํ๋ค.
INSERT INTO stat_daily_history (stat_date, order_count, amount, replaced_at)
SELECT stat_date, order_count, amount, NOW() FROM stat_daily WHERE stat_date = ?;
stat_daily_history ์ replaced_at ๊ณผ ํจ๊ป ๋ฐ๋ ์ด๋ ฅ์ด ์์ธ๋ค.
์ง๋์ฃผ์ ๋ณธ ์ซ์์ ๋ค๋ฅด๋ค๋ ๋ง์ด ๋์์ ๋ ์ด๊ฒ์ผ๋ก ํ์ธํ๋ค. ์๋ณธ์ด ๋์ค์ ์ ์ ๋ผ์ ์ง๊ณ๊ฐ ๋ฐ๋ ๊ฒ์ด์๊ณ ์ด๋ ฅ์ด ์์ด ์ธ์ ๋ฌด์์ด ๋ฐ๋์๋์ง ์ค๋ช ํ ์ ์์๋ค.
๊ฒ์ฆ โ ์ผ๋ถ๋ฌ ๋ง๋ ์ค๊ฐ ์คํจ
๋ฐ๊พผ ๋ฐฉ์์ด ์ค์ ๋ก ๋ค๋ฅธ์ง ํ์ธํ๋ค.
if (getenv('FAIL_AFTER_DELETE')) { throw new RuntimeException('์ํ์ฉ ์คํจ'); }
FAIL_AFTER_DELETE ๋ฅผ ๊ฑธ์ด ์ง์ด ์งํ์ ์คํจํ๊ฒ ๋ง๋ค์๋ค.
์ ๋ฐฉ์์์๋ ๊ทธ ์๋ฆฌ์์ ๋ฐ์ดํฐ๊ฐ ์์ด์ก๊ณ ๋ฐ๊พผ ๋ฐฉ์์์๋ ์ ๊ฐ์ด ๊ทธ๋๋ก ์์๋ค. ์ด๊ฒ์ ์ ํด ๋ดค์ผ๋ฉด ํธ๋์ญ์ ์ด ์ ๋๋ก ๊ฑธ๋ ธ๋์ง๋ ๋ชฐ๋์ ๊ฒ์ด๋ค.
์ ๋ฆฌ
- ์ง์ฐ๊ณ ๋ค์ ๋ฃ๋ ๋ฐฉ์์ ์ค๊ฐ์ ๋ฉ์ถ๋ฉด ์๋ฌด๊ฒ๋ ์๋ค
- ๊ฐฑ์ ์คํจ๊ฐ ๊ทธ๋๋ก ๋ฐ์ดํฐ ์์ค์ด ๋๋ค
- ์ฑ๊ณต ๊ฒฝ๋ก๋ง ๋ณด๊ณ ๋ง๋ค๋ฉด ์คํจ ๊ฒฝ๋ก๊ฐ ๋ฐฉ์น๋๋ค
- ํ ํธ๋์ญ์ ์ ๋ฃ์ผ๋ฉด ๋๋์๊ฐ์ง๋ง ๊ทธ๋์ ์ ๊ธด๋ค
- ์ ์ฒด๋ฅผ ๋ค์ ๋ง๋ค ๋๋ ์๋ก ๋ง๋ค๊ณ ์ด๋ฆ์ ๋ฐ๊พผ๋ค
- ๋ง๋๋ ๋์ ์ ํ๊ฐ ์๋น์คํ๋ค
- ์ผ๋ถ๋ง ๊ฐฑ์ ํ ๋๋ ์ง์ฐ์ง ๋ง๊ณ ๋ฎ์ด์ด๋ค
- ๋ฎ์ด์ฐ๋ ค๋ฉด ์ ์ผ ์ธ๋ฑ์ค๊ฐ ํ์ํ๋ค
- ์ ๊ฐ์ด ์ด์ํ๋ฉด ๋ฎ์ง ์๊ณ ์ด์ ๊ฐ๊ณผ ๋น๊ตํด ํ๋จํ๋ค
- ๋ฐ๊พธ๊ธฐ ์ ๊ฐ์ ์ด๋ ฅ์ผ๋ก ๋จ๊ธด๋ค
- ์ผ๋ถ๋ฌ ์ค๊ฐ์ ์คํจ์์ผ ๋ฐ๊พผ ๋ฐฉ์์ด ๋ค๋ฅธ์ง ํ์ธํ๋ค