DevLog ๐ถ
[Real MySQL 8.0] ํธ๋์ญ์ ๊ณผ MySQL / InnoDB์ ๋ฝ (Lock) ๋ณธ๋ฌธ
[Real MySQL 8.0] ํธ๋์ญ์ ๊ณผ MySQL / InnoDB์ ๋ฝ (Lock)
dolmeng2 2023. 6. 18. 17:50๐ฑ ๋ค์ด๊ฐ๊ธฐ ์
์ด๋ฒ ํฌ์คํ
์์๋ ํธ๋์ญ์
์ ๋ํ ๊ฐ๋จํ ๊ฐ๋
๊ณผ, MySQL๊ณผ InnoDB ์คํ ๋ฆฌ์ง์์ง์์ ์ ๊ณตํ๋ ๋ฝ์ ๋ํด์ ์์๋ณด์.
๐ฑ ํธ๋์ญ์
ํธ๋์ญ์
์ ํ๋์ ๋
ผ๋ฆฌ์ ์ธ ์์
์
์ ์์ ํ ์ ์ฉ(commit)๋๊ฑฐ๋, ์๋ฌด๊ฒ๋ ์ ์ฉ๋์ง ์์ (rollback)์ ๋ณด์ฅํด์ผ ํ๋ค.
InnoDB์ MyISAM ํ
์ด๋ธ์ ํธ๋์ญ์
๊ด์ ์์๋ ์ฐจ์ด๋ฅผ ๋ณด์ด๋๋ฐ, ์ด๋ฅผ ํ์ธํด๋ณด์.
์ฐ์ , ์๋์ ๊ฐ์ด myISAM๊ณผ innoDB๋ฅผ ์ฌ์ฉํ 2๊ฐ์ ํ
์ด๋ธ์ ๋ง๋ค์.
CREATE TABLE tb_myisam (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=MYISAM;
CREATE TABLE tb_innodb (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=innodb;
๊ทธ๋ฆฌ๊ณ , ๊ฐ๊ฐ์ ๋ํด์ ๋ ์ฝ๋๋ฅผ 1๊ฐ์ฉ ์ ์ฅํด๋ณด์.
insert into tb_myisam (id) values (3);
insert into tb_innodb (id) values (3);
์ดํ, auto commit ๋ชจ๋๋ฅผ ํ์ฑํํ ๋ค์ ๋ค์๊ณผ ๊ฐ์ด ๋ ์ฝ๋๋ฅผ ์ถ๊ฐํด๋ณด์.
๐ก AUTO COMMIT์ด๋?
์ฌ์ฉ์๊ฐ commit ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ง ์์๋ SQL๋ฌธ์ด ์ฑ๊ณต์ ์ผ๋ก ์คํ๋๋ฉด ์๋์ผ๋ก ์ปค๋ฐ์, ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ์์์ ๋กค๋ฐฑ์ ํด์ค๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก๋ ํ์ฑํ๊ฐ ๋์ด ์๋ค.
set autocommit = on;
insert into tb_myisam (id) values (1), (2), (3);
insert into tb_innodb (id) values (1), (2), (3);
๋น์ฐํ primary key๋ก ์ค์ ๋ ์ปฌ๋ผ์ ๋์ผํ ๊ฐ์ ๋ฃ์ผ๋ ค๊ณ ํ๊ธฐ ๋๋ฌธ์, ๋ ํ
์ด๋ธ ๋ชจ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
ํ์ง๋ง, ์ค์ ๋ก select ํ์ ๋์ ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ๋ค.
myISAM์ผ๋ก ์์ฑํ ํ
์ด๋ธ์ ๊ฒฝ์ฐ 1, 2, 3 ๋ชจ๋๊ฐ ๊ทธ๋๋ก ์ฝ์
๋์ด ์๋ ๊ฒ์ด๋ค.
์ด๋, ๋กค๋ฐฑ์ด ๋ฐ์ํ์ง ์์๋ค๊ธฐ๋ณด๋ค๋, ์ฟผ๋ฆฌ๋ฌธ์์ 1, 2๋ ์ฝ์
์ฑ๊ณตํ์ง๋ง 3์ ์ฝ์
ํ ์๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ 3์ ๋ํด์๋ง ์ฝ์
ํ์ง ์๊ณ ์ข
๋ฃํ ๊ฒ์ด๋ค. ๋ฐ๋ฉด์, innoDB์ ๊ฒฝ์ฐ ์ฐ๋ฆฌ๊ฐ ํํ ์๊ฐํ ๊ฒ์ฒ๋ผ 1, 2, 3 ๋ชจ๋๋ฅผ ์ฝ์
ํ๋ ์ฟผ๋ฆฌ์ ๋ํด์ ๋กค๋ฐฑ์ ํ๋ค.
์ด๋ฐ ํ์์ 'Partial Update'๋ผ๊ณ ํ๋ฉฐ, ๋ฐ์ดํฐ์ ๊ฒฝํฉ์ฑ์ ๋ง์ถ๋ ๋ฐ ์ด๋ ค์์ ์ฃผ๋ ์์ ์ค ํ๋์ด๋ค.
์ innoDB๋ฅผ ๋ง์ด๋ค ์ฌ์ฉํ๋์ง ํ ๊ฐ์ง ์ด์ ๋ฅผ ๋ ์์๊ฐ๋ค ๐
๐ฑ ๋ฝ - MySQL
MySQL์์ ๋ฝ์ ํฌ๊ฒ ์คํ ๋ฆฌ์ง ์์ง ๋ ๋ฒจ๊ณผ MySQL ์์ง ๋ ๋ฒจ๋ก ๋๋ ์ ์๋ค.
MySQL ์์ง ๋ ๋ฒจ์ ๋ฝ์ ๊ธ๋ก๋ฒ ๋ฝ, ํ
์ด๋ธ ๋ฝ, ๋ฉํ๋ฐ์ดํฐ ๋ฝ, ๋ค์๋ ๋ฝ์ ์ ๊ณตํ๋ค.
๐ฌ ๊ธ๋ก๋ฒ ๋ฝ
MySQL์์ ์ ๊ณตํ๋ ๋ฝ ์ค์์ ๊ฐ์ฅ ๋ฒ์๊ฐ ํฐ ๋ฝ์ด๋ค.
FLUSH TABLES WITH READ LOCK
ํ๋์ ์ธ์
์์ ๊ธ๋ก๋ฒ ๋ฝ์ ํ๋ํ๋ฉด ๋ค๋ฅธ ์ธ์
์์ select๋ฅผ ์ ์ธํ ๋๋ถ๋ถ์ DDL / DML ๋ฌธ์ฅ ์คํ ์, ๊ธ๋ก๋ฒ ๋ฝ์ด ํด์ ๋ ๋๊น์ง ๊ณ์ ๋๊ธฐ ์ํ๋ก ๋จ๊ฒ ๋๋ค. MySQL ์๋ฒ ์ ์ฒด์ ์ํฅ์ ์ฃผ๊ธฐ ๋๋ฌธ์ ์์
์ค์ธ ํ
์ด๋ธ์ด๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋์ด์ ๋์ผํ๊ฒ ์ํฅ์ ์ค๋ค.
๋ง์ฝ, ๊ธ๋ก๋ฒ ๋ฝ์ด ์คํ๋๊ธฐ ์ ์ ์ฐ๊ธฐ ๋ฝ์ด ๊ฑธ๋ฆฐ SQL์ด ์คํ๋๋ค๋ฉด, ๊ธฐ์กด์ ์ฐ๊ธฐ ๋ฝ์ด ์์ ํ ํด์ ๋ ์ดํ์ ๊ธ๋ก๋ฒ ๋ฝ์ด ๊ฑธ๋ฆฌ๊ฒ ๋๋ค. ์ฆ, ํ์ฌ ์คํ ์ค์ธ ๋ชจ๋ ์ฟผ๋ฆฌ๊ฐ ์๋ฃ๋์ด์ผ๋ง ๊ธ๋ก๋ฒ ๋ฝ์ ์คํํ ์ ์๋ ๊ฒ์ด๋ค. ํ์ง๋ง, MySQL 8.0๋ถํฐ Xtrabackup, Enterprise Backup ๊ฐ์ด '๋ฐฑ์
๋ฝ'์ด๋ผ๋ ์กฐ๊ธ ๋ ๊ฐ๋ฒผ์ด ๋ฝ์ด ์ถ๊ฐ๋์๋ค.
# ๋ฐฑ์
๋ฝ
LOCK INSTANCE FOR BACKUP;
# ๋ฝ ํด์
UNLOCK INSTANCE;
๋ฐฑ์
๋ฝ์ ๊ฒฝ์ฐ ํน์ ์ธ์
์์ ํ๋ํ๋ฉด ๋ชจ๋ ์ธ์
์์ ์๋์ ๊ฐ์ ์ ๋ณด๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ํ ์ด๋ธ ๋ฑ, ๋ชจ๋ ๊ฐ์ฒด์ ์์ฑ ๋ฐ ๋ณ๊ฒฝ, ์ญ์
- REPAIR TABLE / OPTIMIZE TABLE
- ์ฌ์ฉ์ ๊ด๋ฆฌ ๋ฐ ๋น๋ฐ๋ฒํธ ๋ณ๊ฒฝ
ํ์ง๋ง, ์ผ๋ฐ์ ์ธ ํ
์ด๋ธ์ ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ํ์ฉํ๊ธฐ ๋๋ฌธ์ ์ด์ ์ ๊ธ๋ก๋ฒ ๋ฝ๋ณด๋ค ํ์คํ ์ํ๋ ๋ฝ์ ์ฌ์ฉํ ์ ์๋ค.
๊ธฐ์กด์ ๊ธ๋ก๋ฒ ๋ฝ์ ์ฌ์ฉํ๋ค๋ฉด ๋ณต์ ์ฉ ์๋ฒ (๋ ํ๋ฆฌ์นด ์๋ฒ)์์ ๋ฐ์ดํฐ์ ๋ณต์ ๊ฐ ์ผ์ด๋๋ ๋์ค์ ๊ธฐ์กด ์๋ฒ์์ ์ค๋ฅ๊ฐ ์๊ฒผ๋ค๋ฉด ๋ฐฑ์
์ญ์ ๊ณ์ ์ง์ฐ / ํน์ ์คํจํ์ ๊ฒ์ด๋ค. ๋ฐฑ์
์ด๋ผ๋ ๊ฒ์ ์๋นํ ์ค๋ ๊ฑธ๋ฆฌ๋ ์์
์ด๊ธฐ ๋๋ฌธ์ ์คํจ ์์ ๋ ๋ค์ ์์ฒญ๋ ์๊ฐ์ ๋ค์ฌ์ผ ํ๊ณ , ๊ทธ๋ฌ๋ฉด ์๋น์ค ์์ฒด์๋ ์ํฅ์ด ํฌ๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ '๋ฐฑ์
๋ฝ'์ด๋ผ๋ ๊ฒ์ด ๋์
๋์๋ค.
๐ฌ ํ ์ด๋ธ ๋ฝ
ํ ์ด๋ธ ๋ฝ์ ๊ฒฝ์ฐ ํ ์ด๋ธ ๋จ์๋ก ์ค์ ํ๋ ์ ๊ธ์ด๋ฉฐ, ๋ช ์์ (explicit) / ์์์ (implicit) ๋ฝ์ ํ๋ํ ์ ์๋ค.
# ๋ฝ ํ๋
LOCK TABLES table_name [READ | WRITE]
# ๋ฝ ํด์
UNLOCK TABLES
๋ฝ์ ํ๋ํ ๋ 2๊ฐ์ ์ต์
์ ์ค ์ ์๋๋ฐ, ํ๋๋ READ, ํ๋๋ WRITE์ด๋ค.
READ
- ํ ์ด๋ธ์ ๋ํ ์ฝ๊ธฐ ๋ฝ ํ๋
- ๋ค๋ฅธ ์ธ์ ์ด ๋์์ ๊ฐ์ ํ ์ด๋ธ์ ๋ํ ์ฝ๊ธฐ ๋ฝ ํ๋ ๊ฐ๋ฅ
- ํ ์ด๋ธ์ ๋ํ ๋ด์ฉ์ ์ฝ์ ์ ์์ง๋ง, ์์ ์ ๋ถ๊ฐ๋ฅ
- ๋์์ ๋ค๋ฅธ ์ธ์ ์ด ํด๋น ํ ์ด๋ธ์ ๋ํด์ ์ฐ๊ธฐ ๋ฝ ํ๋ ๋ถ๊ฐ๋ฅ
WRITE
- ํ ์ด๋ธ์ ๋ํ ์ฐ๊ธฐ ๋ฝ ํ๋
- ๋ค๋ฅธ ์ธ์ ์ด ๋์์ ๊ฐ์ ํ ์ด๋ธ์ ๋ํ ์ฝ๊ธฐ ๋ฝ, ์ฐ๊ธฐ ๋ฝ ํ๋ ๋ถ๊ฐ๋ฅ
- ์ฐ๊ธฐ ๋ฝ์ ํ๋ํ ์ธ์ ์ ํ ์ด๋ธ์ ๋ด์ฉ์ ์ฝ๊ณ ์์ ํ ์ ์์
๋ช
์์ ๋ฝ์ ๊ฒฝ์ฐ ์์ ๊ฐ์ด ์ฟผ๋ฆฌ๋ฅผ ํตํด์ ์ง์ ์ ์ผ๋ก ์ ์ธํ๋ ๋ฐฉ๋ฒ์ด๋ฉฐ, ๋ฌต์์ ๋ฝ์ ๊ฒฝ์ฐ ํ
์ด๋ธ์ ๋ณ๊ฒฝํ๋ ์ฟผ๋ฆฌ๋ฅผ ์คํํ์ ๋ MySQL ์๋ฒ๊ฐ ํด๋น ํ
์ด๋ธ์ ๋ฝ์ ์ค์ ํ๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ ๋ค์, ๋ฐ๋ก ๋ฝ์ ํด์ ํ๋ ํํ๋ก ์ฌ์ฉ๋๋ค. ์๋์ผ๋ก ํ ๋น ๋ฐ ํด์ ๊ฐ ์ผ์ด๋๊ธฐ ๋๋ฌธ์ ํธ๋ฆฌํ์ง๋ง, innoDB์ ๊ฒฝ์ฐ ๋ ์ฝ๋ ๊ธฐ๋ฐ ๋ฝ์ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ ํ
์ด๋ธ ๋ฝ์ด ์คํ๋๋๋ผ๋ DML์์๋ ๋ฌด์๋๊ณ , DDL์์๋ง ์ํฅ์ ์ค๋ค.
๐ฌ ๋ค์๋ ๋ฝ
ํ
์ด๋ธ, ๋ ์ฝ๋๊ฐ ์๋ ์์์ ๋ฌธ์์ด์ ๋ํด ์ ๊ธ์ ํ๋ํ ์ ์๋ค. (์ผ์ข
์ ๋ณ์ ๋๋?)
1๋์ DB ์๋ฒ์ ์ฌ๋ฌ ๋์ ์น ์๋ฒ๊ฐ ์ ์ํ์์ ๋ ํน์ ์ ๋ณด๋ฅผ ๋๊ธฐํํด์ผ ํ๋ ์ํฉ์์ ๋ค์๋๋ฝ์ ์ฌ์ฉํ ์ ์๋ค.
# hello๋ผ๋ ๋ฌธ์์ด์ ๋ํด์ ์ ๊ธ ํ๋
# ์ด๋ฏธ ์ฌ์ฉ ์ค์ด๋ผ๋ฉด 2์ด ๋๊ธฐ ํ ํด์
SELECT GET LOCK('hello', 2);
# ์ ๊ธ์ด ์ค์ ๋์ด ์๋์ง ํ์ธ
SELECT IS_FREE_LOCK('hello');
# hello๋ผ๋ ๋ฌธ์์ด์ ๋ํด ํ๋ํ๋ ์ ๊ธ ํด์
SELECT RELEASE_LOCK('hello');
3๊ฐ์ง ์ฟผ๋ฆฌ ๋ชจ๋ select๋ฌธ์ ๊ฒฐ๊ณผ๋ก ๋ฝ์ ์ ์์ ์ผ๋ก ํ๋ํ๊ฑฐ๋ ํด์ ํ๋ฉด 1์, ์๋๋ผ๋ฉด null์ด๋ 0์ ๋ฐํํ๋ค.
# ๋์์ ๋ฝ ๊ฑธ๊ธฐ
SELECT GET_LOCK('hello1', 10);
SELECT GET_LOCK('hello2', 10);
# ๋ชจ๋ ํด์
SELECT RELEASE_ALL_LOCKS();
๋ค์๋ ๋ฝ์ ๊ฒฝ์ฐ ๋ณต์กํ ์กฐ๊ฑด์ผ๋ก ๋ ์ฝ๋๋ฅผ ํ๊บผ๋ฒ์ ๋ง์ด ๋ณ๊ฒฝํ ๋ ์ฌ์ฉํ๋ฉฐ, MySQL 8.0๋ถํฐ๋ ๋ค์๋ ๋ฝ์ ์ค์ฒฉํ์ฌ ์ฌ์ฉํ๋ ๊ฒ์ ๊ฐ๋ฅํ๋๋ก ๋ง๋ค์๋ค.
๐ฌ ๋ฉํ๋ฐ์ดํฐ ๋ฝ
ํ
์ด๋ธ์ด๋ ๋ทฐ์ ์ด๋ฆ์ด๋ ๊ตฌ์กฐ๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒฝ์ฐ, ๋ฉํ๋ฐ์ดํฐ ๋ฝ์ ํ๋ํ๋ค.
๋ช
์์ ์ผ๋ก ํ๋ํ๊ฑฐ๋ ํด์ ๊ฐ ์ ๋๋ฉฐ RENAME ๋ฑ์ ์ฟผ๋ฆฌ๋ฅผ ์คํํ ๋ ์๋์ผ๋ก ํ๋ํ๋ ์ ๊ธ์ด๋ค.
# ์ด๋ฌ๋ฉด tb_1, tb_2 ๋ชจ๋์ ๋ํด์ ์ ๊ธ์ ์ค์ ํ๋ค
RENAME TABLE tb_1 TO tb_2;
ํ
์ด๋ธ์ ์ด๋ฆ์ ๋ณ๊ฒฝํ ๋ ํน์๋ ์ค์๋น์ค์์ 'ํด๋นํ๋ ํ
์ด๋ธ์ด ์์ต๋๋ค' ๊ฐ์ ๊ฒฝ๊ณ ๋ฉ์์ง๊ฐ ๋จ์ง ์๋๋ก ํ๊ธฐ ์ํด์๋, ํ๋์ rename table ์ฟผ๋ฆฌ์ ์ฌ๋ฌ ๊ฐ์ ์กฐ๊ฑด์ ๋ฃ์ด๋๋ฉด ๋๋ค.
RENAME TABLE tb_1 to tb_2, tb_3 to tb_1
์ด๋ ๊ฒ ๋๋ฉด tb_1์ ๋ํด์๋ tb_2๋ก ๋ฐ๊พธ๋ฉด์, ๊ธฐ์กด์ tb_3์ tb_1์ด๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ฐ๋ก ๋ฐ๊พธ๊ธฐ ๋๋ฌธ์ ๊ฒฝ๊ณ ๋ฉ์์ง๊ฐ ๋จ์ง ์๋๋ค.
๐ก ํ ์ด๋ธ ๋ฝ + ๋ฉํ๋ฐ์ดํฐ ๋ฝ
๋ก๊ทธ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ๋ก๊ทธ ํ
์ด๋ธ์ด ์๋ค๊ณ ์๊ฐํด๋ณด์. ๋จ์ํ ์ฌ์ฉ์์ ์น ์์ฒญ์ ๋ํ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ธฐ ๋๋ฌธ์ INSERT๋ง ์งํ๋๋ ํ
์ด๋ธ์ด๋ค. ํ์ง๋ง, ํ
์ด๋ธ์ ๊ตฌ์กฐ๋ฅผ ๋ณ๊ฒฝํด์ผ ํ๋ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น?
๊ธฐ๋ณธ์ ์ผ๋ก MySQL์ DDL์ ์ฌ์ฉํ๋ค๋ฉด ๋จ์ผ ์ค๋ ๋๋ก ๋์ํ๊ธฐ ๋๋ฌธ์ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆด ๊ฒ์ด๋ค.
๋ณดํต ์ด๋ฐ ๊ฒฝ์ฐ์๋ ์๋ก์ด ํ
์ด๋ธ์ ์์ฑํ๊ณ , ๋น๊ต์ ์ต๊ทผ ๋ฐ์ดํฐ๋ฅผ ์ ์ธํ๊ณ PK๋ก ๋ฒ์๋ฅผ ๋๋ ๋ ์ฝ๋๋ค์ ๋ํด ์ฌ๋ฌ ๊ฐ์ ์ค๋ ๋๋ก ๋ณต์ฌํ๋ ๊ฒ ์ผ๋ฐ์ ์ด๋ค.
INSERT INTO tb_new SELECT * FROM tb_origin WHERE id >= 0 AND id <= 10000;
๊ทธ๋ฆฌ๊ณ , ๋จ์ ๋ฐ์ดํฐ์ ๋ํด์๋ ์์ด ์ ๊ธฐ ๋๋ฌธ์ ํ
์ด๋ธ ๊ตฌ์กฐ ๋ณ๊ฒฝ์ด ์ฉ์ดํด์ง๋ฉฐ, ๋น๊ต์ ์๋น์ค์ ๋ ์ํฅ์ ๋ฏธ์น๊ฒ ๋๋ค.
# auto commit ๋ชจ๋ ๋๊ธฐ
SET autocommit = 0;
# ๋์ ํ
์ด๋ธ์ ๋ํด์ ์ฐ๊ธฐ ๋ฝ ํ๋ (ํ
์ด๋ธ ๋ฝ)
LOCK TABLES tb_origin WRITE, tb_new WRITE;
# ๋จ์์๋ ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํด์ฃผ๊ธฐ
SELECT MAX(id) AS @max_id FROM tb_new;
INSERT INTO tb_new SELECT * FROM tb_origin WHERE id > @max_id;
COMMIT;
# ๋ณต์ฌ ์๋ฃ ์ rename ์งํ (๋ฉํ๋ฐ์ดํฐ ๋ฝ)
RENAME TABLE tb_origin TO tb_origin_old, tb_new to tb_origin;
# ์์ ํ
์ด๋ธ ์ญ์
DROP TABLE tb_origin_old
์ด๋ ๊ฒ ๋๋ฉด ํ
์ด๋ธ ๋ฝ์ ๊ฒฝ์ฐ 20000~20100๋ฒ์งธ ๋ ์ฝ๋๋ฅผ ๋ณต์ฌํ ๋๋ง ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์, ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ tb_new๋ก ๋ณต์ฌํ ๋ ์ต๋ํ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํด๋ฌ์ผ ๋ฝ์ ์ ์ ํ๋ ์๊ฐ์ด ์งง์์ง๋ค.
๐ฑ ๋ฝ - innoDB ์คํ ๋ฆฌ์ง ์์ง
innoDB์์๋ MySQL์์ ์ ๊ณตํ๋ ๋ฝ๊ณผ๋ ๋ณ๋๋ก ๋ฝ์ ์ ๊ณตํ๊ณ ์๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก information_schema ํ
์ด๋ธ์ INNODB_TRX, INNODB_LOCKS, INNODB_LOCK_WAITS ํ
์ด๋ธ์ ์๋ ์ ๋ณด๋ค์ ๋ฐํ์ผ๋ก ์ด๋ค ํธ๋์ญ์
์ด ๋ฝ์ ์ ์ ํ๊ณ ๋๊ธฐ ์ค์ธ์ง ์ ์ ์์ผ๋ฉฐ, ์ฌ๋ฌ ๋ชจ๋ํฐ๋ง ๋ฐฉ๋ฒ๋ค์ ํตํด์ ์คํ ๋ฆฌ์ง ์์ง์์ ์ ๊ณตํ๋ ๋ฝ๊น์ง ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋๋ก ๋๊ณ ์๋ค.
innoDB์์๋ ์ด 8๊ฐ์ง์ ๋ฝ์ ์ ๊ณตํ๊ณ ์์ผ๋ฉฐ, ์ด๋ ๋ค์๊ณผ ๊ฐ๋ค.
- Shared / Exclusive Lock
- Intention Lock
- Record Lock
- Gap Lock
- Next-Key Lock
- Insert Intention Lock
- Auto-increment Lock
- Predicate Lock for Spatial Indexes
๐ฌ Shared / Exclusive Lock (๊ณต์ ๋ฝ, ๋ฒ ํ ๋ฝ)
๊ณต์ ๋ฝ(S-Lock)๊ณผ ๋ฐฐํ ๋ฝ(X-Lock)์ด๋ผ๋ ๋ ์ฝ๋ ๋ ๋ฒจ์ ๋ฝ์ด๋ฉฐ, ๊ณต์ ๋ฝ์ ๊ฒฝ์ฐ ํด๋น ๋ฝ์ ๋ณด์ ํ ํธ๋์ญ์
์ด ํด๋น ๋ ์ฝ๋๋ฅผ ์ฝ์ ์ ์๋๋ก ํ๊ณ , ๋ฐฐํ ๋ฝ์ ๊ฒฝ์ฐ ํด๋น ์ ๊ธ์ ๋ณด์ ํ ํธ๋์ญ์
์ด ํ์ ์
๋ฐ์ดํธํ๊ฑฐ๋ ์ญ์ ํ ์ ์๋๋ก ๋ง๋๋ ๊ฒ์ด๋ค.
์์ ๋งํ๋ ํ
์ด๋ธ ๋ฝ์ READ / WRITE ๋ชจ๋์ ๊ฑฐ์ ๋น์ทํ๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
ํธ๋์ญ์
A๊ฐ S-Lock์ ๊ฐ์ง๊ณ ์์ ๋ ํธ๋์ญ์
B๋ S-Lock์ ๋ณด์ ํ ์ ์์ง๋ง, ํธ๋์ญ์
A๊ฐ X-Lock์ ๊ฐ์ง๊ณ ์๋ค๋ฉด ์ด๋ค ๋ฝ ์์ฒญ์ด๋ ํ์ฉ๋์ง ์๊ณ ๊ณ์ ๋๊ธฐํด์ผ ํ๋ค.
๐ฌ Intention Lock (์๋ ๋ฝ)
์๋ ๋ฝ(Intention Lock)์ ๊ฒฝ์ฐ ํ
์ด๋ธ ๋ฝ๊ณผ ๋ ์ฝ๋ ๋ฝ์ด ๊ณต์กดํ ์ ์๋๋ก ๋ง๋ ๋ค.
ํ
์ด๋ธ์ ํน์ ๋ ์ฝ๋์ ๋ํด์ ์ถํ ๋ฝ์ ๊ฑธ๊ฒ ๋ค๊ณ ํํํ๋ ๊ฒ๊ณผ ๊ฐ๋ค.
๋ง์ฝ WRITE ๋ชจ๋์ ํ
์ด๋ธ ๋ฝ์ ๊ฑธ์๋ค๋ฉด, innoDB์์๋ 2๊ฐ์ง์ ํ์
์ผ๋ก ์๋ ๋ฝ์ ์ํํ๋ค.
Intention Shared Lock (IS)
- ํธ๋์ญ์ ์ด ํ ์ด๋ธ์ ๊ฐ๋ณ ๋ ์ฝ๋์ ๊ณต์ ๋ฝ ์ค์
Intention Exclusive Lock (IX)
- ํธ๋์ญ์ ์ด ํ ์ด๋ธ์ ๊ฐ๋ณ ๋ ์ฝ๋์ ๋ฒ ํ ๋ฝ ์ค์
๋ง์ฝ SELECT ... LOCK IN SHARE MODE์ ์คํํ๋ค๋ฉด ํด๋น ํ
์ด๋ธ์ ๋ํด์ ๋จผ์ IS ์ด์์ ๋ฝ์ ๊ฑธ๊ณ , ๊ทธ ๋ค์ ๋ ์ฝ๋์ ๋ํด์ S-Lock์ด ๊ฑธ๋ฆฌ๋ฉฐ, SELECT ... FOR UPDATE์ ๊ฒฝ์ฐ ํด๋น ํ
์ด๋ธ์ ๋ํด์ ๋จผ์ IX ์ด์์ ๋ฝ์ ๊ฑธ๊ณ , ๊ทธ ๋ค์์ ๋ ์ฝ๋์ X-Lock์ด ๊ฑธ๋ฆฐ๋ค. ์ ์ด๋ ๊ฒ 2๋ฒ ๊ฑฐ๋ ๊ฒ์ผ๊น?
- ์ด๋, ํธ๋์ญ์
A์์ ์ด๋ฏธ ํ
์ด๋ธ์ ๋ํด ๋ฝ์ ๊ฑธ์ด๋์๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ํธ๋์ญ์
์์ ํด๋น ํ
์ด๋ธ์ ๋ ์ฝ๋์ ์ ๊ทผํ์ฌ ๋ฝ์ ๊ฑธ์ง ๋ชปํ๋๋ก ํ๊ธฐ ์ํด์์ด๋ค. ์ฐ๊ธฐ ์์
์ ์ด๋ฏธ IX ๋ฝ์ด ๊ฑธ๋ ค ์๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ํ
์ด๋ธ์์ ๋ฉ๋๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ ์๊ฐ ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
์๋๋ ๋ฝ ์ข
๋ฅ์ ๋ฐ๋ฅธ ๋ค๋ฅธ ํธ๋์ญ์
์ ๊ทผ ์ ํธํ์ฑ์ ๋ํ ํ์ด๋ค.
S | IS | X | IX | |
S | ํธํ ๊ฐ๋ฅ | ํธํ ๊ฐ๋ฅ | ์ถฉ๋ | ์ถฉ๋ |
IS | ํธํ ๊ฐ๋ฅ | ํธํ ๊ฐ๋ฅ | ์ถฉ๋ | ํธํ ๊ฐ๋ฅ |
X | ์ถฉ๋ | ์ถฉ๋ | ์ถฉ๋ | ์ถฉ๋ |
IX | ์ถฉ๋ | ํธํ ๊ฐ๋ฅ | ์ถฉ๋ | ํธํ ๊ฐ๋ฅ |
๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ฅผ ๋ณด๋ฉด IS์ ๊ฒฝ์ฐ X, IX์ ๊ฒฝ์ฐ S, X์ ์ ์ธํ๊ณ ์ฌ๋ฌ ํธ๋์ญ์
์์ ๋์์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
๐ฌ Record Lock (๋ ์ฝ๋ ๋ฝ)
๋ ์ฝ๋ ๋ฝ์ ๊ฒฝ์ฐ ๋ ์ฝ๋์ ๋ํด์ ์ ๊ธ์ ๊ฑฐ๋ ๊ฒ์ด๋ค.
innoDB์ ๊ฒฝ์ฐ ๋ ์ฝ๋ ์์ฒด๋ฅผ ์ ๊ทธ๋ ๊ฒ๋ณด๋ค๋, ์ธ๋ฑ์ค์ ๋ ์ฝ๋๋ฅผ ์ ๊ทผ๋ค. ํ์ง๋ง, ์ธ๋ฑ์ค๊ฐ ์๋๋ผ๋ ํด๋ฌ์คํฐ๋ง ํค๋ฅผ ๋ด๋ถ์ ์ผ๋ก ์์ฑํด์คฌ๋ ๊ฒ์ฒ๋ผ, ์ฌ๊ธฐ์๋ ํด๋ฌ์คํฐ ์ธ๋ฑ์ค๋ฅผ ์์์ ์์ฑํด์ฃผ๊ธฐ ๋๋ฌธ์ ํด๋น ์ธ๋ฑ์ค๋ฅผ ๋ ์ฝ๋ ์ ๊ธ์ ์ฌ์ฉํ๋ค.
# id = 1์ธ ๋ ์ฝ๋์ ๋ํด S-Lock
SELECT id FROM tb_1 WHERE id = 1 LOCK IN SHARE MODE;
# id = 1์ธ ๋ ์ฝ๋์ ๋ํด X-Lock
SELECT id FROM tb_1 WHERE id = 1 FOR UPDATE;
๋ ์ฝ๋๊ฐ ์๋ ์ธ๋ฑ์ค์ ๋ ์ฝ๋์ ๋ํด ๋ฝ์ ๊ฑฐ๋ ์ด์ ๋ ์๋์ ๊ฐ๋ค.
- innoDB์ B+ Tree ์ธ๋ฑ์ค๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ฑฐ๋ ๊ฒ์ํ๋๋ฐ, ์ด๋ ์ธ๋ฑ์ค์ ๋ ์ฝ๋๋ฅผ ํ์ํ์ฌ ํน์ ๋ ์ฝ๋๋ฅผ ์ฐพ์๋ด๊ธฐ ๋๋ฌธ์ ์ธ๋ฑ์ค์ ๋ ์ฝ๋์ ๋ํ ์ ๊ทผ์ด ํ์ํ๋ค.
- ๋ํ, ์ธ๋ฑ์ค์ ๋ํด์๋ง ๋ฝ์ ๊ฑธ๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ ํธ๋์ญ์ ๋ค์ด ์ ๊ทผํ๋ ๊ฒฝ์ฐ์๋ ์ถฉ๋์ ์ต์ํํ์ฌ ์ฑ๋ฅ ์์ฒด์๋ ๋์์ ์ค ์ ์๋ค.
๐ฌ Gap Lock (๊ฐญ ๋ฝ)
๊ฐญ ๋ฝ์ ๊ฒฝ์ฐ ๋ ์ฝ๋๊ฐ ์๋ ๋ ์ฝ๋์ ์ธ์ ํ ๋ค๋ฅธ ๋ ์ฝ๋ ์ฌ์ด์ ๊ฐ๊ฒฉ์ ์ ๊ทธ๋ ๊ฒ์ ์๋ฏธํ๋ค. ์ด๋, ์ฒซ ๋ฒ์งธ์ ๋ง์ง๋ง ๋ ์ฝ๋ ์(Negative Infinity) ๋ค(Positive Infinity)์ ๊ฐ์์ ๋ ์ฝ๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๊ณ ์์ฑํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค. ์ด๋ฌํ ๊ฐ์ ๋ ์ฝ๋๋ฅผ 'Supremum' ๊ฐ์ ๋ ์ฝ๋๋ผ๊ณ ํ๋ค.
๊ฐญ ๋ฝ์ ์ฌ์ฉํ๊ฒ ๋๋ฉด, ์กฐํ ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฒ ์คํํ์ ๋ ๋ค๋ฅธ ํธ๋์ญ์
์์ ์์ ์ด ๋ฐ์ํ๋๋ผ๋ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋ฆฌํด๋๋๋ก ๋ณด์ฅํ ์ ์๋ค. ์ฆ, Phantom Read๋ฅผ ๋ฐฉ์งํ๋ ํจ๊ณผ๋ฅผ ๊ฐ์ง๋ค. ์ด๋ ๊ฐญ ๋ฝ์ด ๋ ์ฝ๋ ์ฌ์ด์ ์๋ก์ด ๋ ์ฝ๋๊ฐ ์ฝ์
๋๋ ๊ฒ์ ์ ์ดํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
select * from tb_1 where id between 1 and 10;
์์ ๊ฐ์ ์ฟผ๋ฆฌ๊ฐ ์์ ๋ 1~10 ์ฌ์ด์ X๋ฝ์ด ๊ฑธ๋ฆฌ๋ ๊ฒ๊ณผ ๋์ผํ๊ธฐ ๋๋ฌธ์, ์๋ก์ด ๋ฐ์ดํฐ๊ฐ ์ฝ์
๋๋ ค๋ฉด ๋๊ธฐํด์ผ ๋๋ค.
๋ํ, ๋์ผํ ๊ฐญ์ ๋ํด์ ์๋ก ๋ค๋ฅธ ํธ๋์ญ์
์์ ์ถฉ๋ํ๋ ๋ฝ์ ๊ฐ์ง ์๋ ์๋ค. ์ฆ, ํธ๋์ญ์
A๊ฐ Gap S-Lock์ ๊ฐ์ง๊ณ ์๊ณ , ํธ๋์ญ์
B๊ฐ ๋์ผํ ๊ฐญ์ ๋ํด์ Gap X-Lock์ ๊ฐ์ง ์ ์๋ค. ์ด๋ ํน์ ๋ ์ฝ๋๊ฐ ์ ๊ฑฐ๋์์ ๋ ์๋ก ๋ค๋ฅธ ํธ๋์ญ์
์์ ํด๋น ๋ ์ฝ๋์ ๊ฐ์ง๊ณ ์๋ ๊ฐญ ๋ฝ์ ๋ณํฉํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ถฉ๋์ด ํ์ฉํ๋ ๊ฒ์ด๋ค.
๐ก Where ์ ์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ๊ฒฐ๊ณผ๊ฐ ํ๋์ผ ๋, Record vs Gap ์ค ์ด๋ค ๋ฝ์ด ์ฌ์ฉ๋ ๊น?
- ๊ธฐ๋ณธ์ ์ผ๋ก ์ปฌ๋ผ์ unique index๊ฐ ๊ฑธ๋ ค ์๋ค๋ฉด record lock์ด ์ฌ์ฉ๋๋ค.
- ์ธ๋ฑ์ค๊ฐ ์๊ฑฐ๋, unique ํ์ง ์์ index๋ผ๋ฉด gap lock์ ์ฌ์ฉํด์ผ ํ๋ค.
: ์ธ๋ฑ์ค๊ฐ ์๋ค๋ฉด ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ์กฐํํ๊ธฐ ์ํด ์ค์บํ ์ธ๋ฑ์ค ๋ฒ์์ ๋ํด gap lock์ด ์ ์ฉ๋๊ณ , ์ธ๋ฑ์ค๊ฐ ์๋ค๋ฉด ํ ์ด๋ธ ์ ์ฒด๋ฅผ ์ค์บํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๋ ์ฝ๋์ ๋ํด์ ๋ฝ์ด ๊ฑธ๋ฆฐ๋ค.
๐ฌ Next-Key Lock (๋ฅ์คํธ ํค ๋ฝ)
๋ ์ฝ๋ ๋ฝ๊ณผ ๊ฐญ ๋ฝ์ ํฉ์น ํํ๋ฅผ ๋ฅ์คํธ ํค ๋ฝ์ด๋ผ๊ณ ํ๋ค.
innoDB์์๋ ํ
์ด๋ธ ์ธ๋ฑ์ค๋ฅผ ๊ฒ์ํ๊ฑฐ๋ ์ค์บํ ๋ ์ค์ ์ธ๋ฑ์ค ๋ ์ฝ๋์ ๋ํด S / X-Lock์ ์ค์ ํ์ฌ ๋ ์ฝ๋ ๋จ์ ๋ฝ์ ๊ฑธ๊ฒ ๋๋ค. ํ์ง๋ง, ๋ฅ์คํธ ํค ๋ฝ์ ๊ฒฝ์ฐ ํด๋น ์ธ๋ฑ์ค ๋ ์ฝ๋ ์ด์ ์ ๊ฐญ์๋ ์ํฅ์ ๋ฏธ์น๊ธฐ ๋๋ฌธ์ ํ๋์ ์ธ์
์ด ํน์ ๋ ์ฝ๋ 1๋ฒ์ S / X-Lock์ ๊ฑธ๋ฉด ๋ค๋ฅธ ์ธ์
์ 1๋ฒ ๋ฐ๋ก ์์ ๊ฐญ์ ์๋ก์ด ๋ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๊ฒ ๋๋ค.
์๋ฅผ ๋ค์ด, 10, 11, 13, 20์ ์ธ๋ฑ์ค๊ฐ ๊ฑธ๋ ค ์๋ค๋ฉด ์๋์ ๊ฐ์ ๊ตฌ๊ฐ์์ ๋ฝ์ด ์์ฑ๋๋ค.
- (Negative infinity, 10]
- (10, 11]
- (11, 13]
- (13, 20]
- (20, Positive infinity)
์ ์ดํด๊ฐ ๋์ง ์์ ์๋ ์์ผ๋, ์์๋ฅผ ๋ค์ด๋ณด์. ์๋๋ crew ํ
์ด๋ธ์ ๋ํด id๊ฐ 100 ์ด์์ธ ๋ ์ฝ๋๋ฅผ ์กฐํํ๋ ์ฟผ๋ฆฌ์ด๋ค.
SELECT * FROM crew WHERE id > 100 FOR UPDATE;
์ด๋, id > 100์ ๋ง์กฑํ๋ id = 101์ธ ๋ฆฌ์ฝ๋๋ฅผ ๋ฐ๊ฒฌํ๋ฉด, ํด๋น ๋ ์ฝ๋ ์ง์ ์ ๋ ์ฝ๋์ ๊ทธ ์ฌ์ด ๋ฝ์ด ๊ฑธ๋ฆฐ๋ค. (50 ~ 101 ์ฌ์ด ๊ฐญ ๋ฝ)
์ดํ, id > 100์ ๋ง์กฑํ๋ ๋ ์ฝ๋์ ๋ํด์๋ ๊ฐญ ๋ฝ๊ณผ ๋ ์ฝ๋ ๋ฝ์ด ๊ฑธ๋ฆฌ๊ฒ ๋๋ฉฐ, ์ด๋ id = 150์ด ์ต๋์ด๊ธฐ ๋๋ฌธ์ Positive Infinity Gap Lock์ด ๊ฑธ๋ฆฌ๊ฒ ๋๋ค.
๋ฅ์คํธ ํค ๋ฝ์ ๊ฒฝ์ฐ ๋ฐ์ด๋๋ฆฌ ๋ก๊ทธ๊ฐ ๊ธฐ๋ก๋๋ ์ฟผ๋ฆฌ๊ฐ ๋ ํ๋ฆฌ์นด ์๋ฒ์์ ์คํ๋ ๋, ๊ธฐ์กด ์๋ฒ์์ ๋ง๋ค์ด๋ธ ๊ฒฐ๊ณผ์ ๋์ผํ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค์ด๋ด๋๋ก ๋ณด์ฅํ๋ ๊ฒ์ด ์ฃผ ๋ชฉ์ ์ด๋ค. ๋ก๊ทธ ํฌ๋งท์ ๊ฒฝ์ฐ statement, row, mixed๋ก ๋๋์ด์ง๋๋ฐ, ์๋์ ๊ฐ์ ํน์ง์ ๊ฐ์ง๋ค.
- statement: ๊ฐ์ฅ ์ค๋๋ ํฌ๋งท, ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ผ๋ก๋ถํฐ ์ฌ์ฉ๋๋ ๋ชจ๋ ์ฟผ๋ฆฌ๋ฅผ ์ ์ฅ
- row : ๋ณ๊ฒฝ๋ ๋ชจ๋ ๋ ์ฝ๋์ ๋ํ ์ ๋ณด ๊ธฐ๋ก
- mixed: statement + row๋ฅผ ํผํฉํ์ฌ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ
๊ธฐ์กด์๋ statement ํฌ๋งท์ ๋ฐ์ด๋๋ฆฌ ๋ก๊ทธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ณดํธ์ ์ด์์ผ๋, ์ด ๊ฒฝ์ฐ repeatable-read ์ด์์ ๊ฒฉ๋ฆฌ ์์ค์ ์ฌ์ฉํด์ผ ํ๋ค๋ ์ ๊ณผ (read-committed ์ฌ์ฉ ์ ์คํ ์์ ๋ง๋ค ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง ์ ์์ด์) ์ฟผ๋ฆฌ์ ์คํ๋ง๋ค ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง๋ ๊ฒฝ์ฐ (์ฌ์ฉ์ ์ ์ ํจ์, ํ๋ก์์ ์ฌ์ฉ ๋ฑ) ํด๋น ์ฟผ๋ฆฌ๋ ์ฌ์ฉํ ์ ์์๋ค๋ ๋จ์ ์ด ์์๋ค. ๋ํ, ๋ฅ์คํธ ํค ๋ฝ๊ณผ ๊ฐญ ๋ฝ์ผ๋ก ์ธํด ๋ฐ๋๋ฝ์ด ๋ฐ์ํ ์ ์์ผ๋ ๋ฐ์ด๋๋ฆฌ ๋ก๊ทธ ํฌ๋งท์ ROW ํํ๋ก ๋ฐ๊ฟ์ ๋ฝ ์์ฒด๋ฅผ ์ค์ด๋ ๊ฒ์ด ์ข๋ค. (MySQL 8.0๋ถํฐ๋ ROW ํฌ๋งท์ ๋ฐ์ด๋๋ฆฌ ๋ก๊ทธ๊ฐ ๊ธฐ๋ณธ์ด๋ค.)
๐ฌ Insert Intention Lock (์ฝ์ ์๋ ๋ฝ)
์ฝ์
์๋ ๋ฝ์ INSERT ๊ตฌ๋ฌธ์ด ์คํ๋ ๋ ๋ฌต์์ ์ผ๋ก ์ค์ ๋๋ ์ผ์ข
์ ๊ฐญ ๋ฝ์ด๋ค.
์ฌ๋ฌ ๊ฐ์ ํธ๋์ญ์
์ด ๊ฐญ ๋ด๋ถ์ ์๋ก ๋ค๋ฅธ ์์น์ ์ฝ์
์ ์งํํ๋ ค๊ณ ํ ๋ ๋๊ธฐ ์์ด ์คํ๋๋๋ก ํ๋ ๊ฒ์ด ๋ชฉ์ ์ด๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ฝ์
์๋ ๋ฝ๋ค๋ผ๋ฆฌ๋ ์ถฉ๋์ด ๋ฐ์ํ์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋ง์ฝ id = 3, 7์ธ ๋ ์ฝ๋๊ฐ ์์ ๋ ํธ๋์ญ์
A๋ id = 5๋ฅผ, ํธ๋์ญ์
B๋ id = 4์ ์ฝ์
ํ๋ ์ํฉ์ ๊ฐ์ ํด๋ณด์.
๊ธฐ๋ณธ์ ์ธ ๊ฐญ ๋ฝ์ ๊ฑธ์๋ค๋ฉด ํธ๋์ญ์
A๊ฐ 5๋ฅผ ์ฝ์
ํ๋ ๊ณผ์ ์์ ์ด์ ๋ ์ฝ๋์ธ 3 ~ 5 ์ฌ์ด์ ๊ฐญ ๋ฝ์ด ๊ฑธ๋ฆด ๊ฒ์ด๋ค. ์ด๋, ํธ๋์ญ์
B๊ฐ id = 4์ ์ฝ์
ํ๋ ค๊ณ ํ์ ๋ ์ด๋ฏธ 3~5 ์ฌ์ด์ ๊ฐญ๋ฝ์ด ๊ฑธ๋ ค ์๊ธฐ ๋๋ฌธ์ ์ข
๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํด์ ๋๊ธฐ ์๊ฐ์ด ์กด์ฌํ๋ค.
๋ฐ๋ฉด์, ์ฝ์
์๋ ๋ฝ์ ๊ฑธ์๋ค๋ฉด ํธ๋์ญ์
A๊ฐ 5๋ฅผ ์ฝ์
ํ๋ ๊ณผ์ ์์ 3 ~ 5 ์ฌ์ด์ ์ฝ์
์๋ ๋ฝ์ด ๊ฑธ๋ฆฐ๋ค. ์ด๋, ํธ๋์ญ์
B๊ฐ id = 4๋ฅผ ์ฝ์
ํ๋ ค๊ณ ํ ๋ ์ฝ์
์๋ ๋ฝ์ ์ถฉ๋์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ๋๊ธฐ ์๊ฐ ์์ด ๋ฐ๋ก ์ฝ์
์ด ๊ฐ๋ฅํด์ง๋ค.
์ฝ์
์ ์ํ X-Lock์ ์ป๊ธฐ ์ํด ์ฝ์
์๋ ๋ฝ์ ํตํด์ ๋ฌต์์ ์ผ๋ก ๋ฝ์ ๊ฑธ์ด๋๊ฒ ๋๋ค.
๐ฌ Auto-increment Lock (์๋ ์ฆ๊ฐ ๋ฝ)
MySQL์์๋ auto_increment๋ผ๋ ์ปฌ๋ผ์ ํตํด์ ์๋์ผ๋ก ์ฆ๊ฐํ๋ ๊ฐ์ ๊ด๋ฆฌํ ์ ์๋ค.
auto_increment๊ฐ ์ฌ์ฉ๋ ํ
์ด๋ธ์ ์ฌ๋ฌ ๊ฐ์ ๋ ์ฝ๋๊ฐ ์ฝ์
๋๋ ๊ฒฝ์ฐ, auto_increment ์ญ์ ์ผ๊ด์ฑ์๊ฒ ์ฆ๊ฐํด์ผ ํ๋ค. ์ด๋ฅผ ์ํด์ innoDB์์๋ ์๋ ์ฆ๊ฐ ๋ฝ์ ํตํด (ํ
์ด๋ธ ๋ ๋ฒจ ๋ฝ) ๊ด๋ฆฌํ๋ค.
์๋ ์ฆ๊ฐ ๋ฝ์ ๊ฒฝ์ฐ ๊ธฐ๋ณธ์ ์ผ๋ก insert, replace ๊ฐ์ด ์๋ก์ด ๋ ์ฝ๋๋ฅผ ์ฝ์
ํ๋ ์ฟผ๋ฆฌ์์๋ง ํ์ํ๋ฉฐ, auto_increment ๊ฐ์ ๊ฐ์ ธ์ค๋ ์๊ฐ์๋ง ๋ฝ์ด ๊ฑธ๋ ธ๋ค๊ฐ ์ฆ์ ํด์ ๋๋ค. ํ
์ด๋ธ๋น ๋จ 1๊ฐ๋ง ์กด์ฌํ๊ธฐ ๋๋ฌธ์, 2๊ฐ์ insert๋ฌธ์ด ๋์์ ์คํ๋๋ ๊ฒฝ์ฐ ๋๋จธ์ง ํ๋๋ ๋ฝ์ด ํด์ ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋ค.
๋ช
์์ ์ผ๋ก ์๋ ์ฆ๊ฐ ๋ฝ์ ํ๋ํ๊ณ ํด์ ํ๋ ๋ฐฉ๋ฒ์ ์์ง๋ง, ์ด์ฐจํผ ์์ฒญ ์งง์ ์๊ฐ ๋์ ๊ฑธ๋ ธ๋ค๊ฐ ํด์ ํ๊ธฐ ๋๋ฌธ์ ํฌ๊ฒ ์ํฅ์ ์๋ค. MySQL 5.1๋ถํฐ๋ ์ด๋ค ์์ผ๋ก ์๋ ์ฆ๊ฐ ๋ฝ์ ์ค์ ํ ์ง ์์คํ
๋ณ์๋ก ๊ด๋ฆฌ๋ ๊ฐ๋ฅํ๋ค.
- innodb_autoinc_lock_mode = 0
๋ชจ๋ INSERT ๋ฌธ์ฅ์ ์๋ ์ฆ๊ฐ ๋ฝ์ ์ฌ์ฉํ๋ค. ์ด๋, ํ ์ด๋ธ ์์ค์ ๋ฝ์ ์ ์ฉํ๋ค.
- innodb_autoinc_lock_mode = 1 (MySQL 5.x ๊ธฐ๋ณธ ๊ฐ)
Bulk Inert ์ฌ์ฉ ์ ํ ์ด๋ธ ๋ ๋ฒจ์ ์๋ ์ฆ๊ฐ ๋ฝ์ ์ฌ์ฉํ๊ณ , ๋ช ๋ น๋ฌธ์ด ๋๋ ๋๊น์ง ์ด๋ฅผ ์ ์งํ๊ฒ ๋๋ค.
INSERT ... SELECT, REPLACE ... SELECT, LOAD DATA ๊ฐ์ ๊ตฌ๋ฌธ์์ ์ฌ์ฉํ๋ค.
ํ์ง๋ง, ๋ง์ฝ ์ฝ์ ๋ ๋ ์ฝ๋์ ์๋ฅผ ๋ฏธ๋ฆฌ ์๊ณ ์๋ค๋ฉด, ๋์น (๋ฎคํ ์ค) ์ ์ด ํ์ ํ์ํ ์๋งํผ์ ์๋ ์ฆ๊ฐ ๊ฐ์ ์ป์ด์ ์ํ๋๋ฉฐ, ํ ์ด๋ธ ๋ ๋ฒจ์ ์ ๊ธ์ ๋ฐฉ์งํ๋ค.
๋ ์ฝ๋ ๊ฑด์๋ฅผ ์ ํํ๊ฒ ์ ์ ์๋ ๊ฒฝ์ฐ์๋ ๋ชจ๋ ์๋ ์ฆ๊ฐ ๊ฐ์ด ์ฐ์์ ์ธ ๊ฐ์ด ๋๊ธฐ ๋๋ฌธ์ ์์ ํ๊ฒ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
๊ทธ๋ฌ๋, Mixed-mode insert์ ๊ฒฝ์ฐ ์ฝ์ ํ ํ์ ์๋ณด๋ค ๋ ํฐ ์๋ ์ฆ๊ฐ ๊ฐ์ ํ ๋น๋ ์ ์์์ ์ ์ํด์ผ ํ๋ค.
ex) insert into tb_1 values (1, 'A'), (NULL, 'B')
- ์ด๋ฐ ์์ผ๋ก null ๊ฐ์ด ํผํฉํ์ฌ ๋ค์ด๊ฐ๋ ๊ฒฝ์ฐ.
- innodb_autoinc_lock_mode = 2 (MySQL 8.0 ๊ธฐ๋ณธ๊ฐ)
์๋ ์ฆ๊ฐ ๋ฝ์ ์ ๋ ์ฌ์ฉํ์ง ์๊ณ ๋ฌด์กฐ๊ฑด ๋์น(๋ฎคํ ์ค)๋ฅผ ์ฌ์ฉํ๋ค. auto_increment ๊ฐ์ ์ ๋ํฌ์ฑ / ๋จ์กฐ ์ฆ๊ฐ์ฑ์ ๋ณด์ฅํ๋ค.
๋๋์ ์ฝ์ ์ฟผ๋ฆฌ๊ฐ ์คํ๋ ๋ ๋ค๋ฅธ ํธ๋์ญ์ ์์๋ INSERT๋ฅผ ์ํํ ์ ์๊ธฐ ๋๋ฌธ์ ๋์ ์ฒ๋ฆฌ ์ฑ๋ฅ์ ๋์์ง๋ค. (์ฌ๋ฌ ๋ช ๋ น๋ฌธ์ด ๋์์ ์ซ์๋ฅผ ์์ฑํ ์ ์์) ํ์ง๋ง, ๋จ๊ฑด ์ฝ์ ์ ๊ฒฝ์ฐ auto_increment ๊ฐ ์ฌ์ด์ ๊ฐญ์ด ์กด์ฌํ์ง ์์ง๋ง ์ฌ๋ฌ ๊ฐ๊ฐ ์ฝ์ ๋ ๊ฒฝ์ฐ ๊ฐญ์ด ์กด์ฌํ ์ ์๋ค.
์ด๋ฌํ ์๋ ์ฆ๊ฐ ๋ฝ์ผ๋ก ์ธํด auto_increment์ ๊ฐ์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ ๋ฒ ์ฆ๊ฐํ๋ฉด ์ ๋ ์ค์ด๋ค์ง ์๋ ๊ฒ์ ๊ธฐ๋ณธ์ผ๋ก ํ๋ค.
Predicate Locks for Spatial Indexes์ ๊ฒฝ์ฐ ๊ณต๊ฐ ์ธ๋ฑ์ฑ์ ์ง์ํ๋ค๊ณ ํ๋๋ฐ, ์ดํดํ๊ธฐ ์ด๋ ค์์ ์ฐ์ ํจ์ค...!
๋ด์ฉ์ด ์ด๋ ค์์ ์๋ฏ๋ง๋ฏํ ๊ฒ ๊ฐ๋ค.
๋ค์ ํฌ์คํ
์์๋ ์ธ๋ฑ์ค์ ๋ฝ์ ๊ด๊ณ + ๊ฒฉ๋ฆฌ ์์ค์ ๋ํด์ ์์๋ณด๋๋ก ํ์!