apache / gravitino

World's most powerful open data catalog for building a high-performance, geo-distributed and federated metadata lake.
https://gravitino.apache.org
Apache License 2.0
926 stars 299 forks source link

[Improvement] Improve time precision of `deleteAt` to reduce possible bugs #3926

Open yuqi1129 opened 3 months ago

yuqi1129 commented 3 months ago

What would you like to be improved?

When we switch default entity store to embedded JDBC database and try to drop a entity, the following errors occur:

java.lang.RuntimeException: Failed to operate object [mysql_it_schema_d163bcc4] operation [DROP] under [mysql_it_catalog_ab4808c3], reason [Unique index or primary key violation: "PUBLIC.UK_CID_SN_DEL_INDEX_4 ON PUBLIC.SCHEMA_META(CATALOG_ID, SCHEMA_NAME, DELETED_AT) VALUES 573259166732862349"; SQL statement:
UPDATE schema_meta SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0 WHERE schema_id = ? AND deleted_at = 0 [23505-200]]
java.lang.RuntimeException: org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.UK_CID_SN_DEL_INDEX_4 ON PUBLIC.SCHEMA_META(CATALOG_ID, SCHEMA_NAME, DELETED_AT) VALUES 573259166732862349"; SQL statement:
UPDATE schema_meta SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0 WHERE schema_id = ? AND deleted_at = 0 [23505-200]
### The error may exist in com/datastrato/gravitino/storage/relational/mapper/SchemaMetaMapper.java (best guess)
### The error may involve com.datastrato.gravitino.storage.relational.mapper.SchemaMetaMapper.softDeleteSchemaMetasBySchemaId-Inline
### The error occurred while setting parameters
### SQL: UPDATE schema_meta SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0 WHERE schema_id = ? AND deleted_at = 0
### Cause: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.UK_CID_SN_DEL_INDEX_4 ON PUBLIC.SCHEMA_META(CATALOG_ID, SCHEMA_NAME, DELETED_AT) VALUES 573259166732862349"; SQL statement:
UPDATE schema_meta SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0 WHERE schema_id = ? AND deleted_at = 0 [23505-200]
    at com.datastrato.gravitino.catalog.SchemaOperationDispatcher.dropSchema(SchemaOperationDispatcher.java:303)
    at com.datastrato.gravitino.catalog.SchemaNormalizeDispatcher.dropSchema(SchemaNormalizeDispatcher.java:68)
    at com.datastrato.gravitino.listener.SchemaEventDispatcher.dropSchema(SchemaEventDispatcher.java:123)
    at com.datastrato.gravitino.server.web.rest.SchemaOperations.lambda$dropSchema$8(SchemaOperations.java:203)
    at com.datastrato.gravitino.lock.TreeLockUtils.doWithTreeLock(TreeLockUtils.java:35)
    at com.datastrato.gravitino.server.web.rest.SchemaOperations.lambda$dropSchema$9(SchemaOperations.java:200)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:422)
    at com.datastrato.gravitino.utils.PrincipalUtils.doAs(PrincipalUtils.java:25)
    at com.datastrato.gravitino.server.web.Utils.doAs(Utils.java:121)
    at com.datastrato.gravitino.server.web.rest.SchemaOperations.dropSchema(SchemaOperations.java:195)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:146)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:189)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:176)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:93)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:478)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:400)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:256)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:235)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:684)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:358)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:311)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799)
    at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1656)
    at com.datastrato.gravitino.server.authentication.AuthenticationFilter.doFilter(AuthenticationFilter.java:59)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
    at com.datastrato.gravitino.server.web.VersioningFilter.doFilter(VersioningFilter.java:97)
    at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
    at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:600)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.Server.handle(Server.java:516)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
    at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
    at java.lang.Thread.run(Thread.java:750)
