8.3.4 B-Tree 인덱스를 통한 데이터 읽기 MySQL이 인덱스를 사용하는 방법 3가지 1. 인덱스 레인지 스캔 리프노드의 인덱스 키가 정렬되어있고 모두 연결리스트 구조로 연결되어 있음. 시작 인덱스의 리프 노드를 찾고 그대로 마지막 인덱스의 리프 노드까지 스캔한다. 리프노드에서 실제 레코드를 읽어오려면 랜덤 I/O가 발생하기 때문에 스캔해야할 레코드가 테이블 전체 레코드의 20~25%를 넘어가면 그냥 풀스캔 때리는게 나을지도 커버링 인덱스로 처리되는 쿼리라면 디스크 I/O가 없기 때문에 괜찮음 SHOW STATUS LIKE 'Handler_%' 쿼리로 레인지 스캔과 관련된 정보를 조회할 수 있다. 2. 인덱스 풀 스캔 리프 노드 싹 다 스캔. 리프 노드 수가 적을수록 풀스캔에 비해 성능이 좋다. ..
인덱스 매우 중요... 8.1 디스크 읽기 방식 데이터베이스 성능 튜닝 = 디스크 I/O 줄이기 8.1.1 HDD, SSD SSD에서는 HDD의 원판을 플래시 메모리로 대체 했다. 원판을 돌릴 필요가 없으므로 아주 빨리 데이터를 읽을 수 있다. 플래시 메모리 이므로 전원이 차단되도 데이터가 보존된다. 순차 I/O의 경우 둘의 차이는 거의 없지만, HDD에 비해 SSD의 큰 장점은 랜덤 I/O에 있다.(원판 돌릴 필요 없음) 데이터베이스 서버의 경우 랜덤 I/O가 많아서 SSD가 최적. 8.1.2 랜덤 I/O와 순차 I/O 순차 I/O의 경우, 디스크에서 블록 단위로 읽어오면 연속한 주소에 해당하는 데이터는 디스크 I/O 없이 로드할 수 있다. 하지만, 랜덤 I/O는 (거의 모든 경우) I/O가 발생할때 ..
7.3 테이블 암호화 키링 플러그인은 마스터 키 생성, 관리만 담당하기 때문에 어떤 플러그인을 쓰든지 암호화된 테이블을 생성하고 활용하는 방법은 동일하다. 7.3.1 생성 CREATE TABLE (...) ENCRYPTION='Y' 와 같이 뒤에 ENCRYPTION='Y'를 붙이면 된다. 실제 쿼리 처리 과정에서 디스크 I/O 레이어에서 암호화/복호화가 자동으로 일어나므로, 사용자가 느끼기에는 암호화가 비활성화된 경우와 동일하다. (일반적 쿼리와 같은 방법으로 날리면 된다는 뜻) 옵션 안 붙여도 자동으로 암호화된 테이블을 생성하게 하려면 default_table_encryption 시스템 변수를 ON으로 하면 됨 7.3.2 응용 프로그램 암호화와의 비교 응용 프로그램에서 암호화하면 인덱스 사용이 어렵다...
8.0 버전 부터 데이터 파일, 언두 로그, 리두 로그, 바이너리 로그 등에도 암호화 지원. 보안상 중요한 데이터, 핀테크에서는 애플리케이션에서 암호화한 데이터(컬럼 단위)를 데이터베이스에서 한번 더 암호화(테이블 단위)하기도 한다. 7.1 MySQL 서버의 데이터 암호화 실제 디스크와 I/O가 일어날 때 암호화/복호화가 일어난다. 즉, MySQL서버의 I/O레이어 에서만 암호화/복호화가 일어난다. 따라서 쿼리 처리과정에서 사용자는 암호화에 대해 인식하지 않아도 된다.(암호화되지 않은 테이블과 똑같은 처리 과정을 거친다.) 암호화 활성화 유무에 관계없이 MySQL 내부와 사용자는 아무런 차이를 느끼지 못한다. 이러한 암호화 방식을 TDE(transparent data encryption)이라 한다. 7...
디스크 데이터가 크면 안좋다. 버퍼 풀에 LOAD할 때나 백업할 때 등 하여튼 안 좋음 MySQL 서버에서 사용 가능한 압출 방식은 테이블 압축, 페이지 압축 두 가지가 있다. 1. 페이지 압축 잘 쓰이지는 않는다. 펀치 홀? 이게 뭐지? 압축 해도 16KB단위 채우려고 빈공간을 꾸역꾸역 남겨 놓는데 이걸 나중에 OS가 펀치 홀 해버리는 것인가 운영체제와 하드웨어의 지원이 필요하다. 잘 안 쓴다니까 넘어가자 2. 테이블 압축 운영체제, 하드웨어에 대한 제약 없이 사용 가능. 활용도가 높다. - 어떻게 앞축이 실행되어 디스크에 저장되는가 일단 압축 테이블을 별도로 만들어야 한다. 테이블을 만들 때 부터 innodb_file_per_table=ON으로 해서 만든다. 그러면 ROW_FORMAT=COMPRESS..
격리 수준이란, 트랜잭션이 동시에 여러개 발생했을 때, 특정 트랜잭션이 다른 트랜잭션의 변경사항을 볼 수 있게 할지 말지 결정하는 것이다. 크게 READ_UNCOMMITED, READ_COMMITED, REPEATABLE_READ, SERIALIZABLE 4가지가 있다. 1. READ_UNCOMMITED 각 트랜잭션의 변경 내용이 commit, rollback 여부에 관계없이 모두 보인다. (dirty read 발생) 사용하지 말자 2. READ_COMMITED 오라클 DBMS에서 기본으로 사용되는 격리 수준. 온라인 서비스에서 가장 많이 사용된다. 데이터 변경이 일어날 때 언두로그에 원본 데이터가 저장된다. 이 격리 수준에서는 COMMIT되기 전 데이터는 언두 로그에서 백업본을 읽기 때문에 COMMIT..
InnoDB 스토리지 엔진은 MySQL에서 제공하는 락과는 별개로, 스토리지 엔진 내부에서 레코드 기반의 락을 제공한다. 레코드 기반이기 때문에 MyISAM보다 뛰어난 동시성을 제공한다. MySQL과 별개로 존재하기 때문에 모니터링하거나 이해하기 어렵다는 단점이 있다. 최근 버전에는 여러가지 모니터링 할 수 있는 커맨드가 추가 됬다. 1. InnoDB 스토리지 엔진의 잠금 레코드락, 레코드와 레코드 사이의 갭락(..)이 존재 - 레코드락: InnoDB에서는 상용 DB와 다르게, 레코드 자체가 아닌 내부적으로 자동 생성된 클러스터 인덱스의 레코드를 잠그는 방식이다.(뭔소리지) - 갭 락: 레코드와 바로 인접한 레코드 사이의 간격을 잠근다. -> 인접한 레코드 사이에 이상한 레코드가 추가되는 것을 막기 위한..
크게 엔진락과 스토리지락이 있다. 엔진락은 모든 스토리지에 영향을 주지만, 스토리지락은 해당하는 스토리지만 영향을 준다. 1. 글로벌 락 MySQL 서버 전체에 영향을 미치는 락. 테이블이나 데이터베이스가 달라도 영향을 끼친다. SELECT 이외의 거의 모든 작업은 이 락이 해제될 때까지 기다려야한다. 백업 락 이라는 것이 있다.. 기존에는 중간에 백업이 실패하면 완전 처음부터 다시 백업을 해야했는데 백업락이 도입되고나서, 백업중에 DDL명령이 실행되면 복제를 일시 중지하는 역할을 하게 됬다. 2. 테이블 락 개별 테이블 단위로 설정되는 잠금. InnoDB에서는 데이터 변경 쿼리(DML) 쿼리에서는 테이블 락이 무시되고, 스키마 정의 변경 쿼리(DDL)에 영향을 미친다. 3. 네임드 락 사용자가 지정한 ..
이번에 푸시 서비스를 개선하는 작업이 있었다. 기존에는 polling 방식으로 푸시 알림이 동작했다. 이를 개선하는 작업으로, firebase cloud messaging(fcm)과 apple push notification service(apns)를 이용해서 기존의 메시지 발송 로직은 유지하되, 전송 방식만 추가하게 되었다. 작업의 과정에는 DB테이블을 새로 추가하는 작업을 포함해 아래 리팩터링 작업이 있었다. 1) 기존 (polling 만 존재하는) notification 도메인을 새로운 notification의 하위 도메인 polling으로 리팩터링(네이밍 수정) 2) 기존 (polling 만 존재하는) notification의 메소드 중 새로운 상위 notification의 메소드가 될 것(예를 ..
잠금 vs 트랜잭션 잠금: 동시성을 해결하기 위한 것. 하나의 데이터를 여러 커넥션이 변경하는 것을 방지하기 위해 필요하다. 락을 써서 한번에 하나의 커넥션만 공유하고 있는 데이터에 대해 변경할 수 있게 해준다. 트랜잭션: 데이터의 정합성 즉 데이터가 일관된 것을 보장하기 위한 기능이다. 트랜잭션은 데이터가 부분 업데이트가 되는 것을 방지한다. 5.1 트랜잭션 1. MySQL에서의 트랜잭션 논리 작업이 100% 적용되거나 아무것도 적용되지 않아야함을 보장. InnoDB의 경우 MyISAM과 다르게 트랜잭션을 제공한다. 따라서 깔끔하게 쿼리 셋을 작성할 수 있다. try {START TRANSACTION ...} catch {...} 2. 주의사항 트랜잭션의 범위를 꼭 필요한 곳으로만 최소화 해야한다.