为什么 table DATABASECHANGELOG 上没有索引 and/or PK?

why no index and/or PK on table DATABASECHANGELOG?

引用自MariaDB Galera Cluster - Known Limitations

All tables should have a primary key (multi-column primary keys are supported). DELETE operations are unsupported on tables without a primary key. Also, rows in tables without a primary key may appear in a different order on different nodes.

Galera 要求每个 table 都应该有一个 PK,或者至少有一个索引。这种限制主要是因为复制(wsrep 插件)。

我们运营一个Galera/MariaDB集群,我看到有DATABASECHANGELOG的客户没有索引和PK。我猜这个 table 是仅附加的(没有更新或删除操作)

我不了解Liquibase,这就是为什么我在这里询问缺少索引and/or PK的原因。我应该打开一个错误报告还是我不明白这个用例?

+----------------------------------------------------------------------------------------+------------+------------+-------------+---------------------+-----------------------+
| schema                                              | table_rows | non_unique | cardinality | medium distribution | replication row reads |
+----------------------------------------------------------------------------------------+------------+------------+-------------+---------------------+-----------------------+
(...)
| xxx.DATABASECHANGELOG                               |        571 |       NULL |        NULL |            571.0000 |           326041.0000 |
| xxxx.DATABASECHANGELOG                              |        491 |       NULL |        NULL |            491.0000 |           241081.0000 |
| xxxxx.DATABASECHANGELOG                             |        433 |       NULL |        NULL |            433.0000 |           187489.0000 |
+----------------------------------------------------------------------------------------+------------+------------+-------------+---------------------+-----------------------+

看看这个Jira ticket

Liquibase was changed to not create a primary key in databasechangelog table because it introduced problems with key sizes and wasn't really necessary. I didn't put in a check and drop for an existing primary key yet. It should be dropped but doesn't cause a problem unless you are hitting an edge case where you have very long id, author and/or file paths.

还描述了一种可能的解决方法:

A simple workaround could be to add a change set with a not primaryKeyExists pre-condition and addPrimaryKey change. A more involved workaround could be to create a plugin which overrides the CreateDatabaseChangeLogTableGenerator and/or StandardChangeLogHistoryService which implement PrioritizedService.

Below is an example of the simple workaround. I've optimized the indexes to reduce table scans, sorting and bookmark lookups on SQL Server, but it's probably equally applicable to Oracle. I was not really concerned about the maximum key length of 900 bytes on SQL Server being exceeded.

<?xml version="1.0" encoding="UTF-8" ?>
<databaseChangeLog
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
      http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">

  <property name="liquibaseCatalogName" value=""/>
  <property name="liquibaseSchemaName" value="${database.liquibaseSchemaName}"/>
  <property name="databaseChangeLogTableName" value="${database.databaseChangeLogTableName}"/>
  <property name="liquibaseTablespaceName" value=""/>

  <changeSet id="1" author="your-name">
      <preConditions onFail="MARK_RAN">
          <primaryKeyExists
              catalogName="${liquibaseCatalogName}"
              schemaName="${liquibaseSchemaName}"
              tableName="${databaseChangeLogTableName}"
              primaryKeyName="PK_${databaseChangeLogTableName}"/>
      </preConditions>
      <dropPrimaryKey
          catalogName="${liquibaseCatalogName}"
          schemaName="${liquibaseSchemaName}"
          tableName="${databaseChangeLogTableName}"
          constraintName="PK_${databaseChangeLogTableName}"/>
  </changeSet>

  <changeSet id="2" author="your-name">
      <createIndex
          catalogName="${liquibaseCatalogName}"
          schemaName="${liquibaseSchemaName}"
          tableName="${databaseChangeLogTableName}"
          indexName="IX_${databaseChangeLogTableName}_DATEEXECUTED_ORDEREXECUTED"
          tablespace="${liquibaseTablespaceName}"
          clustered="true">

          <column name="DATEEXECUTED"/>
          <column name="ORDEREXECUTED"/>
      </createIndex>
  </changeSet>

  <changeSet id="3" author="your-name">
      <addPrimaryKey
          catalogName="${liquibaseCatalogName}"
          schemaName="${liquibaseSchemaName}"
          tableName="${databaseChangeLogTableName}"
          constraintName="PK_${databaseChangeLogTableName}"
          tablespace="${liquibaseTablespaceName}"
          clustered="false"
          columnNames="ID,AUTHOR,FILENAME"/>
  </changeSet>

</databaseChangeLog>