W2D5- 실리콘밸리에서 날아온 데이터베이스 🎁

Sangwon Na·2021년 8월 13일
3

⚠ IntelliJ, JDBC 연결 설정

Process finished with exit code 1 뜨면서 JDBC 연결 안될 시

Connecting to database...
java.sql.SQLException: No suitable driver found for jdbc:mysql://서버주소.com:3306/test
	at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:702)
	at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)
	at Main.main(Main.java:26)
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.sql.Connection.rollback()" because "conn" is null
	at Main.main(Main.java:59)

Process finished with exit code 1

자바에서 mysql을 연결 시에는 MySQL Connector/J 외부 라이브러리 디펜더시(의존성)가 필요합니다.
만약 의존성이 설치되어 있지않으면, 당연히 MySQL과 어떻게 연결할지에 대해 모르기 때문에 에러가 발생하면서 연결이 되지 않습니다.

  • 프로젝트를 만들 때 한꺼번에 넣으면 되지 않나? 왜 귀찮게 이렇게 만들었을까? 생각할수도 있지만, 그렇게되면 매번 프로젝트를 생성할 때마다 각양각색의 라이브러리 등을 다운로드 받고 적용하느라 무거워지고, 생성 할때마다 엄청난 시간이 걸릴지도 모릅니다.

하지만 메이븐과 그래들에는 의존성을 코드 한줄만 입력하면 우리가 만든 프로젝트에 저절로 필요한 플러그인, 라이브러리 등을 알아서 다운로드 하여 적용 시켜 줍니다.

💌 mvn repository 다운로드

JDBC 연결 시 javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify 에러(경고)가 뜹니다.

** BEGIN NESTED EXCEPTION ** 
javax.net.ssl.SSLException
MESSAGE: closing inbound before receiving peer's close_notify

STACKTRACE:
javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify
	at java.base/sun.security.ssl.SSLSocketImpl.shutdownInput(SSLSocketImpl.java:838)
	at java.base/sun.security.ssl.SSLSocketImpl.shutdownInput(SSLSocketImpl.java:817)
	at com.mysql.jdbc.MysqlIO.quit(MysqlIO.java:2249)
	at com.mysql.jdbc.ConnectionImpl.realClose(ConnectionImpl.java:4221)
	at com.mysql.jdbc.ConnectionImpl.close(ConnectionImpl.java:1464)
	at Main.main(Main.java:52)
** END NESTED EXCEPTION **



Process finished with exit code 0

위 경고(에러)가 뜨지만, sql 조회는 되는 경우가 있습니다.
어찌됐든간에 조회가 됐으니 넘어갈수도 있지만, 왜 SSLException가 뜨는지 궁금합니다.

문서를 살펴보니, 서버가 SSL을 사용하도록 올바르게 구성된 한, 커넥터/J 클라이언트에서 암호화된 연결을 사용하도록 구성할 필요가 없습니다(예외는 커넥터/J가 5.6.25 이전 또는 5.7.5 버전을 쓰는 경우, 혹은 MySQL 서버 버전)

즉 5.6.25 혹은 5.7.5 이전 버전의 외부라이브러리를 사용하게 되면 SSL를 사용된 SQL서버에 접속시에는 설정을 구성할 필요가 있다고 합니다.

  • 해결방법
    • ① 실습환경에서 제공된 서버는 https가 적용된 AWS서버라서 connect/j를 버전을 올려주시면 위 에러(경고)창은 해결 될 겁니다.
    • ② connect/j 버전을 낮은걸로, jdbc 연결 시에는 SSL연결이라고 명시를 해주면 됩니다.
      옛날에는 SSL(https)를 선택이라서 http로 연결을 시도했지만, 요즘은 보안때문에 SSL로 연결을 시도하기 때문입니다.
jdbc:mysql://localhost:3306/test?verifyServerCertificate=true&useSSL=true&requireSSL=true

MySQL 버전별 차이 - 공식문서 보러가기

추가로 connect버전을 올려도 똑같은 에러메시지가 뜨셨다면, openjdk를 사용하셔서 그럴 수 있습니다.
https 접속 시 javax.net.ssl.SSLException: java.lang.RuntimeException: 에러 발생 원인

