Activiti重复建表bug
Posted 张侦毅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Activiti重复建表bug相关的知识,希望对你有一定的参考价值。
文章目录
故障码
故障码如下:
2019-11-11 16:05:27.318 INFO 19208 --- [ main] o.activiti.engine.impl.db.DbSqlSession : performing create on history with resource org/activiti/db/create/activiti.mysql.create.history.sql
2019-11-11 16:05:27.338 INFO 19208 --- [ main] o.activiti.engine.impl.db.DbSqlSession : Found MySQL: majorVersion=5 minorVersion=7
2019-11-11 16:05:27.643 INFO 19208 --- [ main] o.activiti.engine.impl.db.DbSqlSession : performing create on identity with resource org/activiti/db/create/activiti.mysql.create.identity.sql
2019-11-11 16:05:27.643 INFO 19208 --- [ main] o.activiti.engine.impl.db.DbSqlSession : Found MySQL: majorVersion=5 minorVersion=7
2019-11-11 16:05:27.708 ERROR 19208 --- [ main] o.activiti.engine.impl.db.DbSqlSession : problem during schema create, statement alter table ACT_ID_MEMBERSHIP
add constraint ACT_FK_MEMB_GROUP
foreign key (GROUP_ID_)
references ACT_ID_GROUP (ID_)
java.sql.SQLIntegrityConstraintViolationException: Can't write; duplicate key in table '#sql-345e_4030'
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.mysql.cj.jdbc.StatementImpl.executeInternal(StatementImpl.java:782) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.mysql.cj.jdbc.StatementImpl.execute(StatementImpl.java:666) ~[mysql-connector-java-8.0.16.jar:8.0.16]
at com.alibaba.druid.filter.FilterChainImpl.statement_execute(FilterChainImpl.java:2958) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.filter.FilterAdapter.statement_execute(FilterAdapter.java:2473) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.filter.FilterEventAdapter.statement_execute(FilterEventAdapter.java:188) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.filter.FilterChainImpl.statement_execute(FilterChainImpl.java:2956) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.proxy.jdbc.StatementProxyImpl.execute(StatementProxyImpl.java:147) ~[druid-1.1.10.jar:1.1.10]
at com.alibaba.druid.pool.DruidPooledStatement.execute(DruidPooledStatement.java:619) ~[druid-1.1.10.jar:1.1.10]
at org.activiti.engine.impl.db.DbSqlSession.executeSchemaResource(DbSqlSession.java:1311) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.db.DbSqlSession.executeSchemaResource(DbSqlSession.java:1231) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.db.DbSqlSession.executeMandatorySchemaResource(DbSqlSession.java:1016) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.db.DbSqlSession.dbSchemaCreateIdentity(DbSqlSession.java:985) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.db.DbSqlSession.dbSchemaUpdate(DbSqlSession.java:1087) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.db.DbSqlSession.performSchemaOperationsProcessEngineBuild(DbSqlSession.java:1422) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.SchemaOperationsProcessEngineBuild.execute(SchemaOperationsProcessEngineBuild.java:27) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.interceptor.CommandInvoker.execute(CommandInvoker.java:24) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:57) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.spring.SpringTransactionInterceptor$1.doInTransaction(SpringTransactionInterceptor.java:47) [activiti-spring-5.22.0.jar:5.22.0]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) [spring-tx-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.activiti.spring.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:45) [activiti-spring-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:31) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.cfg.CommandExecutorImpl.execute(CommandExecutorImpl.java:40) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.ProcessEngineImpl.<init>(ProcessEngineImpl.java:80) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl.buildProcessEngine(ProcessEngineConfigurationImpl.java:613) [activiti-engine-5.22.0.jar:5.22.0]
at org.activiti.spring.SpringProcessEngineConfiguration.buildProcessEngine(SpringProcessEngineConfiguration.java:65) [activiti-spring-5.22.0.jar:5.22.0]
at org.activiti.spring.ProcessEngineFactoryBean.getObject(ProcessEngineFactoryBean.java:60) [activiti-spring-5.22.0.jar:5.22.0]
at org.activiti.spring.ProcessEngineFactoryBean.getObject(ProcessEngineFactoryBean.java:32) [activiti-spring-5.22.0.jar:5.22.0]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:163) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1645) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1178) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:327) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:815) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:721) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:470) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1250) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:541) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1065) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:584) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:373) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1344) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:578) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760) [spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at com.weifu.Application.main(Application.java:30) ~[classes/:na]
分析
上面的故障码是说,Activiti
在执行activiti.mysql.create.identity.sql
的DDL
文件时报错。
于是我们就找到jar
包中的该文件,打开该文件,其内容如下:
create table ACT_ID_GROUP (
ID_ varchar(64),
REV_ integer,
NAME_ varchar(255),
TYPE_ varchar(255),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
create table ACT_ID_MEMBERSHIP (
USER_ID_ varchar(64),
GROUP_ID_ varchar(64),
primary key (USER_ID_, GROUP_ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
create table ACT_ID_USER (
ID_ varchar(64),
REV_ integer,
FIRST_ varchar(255),
LAST_ varchar(255),
EMAIL_ varchar(255),
PWD_ varchar(255),
PICTURE_ID_ varchar(64),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
create table ACT_ID_INFO (
ID_ varchar(64),
REV_ integer,
USER_ID_ varchar(64),
TYPE_ varchar(64),
KEY_ varchar(255),
VALUE_ varchar(255),
PASSWORD_ LONGBLOB,
PARENT_ID_ varchar(255),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
alter table ACT_ID_MEMBERSHIP
add constraint ACT_FK_MEMB_GROUP
foreign key (GROUP_ID_)
references ACT_ID_GROUP (ID_);
alter table ACT_ID_MEMBERSHIP
add constraint ACT_FK_MEMB_USER
foreign key (USER_ID_)
references ACT_ID_USER (ID_);
在上面的提示中,找到最关键的信息,那就是:
2019-11-11 16:05:27.708 ERROR 19208 --- [ main] o.activiti.engine.impl.db.DbSqlSession : problem during schema create, statement alter table ACT_ID_MEMBERSHIP
add constraint ACT_FK_MEMB_GROUP
foreign key (GROUP_ID_)
references ACT_ID_GROUP (ID_)
其对应的activiti.mysql.create.identity.sql
指令为:
alter table ACT_ID_MEMBERSHIP
add constraint ACT_FK_MEMB_GROUP
foreign key (GROUP_ID_)
references ACT_ID_GROUP (ID_);
通过查ACT_ID_MEMBERSHIP
表,我们发现,在数据库中存在两张表名一样的表,分别是act_id_membership
与ACT_ID_MEMBERSHIP
。但是不同之处在于,一张是小写的表名,一张是大写的表名,要知道,在Windows
中创建的MySQL
,本身是不会出现两张相同的表名的,也就是说,数据库表名其实是在创建时就已经不区分大小写了,故不能在创建act_id_membership
后再创建ACT_ID_MEMBERSHIP
,否则就出现问题。
而这里是出现了两张表名一样的表,分别是act_id_membership
与ACT_ID_MEMBERSHIP
,这说明此时的MySQL其实配置的是区分大小写,只有这样上述两张表才能够共存。
为了验证上述猜想,我们可以通过执行下面的语句得知:
SHOW VARIABLES LIKE 'lower_case_table_names';
如果查询的结果显示lower_case_table_names
为0
,则是区分大小写,如果显示为1
则是不区分大小写。而上面Linux
中MySQL
的查询结果为0
,这说明,此时的Linux
中MySQL
是区分大小写的。
然后我们再查看act_id_membership
的建表语句:
CREATE TABLE `act_id_membership` (
`USER_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
`GROUP_ID_` varchar(64) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`USER_ID_`,`GROUP_ID_`),
KEY `ACT_FK_MEMB_GROUP` (`GROUP_ID_`),
CONSTRAINT `ACT_FK_MEMB_GROUP` FOREIGN KEY (`GROUP_ID_`) REFERENCES `act_id_group` (`ID_`),
CONSTRAINT `ACT_FK_MEMB_USER` FOREIGN KEY (`USER_ID_`) REFERENCES `act_id_user` (`ID_`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
我们发现,尽管说原来的表名是小写的,但是其中的外键约束仍然为大写,而再执行ACT_ID_MEMBERSHIP
中的下述修改语句时,就会出错。
alter table ACT_ID_MEMBERSHIP
add constraint ACT_FK_MEMB_GROUP
foreign key (GROUP_ID_)
references ACT_ID_GROUP (ID_);
因为此时在同一张表中,出现了两个相同的外键约束ACT_FK_MEMB_GROUP
,故此时后一个修改失败,于是就出现了上面的情况。
解决办法
上面的问题,其实是由于Activiti
在启动后,发现数据库中不存在工作流相关的数据表,于是就自动启动了建表操作。而原数据库中,本身是存在相应的工作流数据表(表名全部小写),只是由于数据库部署在Linux
中,而Linux
中部署的MySQL
数据库,其默认是区分大小写的,于是Activiti
按照大写的表名查表,发现找不到,这才创建了新的大写的数据表,于是就引发了上面的问题。
而该问题我在之前的文章Docker中安装MySQL有论述,这里可以参考之前的文章内容。
在了解了这里之后,我们自然也就想到了解决办法,那就是将Linux
中的大小写配置与Windows
中的相统一,也就是说让Linux
中的MySQL
,也不去区分数据表的大小写,我们可以通过修改Linux
中的配置文件my.cnf
,在其中添加上如下配置:
lower_case_table_names=1
重启MySQL
,该问题解决。
以上是关于Activiti重复建表bug的主要内容,如果未能解决你的问题,请参考以下文章
activiti 工作流 启动时如何取消自动建表到mysql数据库中