【问题标题】:Do django db_index migrations run concurrently?django db_index 迁移是否同时运行?
【发布时间】:2015-08-12 11:50:04
【问题描述】:

我希望添加一个multi-column index to a postgres 数据库。我有一个非阻塞 SQL 命令来执行此操作,如下所示:

CREATE INDEX CONCURRENTLY shop_product_fields_index ON shop_product (id, ...);

当我将db_index 添加到我的模型并运行迁移时,它会同时运行还是会阻止写入?在 django 中可以进行并发迁移吗?

【问题讨论】:

    标签: django django-south django-migrations


    【解决方案1】:

    使用 Django 1.10 迁移,您可以使用 RunSQL 创建并发索引,并通过将 atomic = False 设置为迁移的数据属性使迁移非原子来禁用包装事务:

    class Migration(migrations.Migration):
        atomic = False # disable transaction
    
        dependencies = []
    
        operations = [
            migrations.RunSQL('CREATE INDEX CONCURRENTLY ...')
        ]
    

    【讨论】:

      【解决方案2】:

      Django 3.0 中有AddIndexConcurrentlyRemoveIndexConcurrently

      https://docs.djangoproject.com/en/dev/ref/contrib/postgres/operations/#django.contrib.postgres.operations.AddIndexConcurrently

      创建迁移,然后将 migrations.AddIndex 更改为 AddIndexConcurrently。从django.contrib.postgres.operations 导入。

      【讨论】:

        【解决方案3】:

        您可以使用SeparateDatabaseAndState 迁移操作来提供用于创建索引的自定义 SQL 命令。该操作接受两个操作列表:

        • state_operations 是应用于 Django 模型状态的操作。 它们不会影响数据库。

        • database_operations 是应用于数据库的操作。

        迁移示例可能如下所示:

        from django.db import migrations, models
        
        class Migration(migrations.Migration):
            atomic = False
        
            dependencies = [
                ('myapp', '0001_initial'),
            ]
        
            operations = [    
                migrations.SeparateDatabaseAndState(    
                    state_operations=[
                        # operation generated by `makemigrations` to create an ordinary index
                        migrations.AlterField(
                            # ...  
                        ),
                    ],
        
                    database_operations=[
                        # operation to run custom SQL command (check the output of `sqlmigrate`
                        # to see the auto-generated SQL, edit as needed)
                        migrations.RunSQL(sql='CREATE INDEX CONCURRENTLY ...',
                                          reverse_sql='DROP INDEX ...'),
                    ],
                ),
            ]
        

        【讨论】:

          【解决方案4】:

          django 不支持 PostgreSQL 并发索引创建。

          这是请求此功能的票证 - https://code.djangoproject.com/ticket/21039

          但是,您可以在迁移中手动指定任何自定义 RunSQL 操作 - https://docs.djangoproject.com/en/1.8/ref/migration-operations/#runsql

          【讨论】:

          • 你不能在事务中运行CREATE INDEX CONCURRENTLY,AFAIK Django 总是在事务中运行迁移(至少在 Postgres 上)。
          • @Pankrat 1.10 将支持non-transactional migrations,所以现在应该可以了。
          【解决方案5】:

          按照 tgroshon 对新 django 1.10 + 所说的做

          对于较小版本的 django,我使用更详细的子类化方法取得了成功:

          from django.db import migrations, models
          
          
          class RunNonAtomicSQL(migrations.RunSQL):
              def _run_sql(self, schema_editor, sqls):
                  if schema_editor.connection.in_atomic_block:
                      schema_editor.atomic.__exit__(None, None, None)
                  super(RunNonAtomicSQL, self)._run_sql(schema_editor, sqls)
          
          
          class Migration(migrations.Migration):
              dependencies = [
              ]
          
              operations = [
          
                  RunNonAtomicSQL(
                      "CREATE INDEX CONCURRENTLY",
                  )
              ]
          

          【讨论】:

            【解决方案6】:

            你可以这样做

            
            import django.contrib.postgres.indexes
            from django.db import migrations, models
            from django.contrib.postgres.operations import AddIndexConcurrently
            
            
            class Migration(migrations.Migration):
            
                atomic = False
            
                dependencies = [
                    ("app_name", "parent_migration"),
                ]
            
                operations = [
                    AddIndexConcurrently(
                        model_name="mymodel",
                        index=django.contrib.postgres.indexes.GinIndex(
                            fields=["field1"],
                            name="field1_idx",
                        ),
                    ),
                    AddIndexConcurrently(
                        model_name="mymodel",
                        index=models.Index(
                            fields=["field2"], name="field2_idx"
                        ),
                    ),
                ]
            

            参考:https://docs.djangoproject.com/en/dev/ref/contrib/postgres/operations/#django.contrib.postgres.operations.AddIndexConcurrently

            【讨论】:

              猜你喜欢
              • 2019-12-30
              • 1970-01-01
              • 1970-01-01
              • 2022-07-06
              • 2016-04-14
              • 2017-10-17
              • 2015-07-26
              • 2018-05-04
              • 2015-12-08
              相关资源
              最近更新 更多