Skip to main content
VillageSQL의 확장 아키텍처를 이해하면 확장 개발 시 문제 진단 및 성능 최적화에 도움이 됩니다. 확장 개발 과정은 간단합니다: 해당 SDK를 사용하여 C++ 또는 Rust 함수를 작성하고, 공유 라이브러리로 컴파일한 후, 그 라이브러리를 매니페스트와 함께 .veb 파일로 패키징합니다. INSTALL EXTENSION을 실행하면 VillageSQL이 라이브러리를 로드하고 등록 코드를 호출하여 함수를 즉시 SQL로 사용할 수 있게 합니다. 즉, 서버에 내장된 것처럼 어떤 쿼리에서든 호출할 수 있으며, 서버 재시작도 필요하지 않습니다. 이 페이지 나머지 부분은 해당 프로세스의 각 단계가 어떻게 작동하는지 설명합니다.

용어 정의

  • VEB (VillageSQL Extension Bundle) - .veb 파일 형식으로, 매니페스트, 라이브러리, 메타데이터를 포함하는 tar 아카이브
  • VEF (VillageSQL Extension Framework) - 확장 작성용 C++ 및 Rust SDK
  • VDF (VillageSQL Defined Function) - VEF를 통해 등록된 함수 — C++에서는 VEF_GENERATE_ENTRY_POINTS(), Rust에서는 extension! 매크로를 통해 등록

VDF 함수 검색

VDF는 접두사 포함(qualified) 및 미포함(unqualified) 함수 호출을 모두 지원합니다:
해석 순서:
  1. 시스템 함수 (내장 MySQL)
  2. UDF (CREATE FUNCTION ... SONAME을 통한 전통적인 MySQL 사용자 정의 함수)
  3. VDF (확장 함수) - 해당 이름을 가진 함수가 정확히 하나만 존재할 때만
  4. 저장 함수 (CREATE FUNCTION으로 생성)
둘 이상의 확장이 동일한 이름의 함수를 등록하면 접두사 미포함 호출은 모호해지며, 접두사를 완전히 포함한 이름(extension_name.function_name())을 사용해야 합니다. 성능: 핫 코드 경로에서는 해석 체인을 건너뛰고 직접 확장 함수를 호출하기 위해 접두사 포함 호출(extension_name.function_name())을 사용하세요.

VEB 파일 형식

VillageSQL 확장은 .veb (VillageSQL Extension Bundle) 파일로 배포되며, 다음을 포함하는 tar 아카이브입니다:

manifest.json 스키마

  • name: SQL에서 사용되는 확장 이름과 일치해야 함 (소문자_밑줄)
  • version: 시맨틱 버전 (MAJOR.MINOR.PATCH)
  • description, author, license: 선택적 메타데이터

확장 라이프사이클

설치 흐름

롤백: 단계 중 하나가 실패하면 모든 변경 사항이 취소되고 .so가 언로드됩니다. 심볼 격리: 확장은 RTLD_LOCAL 플래그로 로드되어, 한 확장의 심볼이 다른 확장의 심볼과 충돌하지 않습니다. 이는 여러 확장이 공통 라이브러리 이름이나 함수 이름을 사용할 때 이름 충돌을 방지합니다.
veb_dir 시스템 변수는 .veb 확장 파일이 저장된 디렉터리를 가리킵니다.

제거 흐름

의존성 방지: 테이블 열이 확장의 사용자 정의 유형을 사용하면 제거할 수 없습니다.

확장 디렉터리 구조

VillageSQL은 .veb 파일을 MySQL 데이터 디렉터리에 압축 해제하여 여러 버전을 지원합니다:
SHA256 디렉터리를 왜 사용하는가?
  • 덮어쓰지 않고 새 버전 테스트
  • 롤백 가능
  • “동일한 버전, 다른 코드” 방지
정리: 서버 재시작 시 고아 SHA256 디렉터리가 제거됩니다.

Victionary 캐시 계층

VictionaryClient는 O(log n) 검색을 위한 시스템 메타데이터의 메모리 캐시를 유지합니다.

캐시 작업

캐시 무효화: DDL 작업 (INSTALL/UNINSTALL EXTENSION) 중 자동으로 발생합니다. 메모리 오버헤드: 항목당 약 100바이트.

사용자 정의 유형 시스템

유형 해석

구현 유형

사용자 정의 유형은 MySQL 저장 유형과 매핑됩니다:

동시성 및 트랜잭션 동작

스레드 안전 모델

확장 함수는 행별 실행 모델로 호출됩니다:
  • 행별 격리 실행: 각 함수 호출은 자체 결과 버퍼를 얻음 (디자인상 스레드 안전)
  • 프리런/포스트런 훅: 문장별 설정/정리, SQL 문장당 한 번 호출
  • 격리 보장 없음: 여러 연결이 동시에 함수를 호출할 수 있음
  • 모범 사례: 글로벌 상태를 피하고, 함수 매개변수와 반환 값 사용
VillageSQL은 확장 함수에 대한 스레드 격리를 보장하지 않습니다. 글로벌 변수나 공유 상태를 사용하는 경우, 뮤텍스나 잠금으로 보호하세요.

트랜잭션 동작

확장 함수는 다음 모범 사례를 따르세요:
  • 가능하면 무상태로 설계
  • 파일 쓰기, 외부 API 호출과 같은 영구적 부작용 피하기
  • 프리런/포스트런 상태 사용 시 정리 적절히 처리

성능 고려 사항

최적화: 프리런 훅을 사용하여 문장별 비용이 많이 드는 설정을 행별 작업 반복 대신 캐시하세요.

사용자 정의 유형 성능


보안 및 디버깅

보안 모델

신뢰 모델: 확장은 전체 서버 권한으로 실행됩니다.
  • 샌드박스 또는 권한 시스템 없음
  • 확장은 모든 파일 읽기, 네트워크 접근, 코드 실행 가능
  • 신뢰 영향: 신뢰할 수 있는 소스에서만 확장 설치
설치 보안: villagesql_extension_installer 사용자로 실행 (컨텍스트 전환).
세부 로깅 활성화:
GDB 디버깅:
의존성 확인:
흔한 오류:
  • 정의되지 않은 심볼: ldd(Linux) 또는 otool -L(macOS)로 라이브러리 의존성 확인
  • 공유 객체를 열 수 없음: 라이브러리 의존성이 존재하고 올바르게 링크되었는지 확인
  • VDF 호출 시 충돌: NULL 포인터 처리 확인

다음 단계

확장 생성

첫 번째 확장을 빌드하세요

시스템 참조

시스템 테이블 및 뷰

예제

vsql_complex 구현 분석

확장 관리

모니터링 및 문제 해결