Caused by: org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.UK_CID_SN_DEL_INDEX_4 ON PUBLIC.SCHEMA_META(CATALOG_ID, SCHEMA_NAME, DELETED_AT) VALUES 573259166732862349"; SQL statement:
UPDATE schema_meta SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0 WHERE schema_id = ? AND deleted_at = 0 [23505-200]
### The error may exist in com/datastrato/gravitino/storage/relational/mapper/SchemaMetaMapper.java (best guess)
### The error may involve com.datastrato.gravitino.storage.relational.mapper.SchemaMetaMapper.softDeleteSchemaMetasBySchemaId-Inline
### The error occurred while setting parameters
### SQL: UPDATE schema_meta SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0 WHERE schema_id = ? AND deleted_at = 0
### Cause: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.UK_CID_SN_DEL_INDEX_4 ON PUBLIC.SCHEMA_META(CATALOG_ID, SCHEMA_NAME, DELETED_AT) VALUES 573259166732862349"; SQL statement:
UPDATE schema_meta SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0 WHERE schema_id = ? AND deleted_at = 0 [23505-200]
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:199)
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:67)
    at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:152)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85)
    at com.sun.proxy.$Proxy130.softDeleteSchemaMetasBySchemaId(Unknown Source)
    at com.datastrato.gravitino.storage.relational.service.SchemaMetaService.lambda$deleteSchema$16(SchemaMetaService.java:220)
    at com.datastrato.gravitino.storage.relational.utils.SessionUtils.doWithCommit(SessionUtils.java:33)
    at com.datastrato.gravitino.storage.relational.service.SchemaMetaService.deleteSchema(SchemaMetaService.java:219)
    at com.datastrato.gravitino.storage.relational.JDBCBackend.delete(JDBCBackend.java:181)
    at com.datastrato.gravitino.storage.relational.RelationalEntityStore.delete(RelationalEntityStore.java:110)
    at com.datastrato.gravitino.catalog.SchemaOperationDispatcher.dropSchema(SchemaOperationDispatcher.java:299)
    ... 76 more
Caused by: org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PUBLIC.UK_CID_SN_DEL_INDEX_4 ON PUBLIC.SCHEMA_META(CATALOG_ID, SCHEMA_NAME, DELETED_AT) VALUES 573259166732862349"; SQL statement:
UPDATE schema_meta SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0 WHERE schema_id = ? AND deleted_at = 0 [23505-200]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:459)
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:429)
    at org.h2.message.DbException.get(DbException.java:205)
    at org.h2.message.DbException.get(DbException.java:181)
    at org.h2.index.BaseIndex.getDuplicateKeyException(BaseIndex.java:103)
    at org.h2.mvstore.db.MVSecondaryIndex.checkUnique(MVSecondaryIndex.java:221)
    at org.h2.mvstore.db.MVSecondaryIndex.add(MVSecondaryIndex.java:196)
    at org.h2.mvstore.db.MVTable.addRow(MVTable.java:531)
    at org.h2.table.Table.updateRows(Table.java:523)
    at org.h2.command.dml.Update.update(Update.java:225)
    at org.h2.command.CommandContainer.update(CommandContainer.java:198)
    at org.h2.command.Command.executeUpdate(Command.java:251)
    at org.h2.jdbc.JdbcPreparedStatement.execute(JdbcPreparedStatement.java:240)
    at org.apache.commons.dbcp2.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:95)
    at org.apache.commons.dbcp2.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:95)
    at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:47)
    at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
    at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:50)
    at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
    at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197)
    ... 86 more
    at com.datastrato.gravitino.client.ErrorHandlers$SchemaErrorHandler.accept(ErrorHandlers.java:308)
    at com.datastrato.gravitino.client.ErrorHandlers$SchemaErrorHandler.accept(ErrorHandlers.java:277)
    at com.datastrato.gravitino.client.HTTPClient.throwFailure(HTTPClient.java:225)
    at com.datastrato.gravitino.client.HTTPClient.execute(HTTPClient.java:378)
    at com.datastrato.gravitino.client.HTTPClient.execute(HTTPClient.java:286)
    at com.datastrato.gravitino.client.HTTPClient.delete(HTTPClient.java:610)
    at com.datastrato.gravitino.client.BaseSchemaCatalog.dropSchema(BaseSchemaCatalog.java:183)
    at com.datastrato.gravitino.client.RelationalCatalog.dropSchema(RelationalCatalog.java:48)
    at com.datastrato.gravitino.catalog.mysql.integration.test.CatalogMysqlIT.clearTableAndSchema(CatalogMysqlIT.java:160)
    at com.datastrato.gravitino.catalog.mysql.integration.test.CatalogMysqlIT.stop(CatalogMysqlIT.java:131)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptLifecycleMethod(TimeoutExtension.java:126)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptAfterAllMethod(TimeoutExtension.java:116)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeAfterAllMethods$13(ClassBasedTestDescriptor.java:425)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeAfterAllMethods$14(ClassBasedTestDescriptor.java:423)
    at java.util.ArrayList.forEach(ArrayList.java:1259)
    at java.util.Collections$UnmodifiableCollection.forEach(Collections.java:1082)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeAfterAllMethods(ClassBasedTestDescriptor.java:423)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.after(ClassBasedTestDescriptor.java:225)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.after(ClassBasedTestDescriptor.java:80)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:161)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:161)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.util.ArrayList.forEach(ArrayList.java:1259)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:110)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:90)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:85)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:62)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at com.sun.proxy.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

