Atomicํ๊ฒ ์คํ๋์ด์ผ ํ๋ SQL๋ค์ ๋ฌถ์ด์ ํ๋์ ์์ ์ฒ๋ผ
์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋งํ๋ค.
ACID(Atomicity, Consistency, Isolation, Durability)์ ํน์ง์ ๊ฐ์ง๋ค.
์ด๋ ๊ฒ ๊ฑฐ๋์ ์์ ์ฑ์ ํ๋ณดํ๋ ๋ฐฉ๋ฒ์ด ํธ๋์ญ์ ์ด๋ค.
๊ฐฑ์ , ์ญ์ ํ๋๋ฐ ์ฒ๋ฆฌ ๋์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ๋ชจ๋ ์์ ์ ์์ํ๋ก ๋๋๋ฆฌ๊ณ , ์ฒ๋ฆฌ ๊ณผ์ ์ด ๋ชจ๋ ์ฑ๊ณตํด์ผ DB์ ๋ฐ์ํ๋ค.
๋ถ๋ถ ์์ ์ด ์คํจํ๋ฉด ํธ๋์ญ์ ์คํ ์ ์ผ๋ก ๋๋๋ฆฝ๋๋ค.
์ด๋ ๋ชจ๋ ์ฐ์ฐ์ ์ทจ์ํ์ง ์๊ณ ์ ํด์ง ๋ถ๋ถ๊น์ง๋ง ๋๋๋ฆฌ๊ณ ์ถ์๋ savepoint๋ฅผ ์จ์ฃผ๋ฉด ๋๋ค.
-- SAVEPOINT ์ง์ !
SAVEPOINT ์ธ์ด๋ธํฌ์ธํธ์ด๋ฆ;
-- SAVEPOINT๋ก ๋กค๋ฐฑ!
ROLLBACK TO ์ธ์ด๋ธํฌ์ธํธ์ด๋ฆ;

