Runserver/runfcgi/startup with MySQL is unlike any other database
|Reported by:||Dan McGee||Owned by:||nobody|
|Component:||Database layer (models, ORM)||Version:||1.3|
|Cc:||georgedorn@…||Triage Stage:||Ready for checkin|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
Django provides a BaseDatabaseValidation class. The only database engine to subclass this is MySQL.
$ django-admin.py foobar $ cd foobar <edit settings.py to use ENGINE "django.db.backends.mysql"> $ python2 manage.py runserver Validating models... Unhandled exception in thread started by <bound method Command.inner_run of <django.contrib.staticfiles.management.commands.runserver.Command object at 0x27f5950>> Traceback (most recent call last): File "/usr/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 88, in inner_run self.validate(display_num_errors=True) File "/usr/lib/python2.7/site-packages/django/core/management/base.py", line 249, in validate num_errors = get_validation_errors(s, app) File "/usr/lib/python2.7/site-packages/django/core/management/validation.py", line 103, in get_validation_errors connection.validation.validate_field(e, opts, f) File "/usr/lib/python2.7/site-packages/django/db/backends/mysql/validation.py", line 14, in validate_field db_version = self.connection.get_server_version() File "/usr/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 338, in get_server_version self.cursor() File "/usr/lib/python2.7/site-packages/django/db/backends/__init__.py", line 250, in cursor cursor = self.make_debug_cursor(self._cursor()) File "/usr/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 322, in _cursor self.connection = Database.connect(**kwargs) File "/usr/lib/python2.7/site-packages/MySQLdb/__init__.py", line 81, in Connect return Connection(*args, **kwargs) File "/usr/lib/python2.7/site-packages/MySQLdb/connections.py", line 187, in __init__ super(Connection, self).__init__(*args, **kwargs2) _mysql_exceptions.OperationalError: (2002, "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)")
$ django-admin.py foobar $ cd foobar <edit settings.py to use ENGINE "django.db.backends.sqlite3"> $ python2 manage.py runserver Validating models... 0 errors found Django version 1.3, using settings 'foobar.settings' Development server is running at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
Why this is a problem:
- The number one reason this is bad- no other database engine completely halts the Django project load if it is not up. It simply cannot service requests at all. All other database engines at least show a helpful 500 page on each failed request.
- Validation like this doesn't come early enough for someone that develops on one database engine and then switches to MySQL.
- The validation that needs a valid connection is testing an extreme edge case- those using versions before 5.0.3. From http://www.mysql.com/support/eol-notice.html, Extended Support for 4.1 and Active Support for 5.0 ended ended 2009-12-31.
- We are likely missing validation cases for other databases; we should be consistent in trying to do it right or not do it at all.
- The validation here isn't even correct for unique fields. max_length can be greater than 255, in reality the unique indexes are constrained to 1000 bytes. For that matter, this also does nothing to keep one from shooting themselves in the foot with a combo unique index produced by unique_together.
- Drop this database field validation completely, as only one database is even providing it and not even fully checking.
- Remove the bits referencing the connection; this will solve the most severe problem and those using old database versions should be well aware of the restrictions.
- Make the validation module do the right thing more often, fixing MySQL and adding it for other databases.
Tangentially related to #7040.
Change History (9)
comment:1 Changed 5 years ago by
|Patch needs improvement:||unset|
|Triage Stage:||Unreviewed → Design decision needed|