diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php
index 7618a7c..6f7a005 100644
--- a/core/lib/Drupal/Core/Database/Schema.php
+++ b/core/lib/Drupal/Core/Database/Schema.php
@@ -167,6 +167,18 @@
 
 abstract class Schema implements PlaceholderInterface {
 
+  /**
+   * The maximum allowed length of a database index.
+   *
+   * The MySQL MyISAM storage engine enforces a limit of 1000 bytes, which
+   * corresponds to 333 UTF-8 characters. We enforce this limitation for all
+   * schemata, so that it is not possible to inadvertently declare a schema
+   * that is not compatible with MySQL.
+   *
+   * @see http://dev.mysql.com/doc/refman/5.6/en/myisam-storage-engine.html
+   */
+  const MAX_INDEX_SIZE = 1000;
+
   protected $connection;
 
   /**
@@ -661,6 +673,7 @@ public function createTable($name, $table) {
     if ($this->tableExists($name)) {
       throw new SchemaObjectExistsException(t('Table @name already exists.', array('@name' => $name)));
     }
+    $this->validateTable($name, $table);
     $statements = $this->createTableSql($name, $table);
     foreach ($statements as $statement) {
       $this->connection->query($statement);
@@ -668,6 +681,122 @@ public function createTable($name, $table) {
   }
 
   /**
+   * Validates a table definition.
+   *
+   * @param string $name
+   *   The name of the table.
+   * @param array $table
+   *   A Schema API table definition array.
+   *
+   * @throws Drupal\Core\Database\SchemaIndexLengthException
+   *   If a specified index is too long.
+   *
+   * @see \Drupal\Core\Database\Schema::addIndex()
+   */
+  public function validateTable($name, array $table) {
+    $spec = array_intersect_key($table, array('unique keys' => 1, 'indexes' => 1));
+    if (isset($table['primary key'])) {
+      $spec['primary key'] = array('primary key' => $table['primary key']);
+    }
+    foreach ($spec as $type => $keys) {
+      foreach ($keys as $name => $fields) {
+        $total_size = 0;
+        foreach ($fields as $field) {
+          $size = $this->indexSize($field);
+          // Schema::indexSize returns FALSE if the field by itself is too
+          // large to index.
+          if ($size === FALSE) {
+            throw new SchemaIndexLengthException('Table index @name exceeds the maximum allowed size.');
+            break;
+          }
+          else {
+            $total_size += $size;
+          }
+        }
+        if ($total_size > static::MAX_INDEX_SIZE) {
+          throw new SchemaIndexLengthException('Table index @name exceeds the maximum allowed size.');
+        }
+      }
+    }
+  }
+
+  /**
+   * Returns the index length to reserve when validating a given field.
+   *
+   * @param array $field
+   *   The database field definition array from hook_schema().
+   *
+   * @return int|FALSE
+   *   The approximate length of the index, in bytes, or FALSE if an index is
+   *   not acceptable with the given field.
+   */
+  protected function indexSize($field) {
+    // Default to 0, so that custom field types are not counted.
+    $size = 0;
+
+    // If just the field name is provided, the whole field is used for
+    // the index, so add its total length.
+    if (is_string($field)) {
+      // For fields with a specified length, use that.
+      if (isset($table['fields'][$field]['length'])) {
+        // Each unicode character uses 3 bytes.
+        $size = 3 * $table['fields'][$field]['length'];
+      }
+      // For fields without a specified length, allot space based on the
+      // field type's size in MySQL.
+      // @see http://drupal.org/node/159605
+      else {
+        switch ($field['type']) {
+          case 'serial':
+          case 'int':
+          case 'float':
+            // If the field type is serial, int, or float, allot 8 bytes.
+            $size = 8;
+            break;
+
+          case 'numeric':
+            // If the field type is numeric, allot 29 bytes.
+            $size = 29;
+            break;
+
+          case 'char':
+            // If the field type is char, allot 255 bytes.
+            $size = 255;
+            break;
+
+          case 'char':
+            // If the field type is text, allot 256 bytes for tiny or small
+            // fields, and fail otherwise.
+            if (($field['size'] == 'tiny') || ($field['size'] == 'small')) {
+              $size = 256;
+            }
+            else {
+              // Larger sizes are too big for an index.
+              return FALSE;
+            }
+            break;
+
+          case 'blob':
+          case 'varchar':
+            // BLOBs and unlimited varchars are always too big.
+            return FALSE;
+            break;
+        }
+      }
+    }
+
+    // Otherwise, if the field is an array, then the first key of the
+    // array is the field name, and the second is the length used in the
+    // index, e.g. array('my_field', 64)
+    // See \Drupal\Core\Database\Driver\mysql\Schema::createKeySql().
+    else {
+      $size = $field[1];
+    }
+
+    return $size;
+  }
+
+  /**
    * Return an array of field names from an array of key/index column specifiers.
    *
    * This is usually an identity function but if a key/index uses a column prefix
diff --git a/core/lib/Drupal/Core/Database/SchemaIndexLengthException.php b/core/lib/Drupal/Core/Database/SchemaIndexLengthException.php
new file mode 100644
index 0000000..b223353
--- /dev/null
+++ b/core/lib/Drupal/Core/Database/SchemaIndexLengthException.php
@@ -0,0 +1,15 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\Core\Database\SchemaIndexLengthException.
+ */
+
+namespace Drupal\Core\Database;
+
+/**
+ * Exception thrown if a schema contains an index that is too long.
+ *
+ * @see Drupal\Core\Database\Schema::MAX_INDEX_LENGTH
+ */
+class SchemaIndexLengthException extends SchemaException implements DatabaseException { }
