diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index faaefca..bacd998 100644
--- a/django/db/backends/mysql/base.py
+++ b/django/db/backends/mysql/base.py
@@ -15,11 +15,13 @@ except ImportError, e:
     from django.core.exceptions import ImproperlyConfigured
     raise ImproperlyConfigured("Error loading MySQLdb module: %s" % e)
 
+from django.utils.functional import cached_property
+
 # We want version (1, 2, 1, 'final', 2) or later. We can't just use
 # lexicographic ordering in this check because then (1, 2, 1, 'gamma')
 # inadvertently passes the version test.
 version = Database.version_info
-if (version < (1,2,1) or (version[:3] == (1, 2, 1) and
+if (version < (1, 2, 1) or (version[:3] == (1, 2, 1) and
         (len(version) < 5 or version[3] != 'final' or version[4] < 2))):
     from django.core.exceptions import ImproperlyConfigured
     raise ImproperlyConfigured("MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__)
@@ -163,6 +165,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
     supports_timezones = False
     requires_explicit_null_ordering_when_grouping = True
     allows_primary_key_0 = False
+    uses_savepoints = True
 
     def __init__(self, connection):
         super(DatabaseFeatures, self).__init__(connection)
@@ -258,15 +261,17 @@ class DatabaseOperations(BaseDatabaseOperations):
                 sql.append('%s %s;' % (style.SQL_KEYWORD('TRUNCATE'), style.SQL_FIELD(self.quote_name(table))))
             sql.append('SET FOREIGN_KEY_CHECKS = 1;')
 
-            # 'ALTER TABLE table AUTO_INCREMENT = 1;'... style SQL statements
-            # to reset sequence indices
-            sql.extend(["%s %s %s %s %s;" % \
-                (style.SQL_KEYWORD('ALTER'),
-                 style.SQL_KEYWORD('TABLE'),
-                 style.SQL_TABLE(self.quote_name(sequence['table'])),
-                 style.SQL_KEYWORD('AUTO_INCREMENT'),
-                 style.SQL_FIELD('= 1'),
-                ) for sequence in sequences])
+            # Truncate already resets the AUTO_INCREMENT field from
+            # MySQL version 5.0.13 onwards. Refs #16961.
+            if self.connection.mysql_version < (5,0,13):
+                sql.extend(
+                    ["%s %s %s %s %s;" % \
+                     (style.SQL_KEYWORD('ALTER'),
+                      style.SQL_KEYWORD('TABLE'),
+                      style.SQL_TABLE(self.quote_name(sequence['table'])),
+                      style.SQL_KEYWORD('AUTO_INCREMENT'),
+                      style.SQL_FIELD('= 1'),
+                     ) for sequence in sequences])
             return sql
         else:
             return []
@@ -387,8 +392,6 @@ class DatabaseWrapper(BaseDatabaseWrapper):
             self.connection = Database.connect(**kwargs)
             self.connection.encoders[SafeUnicode] = self.connection.encoders[unicode]
             self.connection.encoders[SafeString] = self.connection.encoders[str]
-            self.features.uses_savepoints = \
-                self.get_server_version() >= (5, 0, 3)
             connection_created.send(sender=self.__class__, connection=self)
         cursor = self.connection.cursor()
         if new_connection:
@@ -405,10 +408,11 @@ class DatabaseWrapper(BaseDatabaseWrapper):
         except Database.NotSupportedError:
             pass
 
-    def get_server_version(self):
+    @cached_property
+    def mysql_version(self):
         if not self.server_version:
             if not self._valid_connection():
-                self.cursor()
+                self.cursor().close()
             m = server_version_re.match(self.connection.get_server_info())
             if not m:
                 raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info())
diff --git a/django/db/backends/mysql/introspection.py b/django/db/backends/mysql/introspection.py
index ab4eebe..bb56ae3 100644
--- a/django/db/backends/mysql/introspection.py
+++ b/django/db/backends/mysql/introspection.py
@@ -65,27 +65,14 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
         key columns in given table.
         """
         key_columns = []
-        try:
-            cursor.execute("""
-                SELECT column_name, referenced_table_name, referenced_column_name
-                FROM information_schema.key_column_usage
-                WHERE table_name = %s
-                    AND table_schema = DATABASE()
-                    AND referenced_table_name IS NOT NULL
-                    AND referenced_column_name IS NOT NULL""", [table_name])
-            key_columns.extend(cursor.fetchall())
-        except (ProgrammingError, OperationalError):
-            # Fall back to "SHOW CREATE TABLE", for previous MySQL versions.
-            # Go through all constraints and save the equal matches.
-            cursor.execute("SHOW CREATE TABLE %s" % self.connection.ops.quote_name(table_name))
-            for row in cursor.fetchall():
-                pos = 0
-                while True:
-                    match = foreign_key_re.search(row[1], pos)
-                    if match == None:
-                        break
-                    pos = match.end()
-                    key_columns.append(match.groups())
+        cursor.execute("""
+            SELECT column_name, referenced_table_name, referenced_column_name
+            FROM information_schema.key_column_usage
+            WHERE table_name = %s
+                AND table_schema = DATABASE()
+                AND referenced_table_name IS NOT NULL
+                AND referenced_column_name IS NOT NULL""", [table_name])
+        key_columns.extend(cursor.fetchall())
         return key_columns
 
     def get_primary_key_column(self, cursor, table_name):
diff --git a/django/db/backends/mysql/validation.py b/django/db/backends/mysql/validation.py
index 663cc7d..de7474d 100644
--- a/django/db/backends/mysql/validation.py
+++ b/django/db/backends/mysql/validation.py
@@ -3,30 +3,13 @@ from django.db.backends import BaseDatabaseValidation
 class DatabaseValidation(BaseDatabaseValidation):
     def validate_field(self, errors, opts, f):
         """
-        There are some field length restrictions for MySQL:
-
-        - Prior to version 5.0.3, character fields could not exceed 255
-          characters in length.
-        - No character (varchar) fields can have a length exceeding 255
-          characters if they have a unique index on them.
+        MySQL has the following field length restriction:
+        No character (varchar) fields can have a length exceeding 255
+        characters if they have a unique index on them.
         """
         from django.db import models
-        from MySQLdb import OperationalError
-        try:
-            db_version = self.connection.get_server_version()
-            text_version = '.'.join([str(n) for n in db_version[:3]])
-        except OperationalError:
-            db_version = None
-            text_version = ''
         varchar_fields = (models.CharField, models.CommaSeparatedIntegerField,
                 models.SlugField)
-        if isinstance(f, varchar_fields) and f.max_length > 255:
-            if db_version and db_version < (5, 0, 3):
-                msg = '"%(name)s": %(cls)s cannot have a "max_length" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %(version)s).'
-            elif f.unique == True:
-                msg = '"%(name)s": %(cls)s cannot have a "max_length" greater than 255 when using "unique=True".'
-            else:
-                msg = None
-
-            if msg:
-                errors.add(opts, msg % {'name': f.name, 'cls': f.__class__.__name__, 'version': text_version})
+        if isinstance(f, varchar_fields) and f.max_length > 255 and f.unique:
+            msg = '"%(name)s": %(cls)s cannot have a "max_length" greater than 255 when using "unique=True".'
+            errors.add(opts, msg % {'name': f.name, 'cls': f.__class__.__name__})
diff --git a/docs/intro/install.txt b/docs/intro/install.txt
index ef04eba..95f7b27 100644
--- a/docs/intro/install.txt
+++ b/docs/intro/install.txt
@@ -39,11 +39,9 @@ you should see something like::
 Set up a database
 -----------------
 
-If you installed Python 2.6 or later, you can skip this step for now.
-
-If not, or if you'd like to work with a "large" database engine like PostgreSQL,
-MySQL, or Oracle, consult the :ref:`database installation information
-<database-installation>`.
+This step is only necessary if you'd like to work with a "large" database engine
+like PostgreSQL, MySQL, or Oracle. To install such a database, consult the
+:ref:`database installation information <database-installation>`.
 
 Remove any old versions of Django
 ---------------------------------
diff --git a/docs/ref/databases.txt b/docs/ref/databases.txt
index 59a0c36..c271946 100644
--- a/docs/ref/databases.txt
+++ b/docs/ref/databases.txt
@@ -122,30 +122,23 @@ lookups that use the ``LIKE`` operator in their SQL, as is done with the
 MySQL notes
 ===========
 
-Django expects the database to support transactions, referential integrity, and
-Unicode (UTF-8 encoding). Fortunately, MySQL_ has all these features as
-available as far back as 3.23. While it may be possible to use 3.23 or 4.0,
-you'll probably have less trouble if you use 4.1 or 5.0.
+Version support
+---------------
 
-MySQL 4.1
----------
+Django supports MySQL 5.0.3 and higher.
 
-`MySQL 4.1`_ has greatly improved support for character sets. It is possible to
-set different default character sets on the database, table, and column.
-Previous versions have only a server-wide character set setting. It's also the
-first version where the character set can be changed on the fly. 4.1 also has
-support for views, but Django currently doesn't use views.
+`MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed
+data on all database schema. Django's ``inspectdb`` feature uses this feature.
 
-MySQL 5.0
----------
+.. versionchanged:: 1.5
+    The minimum version requirement of MySQL 5.0.3 was set in Django 1.5.
 
-`MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed
-data on all database schema. Django's ``inspectdb`` feature uses this
-``information_schema`` if it's available. 5.0 also has support for stored
-procedures, but Django currently doesn't use stored procedures.
+Django expects the database to support Unicode (UTF-8 encoding) and delegates to
+it the task of enforcing transactions and referential integrity. It is important
+to be aware of the fact that the two latter ones aren't actually enforced by
+MySQL when using the MyISAM storage engine, see the next section.
 
 .. _MySQL: http://www.mysql.com/
-.. _MySQL 4.1: http://dev.mysql.com/doc/refman/4.1/en/index.html
 .. _MySQL 5.0: http://dev.mysql.com/doc/refman/5.0/en/index.html
 
 Storage engines
@@ -381,10 +374,6 @@ for the field. This affects :class:`~django.db.models.CharField`,
 :class:`~django.db.models.SlugField` and
 :class:`~django.db.models.CommaSeparatedIntegerField`.
 
-Furthermore, if you are using a version of MySQL prior to 5.0.3, all of those
-column types have a maximum length restriction of 255 characters, regardless
-of whether ``unique=True`` is specified or not.
-
 DateTime fields
 ~~~~~~~~~~~~~~~
 
diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
index d5b1ea8..f87b9c4 100644
--- a/tests/regressiontests/backends/tests.py
+++ b/tests/regressiontests/backends/tests.py
@@ -61,10 +61,34 @@ class OracleChecks(unittest.TestCase):
     def test_client_encoding(self):
         # If the backend is Oracle, test that the client encoding is set
         # correctly.  This was broken under Cygwin prior to r14781.
-        c = connection.cursor()  # Ensure the connection is initialized.
+        connection.cursor()  # Ensure the connection is initialized.
         self.assertEqual(connection.connection.encoding, "UTF-8")
         self.assertEqual(connection.connection.nencoding, "UTF-8")
 
+class MySQLTests(TestCase):
+    @unittest.skipUnless(connection.vendor == 'mysql',
+                        "Test valid only for MySQL")
+    def test_autoincrement(self):
+        """
+        Check that auto_increment fields are reset correctly by sql_flush().
+        Before MySQL version 5.0.13 TRUNCATE did not do auto_increment reset.
+        Refs #16961.
+        """
+        statements = connection.ops.sql_flush(no_style(),
+                                              tables=['test'],
+                                              sequences=[{
+                                                  'table': 'test',
+                                                  'col': 'somecol',
+                                              }])
+        found_reset = False
+        for sql in statements:
+            found_reset = found_reset or 'ALTER TABLE' in sql
+        if connection.mysql_version < (5,0,13):
+            self.assertTrue(found_reset)
+        else:
+            self.assertFalse(found_reset)
+
+ 
 class DateQuotingTest(TestCase):
 
     def test_django_date_trunc(self):
diff --git a/tests/regressiontests/test_runner/models.py b/tests/regressiontests/test_runner/models.py
index e69de29..9a072e6 100644
--- a/tests/regressiontests/test_runner/models.py
+++ b/tests/regressiontests/test_runner/models.py
@@ -0,0 +1,5 @@
+from django.db import models
+
+class Person(models.Model):
+    first_name = models.CharField(max_length=20)
+    last_name = models.CharField(max_length=20)
diff --git a/tests/regressiontests/test_runner/tests.py b/tests/regressiontests/test_runner/tests.py
index ccb65b4..3fc8d7f 100644
--- a/tests/regressiontests/test_runner/tests.py
+++ b/tests/regressiontests/test_runner/tests.py
@@ -8,13 +8,15 @@ from optparse import make_option
 from django.core.exceptions import ImproperlyConfigured
 from django.core.management import call_command
 from django import db
-from django.test import simple
+from django.db import connection
+from django.test import simple, TransactionTestCase
 from django.test.simple import DjangoTestSuiteRunner, get_tests
 from django.test.testcases import connections_support_transactions
 from django.utils import unittest
 from django.utils.importlib import import_module
 
 from ..admin_scripts.tests import AdminScriptTestCase
+from .models import Person
 
 
 TEST_APP_OK = 'regressiontests.test_runner.valid_app.models'
@@ -262,3 +264,24 @@ class Sqlite3InMemoryTestDbs(unittest.TestCase):
                 self.assertTrue(connections_support_transactions(), msg)
             finally:
                 db.connections = old_db_connections
+
+
+class AutoIncrementResetTest(TransactionTestCase):
+    """
+    Here we test creating the same model two times in different test methods,
+    and check that both times they get "1" as their PK value. That is, we test
+    that AutoField values start from 1 for each transactional test case.
+    """
+    @unittest.skipIf(connection.vendor == 'oracle',
+                     "Oracle's auto-increment fields are not reset between "
+                     "tests")
+    def test_autoincrement_reset1(self):
+        p = Person.objects.create(first_name='Jack', last_name='Smith')
+        self.assertEquals(p.pk, 1)
+    
+    @unittest.skipIf(connection.vendor == 'oracle',
+                     "Oracle's auto-increment fields are not reset between "
+                     "tests")
+    def test_autoincrement_reset2(self):
+        p = Person.objects.create(first_name='Jack', last_name='Smith')
+        self.assertEquals(p.pk, 1)