As the query response time(less that 1ms) is very fast compared to MySQL, the value of new deleteAt is the same as old one, then error occur.

How should we improve?

I believe we need to improve the precision or use other ways to solve it, or we can't use embedded JDBC database well.

xloya commented 3 months ago

In H2, the UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) function does not seem to be able to retain data below seconds, and the results are all 0 after seconds, so conflicts may occur.

yuqi1129 commented 3 months ago

In H2, the CURRENT_TIMESTAMP(3) function does not seem to be able to retain data below milliseconds, and the results are all 0 after mills, so conflicts may occur.

I recall that we discussed this several months ago. Do you have any suggestions on how to solve it?

xloya commented 3 months ago

In H2, the CURRENT_TIMESTAMP(3) function does not seem to be able to retain data below milliseconds, and the results are all 0 after mills, so conflicts may occur.

I recall that we discussed this several months ago. Do you have any suggestions on how to solve it?

The current method works well in our production environment, but I think the following research can be done:

  1. Is this method universal enough in most RDBMSs
  2. Is there an embedded RDBMS that supports the current method
  3. Is there a way to get millisecond time in H2
  4. Optimize the current function to support millisecond or even higher precision timestamps in a more general way. But this may affect some code logic.
yuqi1129 commented 3 months ago

From my observation, most RDBMSs cannot support time precision less than one millisecond. Using the built-in function to get the current time is far from ideal in terms of precision.

Is there a way to get millisecond time in H2

We don't need to limit our system to H2. We have left the interface to support other embedded databases like derby, sqlite, though it's not so necessary now or in the near future.

Optimize the current function to support millisecond or even higher precision timestamps in a more general way. But this may affect some code logic.

Yeah, I'm focusing on this point and will provide a TSO that is strongly related to current time but provides higher precision time. In this way, it can be database independent. I'm not entirely sure if the complexity is acceptable.

xloya commented 3 months ago

From my observation, most RDBMSs cannot support time precision less than one millisecond. Using the built-in function to get the current time is far from ideal in terms of precision.

Is there a way to get millisecond time in H2

We don't need to limit our system to H2. We have left the interface to support other embedded databases like derby, sqlite, though it's not so necessary now or in the near future.

Optimize the current function to support millisecond or even higher precision timestamps in a more general way. But this may affect some code logic.

Yeah, I'm focusing on this point and will provide a TSO that is strongly related to current time but provides higher precision time. In this way, it can be database independent. I'm not entirely sure if the complexity is acceptable.

My initial consideration was to calculate the time externally and save it to the database, but this means that the time may be client-dependent, which may lead to inaccurate time if the clocks of multiple clients are not synchronized.

yuqi1129 commented 3 months ago

My initial consideration was to calculate the time externally and save it to the database, but this means that the time may be client-dependent, which may lead to inaccurate time if the clocks of multiple clients are not synchronized.

I see, there could be a time-skew problem if we use the time generated by the Gravitino server. let me think if it can be addressed.

yuqi1129 commented 2 months ago

Resolved by #3954

yuqi1129 commented 3 weeks ago

The problem still exists, please see: https://github.com/apache/gravitino/actions/runs/10570943483/job/29286239153?pr=4694

yuqi1129 commented 3 weeks ago

Test code

    for (int i = 0; i < 10; i++) {
        try {
          ResultSet rs = statement.executeQuery("SELECT (UNIX_TIMESTAMP() * 1000.0), EXTRACT(MICROSECOND FROM CURRENT_TIMESTAMP(3)) / 1000");
          rs.next();
          String v1 = rs.getString(1);
          String v2 = rs.getString(2);
          LOG.info("Current timestamp-yq: {}, {}", v1, v2);

          statement.execute("update schema_meta set deleted_at = 1000 where schema_id = 1");
        } catch (Exception e) {
          LOG.error("Failed to connect to H2 database. Retrying...", e);
          Thread.sleep(1000);
        }
      }