트랙잭션 소개

트랜잭션이란?

  • 테이블 내용을 변경하는 SQL들이 연달아 실행되며, 마치 하나의 SQL처럼 다 같이 성공하던지 아니면 실패해야 한다면 트랜잭션의 사용이 필수!
  • Atomic(하나의 시퀀스)하게 실행되어야 하는 SQL들을 묶어서 하나의 작업처럼 처리하는 방법
  • DDL이나 DML 중 레코드를 수정/추가/삭제 한 것에만 의미가 있음.
  • SELECT에는 트랙잭션을 사용할 이유가 없음.
  • BEGIN과 END 혹은 BEGIN과 COMMIT 사이에 해당 SQL들을 사용
  • ROLLBACK

트랙잭션 예시

  • 은행 계좌 이체
    • 계좌 이체: 인출과 입금의 두 과정으로 이뤄짐
    • 만일 인출 성공했는데 입금이 실패한다면?
    • 이 두 과정은 동시에 성공하던지 실패해야함 -> Atomic하다는 의미
    • 이러한 두 과정을 하나로 묶어서 실행하는걸 트랙잭션이라 함.
BEGIN; -- START TARNSACTION
 A의 계좌로부터 인출;
 B의 계좌로 입금;
END; -- COMMIT
  • BEGIN과 START TRANSACTION은 같은 의미
  • END와 COMMIT은 동일
  • 만일 BEGIN 전의 상태로 돌아가고 싶다면 ROLLBACK 실행


이 동작은 autocommit 모드에 따라 달라짐.

autocommit = True // ON

  • 모든 레코드 수정/삭제/추가 작업이 기본적으로 바로 DB에 쓰여짐. 이를 커밋(Commit)된다고 함.
  • 만일 특정 작업을 트랜잭션으로 묶고 싶다면 BEGIN과 END(COMMIT)/ROLLBACK으로 처리

autocommit = False // OFF

  • 모든 레코드 수정/삭제/추가 작업이 COMMIT이 호출될 때까지 커밋되지 않음.
  • 명시적으로 커밋을 해야함.
  • ROLLBACK이 호출되면 앞서 작업들이 무시됨

-- autocommit 작동 방법
SHOW VARIABLES LIKE 'AUTOCOMMIT';

-- autocommit 변경 방법
SET autocommit = 0 --(혹은 1)로 작동 변경가능 

DELETE FROM vs TRUNCATE 차이

  • 테이블 안에 내용을 모두 삭제하지만, TRUNCATE는 WHERE를 사용해 특정레코드는 삭제 불가능, 그래서 TRUNCATE 테이블명 으로 사용
  • DELETE FROM는 속도가 느림
  • TRUNCATE는 Transaction을 지원하지 않음.

  • default를 null로 줬기 때문에, 따로 Values(인자)를 주지 않으면 NULL값이 들어갑니다.
  • 4번째 INSERT의 'Male2'은 enum에 없는 값이 들어갑니다. 따라서 enum에 열거되어있지 않기 때문에 빈 값이 들어갑니다.
  • 빈 문자열은 대신 특수 오류 값으로 삽입됩니다. 이 enum으로 만든 필드의 문자열은 숫자 값 0을 가지고 있어 "일반" 빈 문자열과 구별 될 수 있습니다.
    예시) ENUM('Mercury', 'Venus', 'Earth')

View 소개

View란?
자주 사용하는 SQL 쿼리(SELECT)에 이름을 주고 그 사용을 쉽게 하는 것

  • 이름이 있는 쿼리가 View로 데이터베이스단에 저장됨.
    • SELECT 결과가 테이블로 저장되는 것이 아니라 View가 사용될 때마다 SELECT가 실행됨.
    • 때문에 가상 테이블이라고 부르기도 함(Virtual Table)
  • CREATE OR REPLACE VIEW 뷰이름 AS SELECT ...

Stored Procedure, Trigger 소개

