Edited at

Django1.7 + MySQLで寿司ビール問題が起きるようなカラムにindexを貼る

More than 3 years have passed since last update.


目的

Django1.7 + MySQL5.5以上で、utf8mb4を使う


普通にやると


settings.py

DATABASES = {

'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'hoge',
'USER': 'hoge',
'OPTIONS': {
'charset': 'utf8mb4',
}
}
}


models.py

from django.db import models

class User(models.Model):
screen_name = models.CharField(max_length=255, unique=True)


Django1.7系からMigrationが使えるようになったので、それを使ってModelを定義する


create-db

create database hoge DEFAULT CHARSET utf8mb4;



shell

$ python manage.py makemigrations

$ python manage.py migrate

> django.db.utils.OperationalError: (1709, 'Index column size too large. The maximum column size is 767 bytes.')

よくある、InnoDBのindex sizeの問題である


解決法

http://blog.kamipo.net/entry/2012/11/13/102024

この辺にあるようにinnodb_large_prefixを使うのが良さげ


my.cnf

[client]

default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
innodb_file_format = Barracuda
innodb_file_per_table = 1
innodb_large_prefix


しかし、ROW_FORMATはどうやって指定するんや


ROW_FORMAT指定方法その1

http://qiita.com/miyagi389/items/ffc9918fd8ef2f2a1a45

しかし、これではmigrationsで作ったModelには反映されない!!


ROW_FORMAT指定方法その2


manage.py

#!/usr/bin/env python

# coding: utf-8
from __future__ import unicode_literals
import os
import sys

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testapp.settings")

from django.db.backends.mysql.schema import DatabaseSchemaEditor
DatabaseSchemaEditor.sql_create_table += " ROW_FORMAT=DYNAMIC"

from django.core.management import execute_from_command_line

execute_from_command_line(sys.argv)


migrateでもROW_FORMAT=DYNAMICが適用されるようになったよ!


補足

Djangoに組み込むモジュールによっては、

migrationに対応していないものもあるので、両方組み合わせて使うとよさげ