BEGIN; -- START TRANSACTION
A์ ๊ณ์ข๋ก๋ถํฐ ์ธ์ถ;
B์ ๊ณ์ข๋ก ์
๊ธ;
END; -- COMMIT
-- โ BEGIN๊ณผ START TRANSACTION์ ๊ฐ์ ์๋ฏธ
-- โ END์ COMMIT์ ๋์ผ
-- โ ๋ง์ผ BEGIN ์ ์ ์ํ๋ก ๋์๊ฐ๊ณ ์ถ๋ค๋ฉด ROLLBACK ์คํ
AUTOCOMMIT : ๋ฐ์ดํฐ ๋ณ๊ฒฝ ์์ ์ ๋ํ SQL ์์ฒด๊ฐ ๋ฐ๋ก ๋ฐ์๋๋ ๊ฒ์ ์๋ฏธํ๋๋ฐ autocommit ์ด ์๋ ์ํ์์๋ ์ฌ๋ฌ์ค์ ๋ช ๋ น์ ํ๋์ ํธ๋์ญ์ ์ผ๋ก ๋ฌถ์์๊ฐ ์๋ค.
-- autocommit ๋ชจ๋ ํ์ธํ๊ธฐ
SHOW VARIABLES LIKE 'AUTOCOMMIT';
-- (ํน์ 1 = ON)์ ์คํ์ผ๋ก ๋ณ๊ฒฝ๊ฐ๋ฅ
SET autocommit=0 -- OFF
๋ทฐ(view)๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์กด์ฌํ๋ ์ผ์ข ์ ๊ฐ์ ํ ์ด๋ธ์ ์๋ฏธํฉ๋๋ค.
์ด๋ฌํ ๋ทฐ๋ ์ค์ ํ ์ด๋ธ์ฒ๋ผ ํ๊ณผ ์ด์ ๊ฐ์ง๊ณ ์์ง๋ง, ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์์ง๋ ์์ต๋๋ค.
์ด๋ฆ์ด ์๋ ์ฟผ๋ฆฌ๊ฐ View๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๋จ์ ์ ์ฅ๋๋ค.
๊ธฐ๋ณธ ๋ฌธ๋ฒ
CREATE VIEW ๋ทฐ์ด๋ฆ AS
SELECT ํ๋์ด๋ฆ1, ํ๋์ด๋ฆ2, ...
FROM ํ
์ด๋ธ์ด๋ฆ
WHERE ์กฐ๊ฑด
-- CREATE ๋ฌธ์ OR REPLACE ์ ์ ์ถ๊ฐํ์ฌ ๊ธฐ์กด์ ์กด์ฌํ๋ ๋ทฐ๋ฅผ ์๋ก์ด ๋ทฐ๋ก ๋์ฒดํ ์ ์๋ค. ๊ธฐ์กด์ ์์ผ๋ฉด ๊ทธ๋ฅ create
CREATE OR REPLACE VIEW test.youji_session_details AS
SELECT s.id, s.user_id, s.created, s.channel_id, c.channel
FROM prod.session s
JOIN prod.channel c ON c.id = s.channel_id;
SELECT * FROM test.youji_session_details;
-- ๋ฌธ๋ฒ ์ ์
DELIMITER // -- $$๋ ๊ฐ๋ฅ!
CREATE PROCEDURE stored_procedure_name(parameter_list)
BEGIN
statements;
END //
DELIMITER ;
-- ํธ์ถ ๋ฌธ๋ฒ
CALL stored_procedure_name(argument_list);
DELIMITER //
CREATE PROCEDURE test.return_youji_session_details(IN channelName varchar(64))
BEGIN
SELECT *
FROM test.youji_session_details
WHERE channel = channelName;
END //
DELIMITER ;
-- ํธ์ถ
CALL test.return_youji_session_details('Facebook');
-- sql๋ฌธ
DELIMITER //
CREATE PROCEDURE test.return_youji_session_count(IN channelName varchar(64), INOUT totalRecord int)
BEGIN
SELECT COUNT(1) INTO totalRecord FROM test.youji_session_details
WHERE channel = channelName;
END //
DELIMITER ;
-- ํธ์ถ
SET @facebook_count = 0;
CALL test.return_youji_session_count('Facebook', @facebook_count);
SELECT @facebook_count;
-- 14130 ๊ฐ์ ์ถ๋ ฅํ๋ค.
DELIMITER $$
CREATE FUNCTION test.Channel_Type(channel varchar(32))
RETURNS VARCHAR(20)
DETERMINISTIC
BEGIN
DECLARE channel_type VARCHAR(20);
IF channel in ('Facebook', 'Instagram', 'Tiktok') THEN
SET channel_type = 'Social Network';
ELSEIF channel in ('Google', 'Naver') THEN
SET channel_type = 'Search Engine';
ELSE
SET channel_type = channel;
END IF;
-- return the customer level
RETURN (channel_type);
END$$ -- $$ ๋ // ์๋ฌด๊ฑฐ๋ ์ฌ์ฉํด๋ ์๊ด์๋ค.
-- ํธ์ถ
SELECT channel, test.Channel_Type(channel)
FROM prod.channel;
CREATE TRIGGER ํธ๋ฆฌ๊ฑฐ์ด๋ฆ
{BEFORE | AFTER} {INSERT | UPDATE| DELETE } -- before/after์ค ์ธ์ ํธ์ถํ ์ง ์ ํ๊ณ 3๊ฐ์ ๋ช
๋ น์ด์ค ํ๋๋ฅผ ๊ณ ๋ฅธ๋ค.
ON table_name FOR EACH ROW
trigger_body;
-- Trigger
DESCRIBE test.youji_name_gender; -- describe๋ ๊ทธ๋ค์์ ๋์ค๋ ํ
์ด๋ธ์ ์คํค๋ง๋ฅผ ๋ณด์ฌ์ค๋ค.(๊ตฌ์ฑํ๋ ํ๋์ ์์ฑ,๊ฐ์ ๋ณด์ฌ์ค๋ค).
CREATE TABLE test.youji_name_gender_audit (
name varchar(16),
gender enum('Male', 'Female'),
modified timestamp
);
SELECT * FROM test.youji_name_gender;
CREATE TRIGGER test.before_update_youji_name_gender
BEFORE UPDATE ON test.youji_name_gender
FOR EACH ROW
INSERT INTO test.youji_name_gender_audit
SET name = OLD.name,
gender = OLD.gender,
modified = NOW();
UPDATE test.youji_name_gender -- ์ด ์
๋ฐ์ดํธ ๋ฌธ์ ์คํํ๋ฉด ํ๋ก์์ ธ๋ก ๋ฑ๋ก๋ ํ
์ด๋ธ์ ์๋์ผ๋ก old๊ฐ์ด ์ถ๊ฐ๋๋ค.
SET name = 'youji123'
WHERE name = 'youji';
-- ์
๋ฐ์ดํธ๋ ๊ฒฐ๊ณผ ํธ์ถ
select * from test.youji_name_gender;
-- ํธ๋ฆฌ๊ฑฐ๋ก ์ค์ ํ ํ๋๊ฐ๋ค์ ๋ณด์ฌ์ค๋ค.(update ํ)
SELECT * FROM test.youji_name_gender_audit;
-- EXPLAIN
EXPLAIN SELECT -- ๋์ค์ ์ฑ๋ฅ์ ๋ฌธ์ ๊ฐ ์๋ค? ๊ทธ๋ฌ๋ฉด explain์ ์จ๋ณด์. ์ผ๋จ์ ์ด๋ฐ๊ฒ ์๋ค๋๊ฒ์ ์ง์ค
LEFT(s.created, 7) AS mon,
c.channel,
COUNT(DISTINCT user_id) AS mau
FROM prod.session s
JOIN prod.channel c ON c.id = s.channel_id
GROUP BY 1, 2
ORDER BY 1 DESC, 2;
CREATE TABLE example (
id INT NOT NULL AUTO_INCREMENT,
index_col VARCHAR(20),
PRIMARY KEY (id),
INDEX index_name (index_col)
-- index ๋ค์ ์ฌ์ฉํ ์ด๋ฆ ( ํ๋ ๋ช
)์ ๋ฃ์ด์ค๋ค.
);
CREATE TABLE test.session_with_index_youji (
id int NOT NULL auto_increment,
user_id int not NULL,
created timestamp not NULL default CURRENT_TIMESTAMP,
channel_id int not NULL,
PRIMARY KEY(id),
FOREIGN KEY(channel_id) references prod.channel(id),
INDEX user_id(user_id)
);
-- ์์ ํ
์ด๋ธ์ ๊ธฐ์กด prod.session์ ๋ด์ฉ์ ๋ณต์ฌํ๊ณ ์ถ๋ค๋ฉด ์๋ ๋ช
๋ น ์คํ
INSERT INTO test.session_with_index_youji SELECT * FROM prod.session;
-- ํธ์ถ : index๊ฐ ๊ฑธ๋ฆฐ ์ ๋ณด๋ฅผ ์ ์ ์๋ค.
show index from test.session_with_index_youji;
-- ์ฑ๋ฅ๋น๊ต
SELECT user_id, COUNT(1) FROM prod.session GROUP BY 1; -- 0.057 sec
SELECT user_id, COUNT(1) FROM test.session_with_index_youji GROUP BY 1; -- 0.027 sec
-- => index๋ฅผ ์ธ๋ ์กฐ๊ธ ๋ ๋น ๋ฅธ ์ฑ๋ฅ์ ๋ณด์ธ๋ค.