쩨이엠 개발 블로그

[ H2 ] Unsupported connection setting "MVCC" 본문

개발/ETC

[ H2 ] Unsupported connection setting "MVCC"

쩨이엠 2020. 11. 10. 10:23
728x90
반응형

H2 커넥션 도중 에러가 났다

 

Error 내용

 
 com.example.demo.MemberRepositoryTest > testMember() FAILED

    org.springframework.dao.InvalidDataAccessApiUsageException at MemberRepositoryTest.java:23

        Caused by: javax.persistence.TransactionRequiredException at MemberRepositoryTest.java:23

2020-11-08 15:45:22.099 ERROR 38542 --- [         task-1] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Exception during pool initialization.

org.h2.jdbc.JdbcSQLNonTransientConnectionException: Unsupported connection setting "MVCC" [90113-200]

at org.h2.message.DbException.getJdbcSQLException(DbException.java:622) ~[h2-1.4.200.jar:1.4.200]

at org.h2.message.DbException.getJdbcSQLException(DbException.java:429) ~[h2-1.4.200.jar:1.4.200]

at org.h2.message.DbException.get(DbException.java:205) ~[h2-1.4.200.jar:1.4.200]

at org.h2.message.DbException.get(DbException.java:181) ~[h2-1.4.200.jar:1.4.200]

at org.h2.engine.ConnectionInfo.readSettingsFromURL(ConnectionInfo.java:269) ~[h2-1.4.200.jar:1.4.200]

at org.h2.engine.ConnectionInfo.<init>(ConnectionInfo.java:78) ~[h2-1.4.200.jar:1.4.200]

at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:152) ~[h2-1.4.200.jar:1.4.200]

at org.h2.Driver.connect(Driver.java:69) ~[h2-1.4.200.jar:1.4.200]

at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-3.4.5.jar:na]

at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:358) ~[HikariCP-3.4.5.jar:na]

at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:206) ~[HikariCP-3.4.5.jar:na]

at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:477) ~[HikariCP-3.4.5.jar:na]

at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:560) ~[HikariCP-3.4.5.jar:na]

at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115) ~[HikariCP-3.4.5.jar:na]

at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-3.4.5.jar:na]

at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:101) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:176) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:118) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1224) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1255) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]

at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE]

at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE]

at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391) ~[spring-orm-5.2.9.RELEASE.jar:5.2.9.RELEASE]

at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]

at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

2020-11-08 15:45:22.100  WARN 38542 --- [         task-1] o.h.e.j.e.i.JdbcEnvironmentInitiator     : HHH000342: Could not obtain connection to query metadata : Unsupported connection setting "MVCC" [90113-200]

2020-11-08 15:45:22.101  WARN 38542 --- [extShutdownHook] o.s.b.f.support.DisposableBeanAdapter    : Invocation of destroy method failed on bean with name 'entityManagerFactory': org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]

2020-11-08 15:45:22.101  INFO 38542 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
 

 

Setting

  • Spring boot 2.3.4.RELEASE
  • H2 1.4.200

application.yml

 
 spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/jpa;MVCC=TRUE
    username: sa
    password:
    driver-class-name: org.h2.Driver
    

 

에러 내용은 MVCC가 커넥션 세팅이 지원되지 않는다는건데

 

h2 버전이 1.4.200 경우 MVCC=TRUE 있으면 DB연결에 실패한다고한다

빼고나니 바로 접속이 된다

 

근데 MVCC 뭔데? 해서 찾아보았다

 

MVCC란?

: 다중 버전 동시성 제어 (Multi-Version Concurrency Control)

: 동시성을 제어하기 위해 사용하는 매커니즘 중 하나

 

.. 뭔소린지 모르겠다

 

 

그래서 동시성이란?

말그대로 동시에 데이터베이스에 접근이 가능하도록 하는 것인데 이는 일관성과 반비례관계 가지고 있다

 

동시에 접속하는 사람이 많으면 데이터가 일관적이지 않을 있고, 

일관적인 데이터를 위해서는 동시 접속하는 동시성을 낮출 밖에 없다

 

하여 동시성 제어의 목표는 동시에 실행되는 트랜잭션을 최대화하면서도, 데이터 무결성이 유지되도록 하는 것이다.

 

읽기와 쓰기 작업이 서로를 방해해 동시성을 떨어뜨리고, 공유 Lock 사용함에도 데이터 일관성이 훼손될 있는 문제를 해결하기 위해 MVCC 매커니즘을 사용한다

 

 

MVCC 매커니즘 동작 프로세스

  • 데이터를 변경 변경사항을 Undo 영역에 저장한다
  • 데이터를 읽다가 트랜잭션 시작 시점 이후에 변경된 값을 발견하면 Undo 영역에 저장된 정보를 이용해 버전을 생성하고 그것을 읽는다

 

장점

  • 잠금을 기다릴 필요가 없기 때문에 일반적인 RDBMS보다 매우 빠르다 (동시성)
  • 데이터를 읽을 다른 사용자의 CRUD 영향을 받지 않는다 (일관성)

단점

  • 데이터의 버전 충돌이 있을 있다 -> 애플리케이션 영역에서 문제를 해결해야함
  • 사용하지 않는 버전들에 대한 정리가 필요하다

 

Snapshot too old

MVCC 매커니즘은 Undo 영역을 활용함으로써 동시성과 일관성을 유지할 있는 대신, Snapshot too old 에러가 발생한다

에러는 Undo 영역에 저장된 정보가 다른 트랜잭션에 의해 재사용돼 필요한 버전을 생성할 없을 발생한다.

쉽게말하면 Undo 데이터가 덮어씌워져서 발생한 에러이다.

 

대신 발생가능성을 줄이는 방법이 있다

  1. Undo 영역의 크기를 증가시킨다(쿼리를 실행하는 동안 덮여쓰여질 크기보다 크게 혹은 추가하는게 좋으나 수동보다는 자동으로 관리하는것을 권장)
  2. 커밋 수를 줄인다 (불필요한 커밋 제거)
  3. 트랜잭션이 몰리지 않도록 시간이 오래걸리는 쿼리는 튜닝 혹은 힌트 추가로 시간을 단축시키거나 단계적으로 실행할 있도록 쿼리를 조정한다
  4. order by등의 sort 연산이 발생하도록 한다

 

728x90
반응형
Comments