diff --git a/django/contrib/gis/db/backends/mysql/schema.py b/django/contrib/gis/db/backends/mysql/schema.py
index 5305bd2280..693c48dba6 100644
--- a/django/contrib/gis/db/backends/mysql/schema.py
+++ b/django/contrib/gis/db/backends/mysql/schema.py
@@ -16,8 +16,8 @@ class MySQLGISSchemaEditor(DatabaseSchemaEditor):
         self.geometry_sql = []
 
     def skip_default(self, field):
-        # Geometry fields are stored as BLOB/TEXT, for which MySQL and MariaDB
-        # < 10.2.1 don't support defaults.
+        # Geometry fields are stored as BLOB/TEXT, for which MySQL < 8.0.13 and
+        # MariaDB < 10.2.1 don't support defaults.
         if isinstance(field, GeometryField) and not self._supports_limited_data_type_defaults:
             return True
         return super().skip_default(field)
diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py
index efb291f4e6..3a0dc39238 100644
--- a/django/db/backends/base/schema.py
+++ b/django/db/backends/base/schema.py
@@ -217,14 +217,15 @@ class BaseDatabaseSchemaEditor:
         include_default = include_default and not self.skip_default(field)
         if include_default:
             default_value = self.effective_default(field)
+            column_default = ' DEFAULT ' + self._column_default_sql(field)
             if default_value is not None:
                 if self.connection.features.requires_literal_defaults:
                     # Some databases can't take defaults as a parameter (oracle)
                     # If this is the case, the individual schema backend should
                     # implement prepare_default
-                    sql += " DEFAULT %s" % self.prepare_default(default_value)
+                    sql += column_default % self.prepare_default(default_value)
                 else:
-                    sql += " DEFAULT %s"
+                    sql += column_default
                     params += [default_value]
         # Oracle treats the empty string ('') as null, so coerce the null
         # option whenever '' is a possible value.
@@ -263,6 +264,13 @@ class BaseDatabaseSchemaEditor:
             'requires_literal_defaults must provide a prepare_default() method'
         )
 
+    def _column_default_sql(self, field):
+        """
+        Return the SQL to use in a DEFAULT clause. The resulting string should
+        contain a '%s' placeholder for a default value.
+        """
+        return '%s'
+
     @staticmethod
     def _effective_default(field):
         # This method allows testing its logic without a connection.
@@ -826,7 +834,7 @@ class BaseDatabaseSchemaEditor:
         argument) a default to new_field's column.
         """
         new_default = self.effective_default(new_field)
-        default = '%s'
+        default = self._column_default_sql(new_field)
         params = [new_default]
 
         if drop:
diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py
index 58f54c70a8..febc246e09 100644
--- a/django/db/backends/mysql/base.py
+++ b/django/db/backends/mysql/base.py
@@ -131,8 +131,8 @@ class DatabaseWrapper(BaseDatabaseWrapper):
     }
 
     # For these data types:
-    # - MySQL and MariaDB < 10.2.1 don't accept default values and implicitly
-    #   treat them as nullable
+    # - MySQL < 8.0.13 and MariaDB < 10.2.1 don't accept default values and
+    #   implicitly treat them as nullable
     # - all versions of MySQL and MariaDB don't support full width database
     #   indexes
     _limited_data_types = (
diff --git a/django/db/backends/mysql/schema.py b/django/db/backends/mysql/schema.py
index 8c54565e3d..d138606791 100644
--- a/django/db/backends/mysql/schema.py
+++ b/django/db/backends/mysql/schema.py
@@ -54,10 +54,22 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
 
     @property
     def _supports_limited_data_type_defaults(self):
-        # Only MariaDB >= 10.2.1 supports defaults for BLOB and TEXT.
+        # MariaDB >= 10.2.1 and MySQL >= 8.0.13 supports defaults for BLOB
+        # and TEXT.
         if self.connection.mysql_is_mariadb:
             return self.connection.mysql_version >= (10, 2, 1)
-        return False
+        return self.connection.mysql_version >= (8, 0, 13)
+
+    def _column_default_sql(self, field):
+        if (
+            not self.connection.mysql_is_mariadb and
+            self._supports_limited_data_type_defaults and
+            self._is_limited_data_type(field)
+        ):
+            # MySQL supports defaults for BLOB and TEXT columns only if the
+            # default value is written as an expression i.e. in parentheses.
+            return '(%s)'
+        return super()._column_default_sql(field)
 
     def add_field(self, model, field):
         super().add_field(model, field)