Stored Procedure란?

  • View의 가상테이블처럼 MySQL 서버단에 저장되는데, View보다 훨씬 강력한 기능 제공

    • CREATE PROCEDURE 사용
    • DROP PROCEDURE [IF EXISTS]로 제거
  • 프로그래밍 언어의 함수처럼 인자를 넘기는 것이 가능, INOUT 지원

  • 리턴되는 값은 레코드들의 집합

  • 간단한 분기문(if, case)과 루프(loop)를 통한 프로그램이 가능

  • 디버깅이 힘들고 서버단의 부하를 증가시킨다는 단점 존재

  • 정의 문법
DELIMITER //
CREATE PROCEDURE procedure_name(parameter_list)
BEGIN
	statements;
END //
DELIMTER;

DELIMITER 다음에 나오는 문자(//)는 $$등 아무거나 해도 됨.
다음 문자(//) 나올때까지 안에 내용을 Sotred 저장해서 사용한다는 의미

  • 호출 문법
CALL stored_procedure_name(argument_list);

Stored function이란?

  • 값(Scalar)을 하나 리턴해주는 서버쪽 함수(특정 데이터베이스 밑에 등록됨)
    • 리턴값은 Deterministic 혹은 Non Deterministic
  • 모든 함수의 인자는 IN 파라미터
  • CREATE FUNCTION 사용

Trigger이란?

  • INSERT/DELETE/UPDATE 실행 전후에 특정 작업을 수행하는 작업을 수행하는 것
    • 대상 테이블 지정 필요
  • CREATE TRIGGER 명령을 사용
  • NEW/OLD modifier
    • NEW는 INSERT와 UPDATE 시
    • OLD는 DELETE와 UPDATE 시
    CREATE TRIGGER 트리거이름
    {BEFORE | AFTER} {INSERT | UPDATE | DELETE}
    ON table_name FOR EACH ROW
    trigger_body;
  • [예시] 중요 테이블의 경우 감사(audit)가 필요
    • 레코드에 변경이 생길 때마다(BEFORE) 변경전(OLD)의 레코드를 저장하는 트리거

성능 튜닝: Explain SQL과 Index 튜닝

  • Explain SQL
    • SELECT/UPDATE/INSERT/DELETE 등의 쿼리가 어떻게 수행되는지 내부를 보여주는 SQL 명령
      • MySQL이 해당 쿼리를 어떻게 실행할지 Execution Plan을 보여줌. 이를 바탕으로 느리게 동작하는 쿼리의 최적화가 가능해짐
-- EXPLAIN
EXPLAIN SELECT 
-- 서술
  • Index
    • Index는 테이블에서 특정 찾기 작업을 빠르게 수행하기 위해서 MySQL이 별도로 만드는 데이터 구조를 말함.
    • Primary Key나 Foreign Key로 지정된 컬럼은 기본적으로 Index를 갖게 됨.
    • INDEX와 KEY는 동의어
    • Index는 SELECT/DELETE/JOIN 명령을 빠르게 하지만, 대신 INSERT/UPDATE 명령은 느리게 하는 단점이 존재
      • 테이블에 너무 많은 인덱스를 추가하면, 인덱스의 로딩으로 인한 오버헤드로 인해 시스템이 전체적으로 느려질 수 있음.
    • CREATE TABLE시 지정 가능(컬럼 속성)
-- 테이블 생성하면서 하는 방법
CREATE TABLE example (
id int not null auto_increment,
index_col VARCHAR(20),
PRIMARY KEY(id),
INDEX index_name(index_col)
);

-- 생성된 테이블을 ALTER로 수정하면서 하는 방법
ALTER TABLE testalter_tbl ADD INDEX(column1);

느낀점

키워드에 대해서 제시할 뿐, 따로 상세하게 정리하지는 않았다.
주말을 이용해서 SQL 책을 하나 다 보고나서, 다시 글에 살을 붙일 예정이다.

profile
나상원의 LOG

1개의 댓글

comment-user-thumbnail
2021년 8월 14일

오 mysql connector 버전에 따라서 ssl 관련 인증서가 누락 됐을 때 생성하는 경우도 있네요.
상원님한테 ssl 관련 exception 말씀드리고 나서 8버전 쓴다고 왜 에러가 해결됐지? 라는 생각을 해봤는데 궁금증이 해결됐습니다! 감사합니다

답글 달기