django-celery-beat icon indicating copy to clipboard operation
django-celery-beat copied to clipboard

Fix max_length issue for mysql

Open milind-shakya-sp opened this issue 6 years ago • 21 comments

Current issues with mysql + django-celery-beat

If you want to run django-celery-beat with MySQL, you might run into some issues. One such issue is when you try to run python manage.py migrate django_celery_beat, you might get the following error

 django.db.utils.OperationalError: (1071, 'Specified key was too long; max key length is 767 bytes')

To get around this issue, with this pr, we can set the following in the settings file

DJANGO_CELERY_BEAT_NAME_MAX_LENGTH=191 (or any other value if any other db other than MySQL is causing similar issues.) max_length of 191 seems to work for MySQL.

milind-shakya-sp avatar Dec 03 '18 22:12 milind-shakya-sp

Rebased. @auvipy I agree in most cases, we would'nt update an existing migration and instead create a new one, but in this case, its required to update the existing migration, since without it, things will break for MySQL, when it tries to run the first migration. This way it will work for all databases.

milind-shakya-sp avatar Dec 04 '18 15:12 milind-shakya-sp

could you check this works in a backward compatible way?

auvipy avatar Dec 05 '18 16:12 auvipy

@auvipy Yes it should work since it defaults to the original max_length to maintain backwards compatibility.

milind-shakya-sp avatar Dec 05 '18 16:12 milind-shakya-sp

is it possible to test the change to check it won't regress? @tinylambda could you check this PR?

auvipy avatar Dec 07 '18 18:12 auvipy

is it possible to test the change to check it won't regress? @tinylambda could you check this PR?

what about removing the db constraints to avoid the MySQL's limitation, instead, we use Django model's signal mechanism pre_save to avoid duplication at the framework level ?

tinylambda avatar Dec 10 '18 03:12 tinylambda

is it possible to test the change to check it won't regress? @tinylambda could you check this PR?

what about removing the db constraints to avoid the limitation, instead, we use Django model's signal mechanism pre_save to avoid duplication?

@milind-shakya-sp

tinylambda avatar Dec 10 '18 03:12 tinylambda

@tinylambda Are you suggesting, removing the max_length=200 restriction altogether?

hmmm, not sure if that will have some other side-effects as a result.

milind-shakya-sp avatar Dec 10 '18 15:12 milind-shakya-sp

@tinylambda Are you suggesting, removing the max_length=200 restriction altogether?

hmmm, not sure if that will have some other side-effects as a result.

I means removing unique=True

tinylambda avatar Dec 11 '18 02:12 tinylambda

@tinylambda i dont think the issue is with the uniqueness constraint. its with the max length value being too large for mysql.

milind-shakya-sp avatar Dec 11 '18 03:12 milind-shakya-sp

@tinylambda i dont think the issue is with the uniqueness constraint. its with the max length value being too large for mysql.

You need this: https://stackoverflow.com/questions/1814532/1071-specified-key-was-too-long-max-key-length-is-767-bytes?answertab=active#tab-top

unique=True will create an index on the column.

tinylambda avatar Dec 11 '18 06:12 tinylambda

@tinylambda i dont think the issue is with the uniqueness constraint. its with the max length value being too large for mysql.

You need this: https://stackoverflow.com/questions/1814532/1071-specified-key-was-too-long-max-key-length-is-767-bytes?answertab=active#tab-top

unique=True will create an index on the column.

Any update ? @milind-shakya-sp

tinylambda avatar Dec 12 '18 04:12 tinylambda

@tinylambda I haven't had the chance to test the changes when we remove unique=True, but don't we actually want unique=True, since that will prevent PeriodicTask with duplicate names?

milind-shakya-sp avatar Dec 12 '18 15:12 milind-shakya-sp

@tinylambda I haven't had the chance to test the changes when we remove unique=True, but don't we actually want unique=True, since that will prevent PeriodicTask with duplicate names?

What about adding another column to store the md5sum of the name, and add unique=True on this column, because md5sum is fixed-length (32 chars), its behavior is predictable.

tinylambda avatar Dec 13 '18 03:12 tinylambda

@tinylambda I feel that might be a bit overkill. Any issues with the current approach?

milind-shakya-sp avatar Dec 13 '18 16:12 milind-shakya-sp

What about adding another column to store the md5sum of the name, and add unique=True on this column, because md5sum is fixed-length (32 chars), its behavior is predictable.

I can come up with only one quite artificial advantage of this approach: we don't lose eight characters for MySQL utf8mb4 users (they cannot use the app in its current form anyways).

but we would still have to touch the existing migrations, because they just won't work for utf8mb4. I agree, that the md5 approach would be overkill, involving lots of refactoring and assuring in tests, that we never forget to fill in the value. it would also require a data migration for existing projects to calculate the md5.

in a manual review i cannot find any backwards compatibility breaking changes. existing installations of this app won't see any changes. and new installations behave the same, too.

Maybe @milind-shakya-sp you can include https://github.com/milind-shakya-sp/django-celery-beat/pull/1 in your PR to prove the backwards compatibility with my tests.

tuky avatar Feb 11 '19 10:02 tuky

It's quite unfortunate, the build failed just because of an unrelated RemovedInSphinx20Warning. Apart from that you can now see in the build logs that we successfully tested the new setting :-)

tuky avatar Feb 15 '19 12:02 tuky

could you please rebase? and check the Travis?

auvipy avatar Apr 23 '19 03:04 auvipy

will it help? the last master build also failed: https://travis-ci.org/celery/django-celery-beat/builds/513951725?utm_source=github_status&utm_medium=notification

tuky avatar Apr 23 '19 07:04 tuky

rebased but got some new errors. will look at them after sometime unless @tuky wants to take a stab at them first.

milind-shakya-sp avatar Apr 23 '19 17:04 milind-shakya-sp

So, I did a little research on this. and here are the options from what I can see.

  1. I really dislike the use of settings that modify migration files, but I would be okay with merging based on the fact that django-celery-results already has the same hack.
  2. Since this is only an issue with mysql before 5.7, which is already 6 years old, so I also think it would be acceptable to say upgrade your mysql to something current, but the older versions are still supported on most platforms (mysql support grid).
  3. We could detect if we're on mysql, and if so automatically set the max length to 190, which is below the amount for the issue. This would be similar to using the django setting, but would keep control of the values on our end and make it "just work" rather than people having to google the error and setting a special setting for it.
  4. Make a custom migration that only sets unique on only the first 190 chars of the field if running on mysql. The length would remain 200, but it the unique constraint would apply to only the first 190 chars.

I think I like either 3 or 4 the most because then people wouldn't even hit the issue to begin with.

liquidpele avatar May 27 '19 00:05 liquidpele

upgrading minimal MySQL version should let us not make this change

auvipy avatar Jan 20 '21 17:01 auvipy