diff --git a/includes/cache.inc b/includes/cache.inc
index 4c2bed3..deb34de 100644
--- a/includes/cache.inc
+++ b/includes/cache.inc
@@ -335,6 +335,11 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
    * Implements DrupalCacheInterface::getMultiple().
    */
   function getMultiple(&$cids) {
+    $cid_mapping = array();
+    foreach ($cids as $cid) {
+      $cid_mapping[$this->normalizeCid($cid)] = $cid;
+    }
+
     try {
       // Garbage collection necessary when enforcing a minimum cache lifetime.
       $this->garbageCollection($this->bin);
@@ -346,9 +351,11 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
       // is used here only due to the performance overhead we would incur
       // otherwise. When serving an uncached page, the overhead of using
       // db_select() is a much smaller proportion of the request.
-      $result = db_query('SELECT cid, data, created, expire, serialized FROM {' . db_escape_table($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => $cids));
+      $result = db_query('SELECT cid, data, created, expire, serialized FROM {' . db_escape_table($this->bin) . '} WHERE cid IN (:cids)', array(':cids' => array_keys($cid_mapping)));
       $cache = array();
       foreach ($result as $item) {
+        // Map the cache ID back to the original.
+        $item->cid = $cid_mapping[$item->cid];
         $item = $this->prepareItem($item);
         if ($item) {
           $cache[$item->cid] = $item;
@@ -462,7 +469,7 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
 
     try {
       db_merge($this->bin)
-        ->key(array('cid' => $cid))
+        ->key(array('cid' => $this->normalizeCid($cid)))
         ->fields($fields)
         ->execute();
     }
@@ -523,22 +530,22 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
         }
         else {
           db_delete($this->bin)
-            ->condition('cid', db_like($cid) . '%', 'LIKE')
+            ->condition('cid', db_like($this->normalizeCid($cid)) . '%', 'LIKE')
             ->execute();
         }
       }
       elseif (is_array($cid)) {
+        $cid = array_values(array_map(array($this, 'normalizeCid'), $cid));
         // Delete in chunks when a large array is passed.
-        do {
+        foreach (array_chunk($cid, 1000) as $cids_chunk) {
           db_delete($this->bin)
-            ->condition('cid', array_splice($cid, 0, 1000), 'IN')
+            ->condition('cid', $cids_chunk, 'IN')
             ->execute();
         }
-        while (count($cid));
       }
       else {
         db_delete($this->bin)
-          ->condition('cid', $cid)
+          ->condition('cid', $this->normalizeCid($cid))
           ->execute();
       }
     }
@@ -577,4 +584,28 @@ class DrupalDatabaseCache implements DrupalCacheInterface {
     // Confirm that all fields are present.
     return isset($schema['fields']) && !array_diff($fields, array_keys($schema['fields']));
   }
+
+  /**
+   * Normalizes a cache ID in order to comply with database limitations.
+   *
+   * @param string $cid
+   *   The passed in cache ID.
+   *
+   * @return string
+   *   An ASCII-encoded cache ID that is at most 255 characters long.
+   */
+  protected function normalizeCid($cid) {
+    // Nothing to do if the ID is a US ASCII string of 255 characters or less.
+    $cid_is_ascii = mb_check_encoding($cid, 'ASCII');
+    if (strlen($cid) <= 255 && $cid_is_ascii) {
+      return $cid;
+    }
+    // Return a string that uses as much as possible of the original cache ID
+    // with the hash appended.
+    $hash = drupal_hash_base64($cid);
+    if (!$cid_is_ascii) {
+      return $hash;
+    }
+    return substr($cid, 0, 255 - strlen($hash)) . $hash;
+  }
 }
diff --git a/modules/simpletest/tests/cache.test b/modules/simpletest/tests/cache.test
index b42de36..c70bf36 100644
--- a/modules/simpletest/tests/cache.test
+++ b/modules/simpletest/tests/cache.test
@@ -152,6 +152,17 @@ class CacheSavingCase extends CacheTestCase {
   }
 
   /**
+   * Test a long key.
+   */
+  function testLongKey() {
+    // Check with a long key.
+    $long_cid = str_repeat('a', 300);
+    cache_set($long_cid, 'test', 'cache');
+    $cache = cache_get($long_cid, 'cache');
+    $this->assertTrue(isset($cache->data) && $cache->data === 'test', 'Cache with a long key is saved and restored properly.');
+  }
+
+  /**
    * Check or a variable is stored and restored properly.
    */
   function checkVariable($var) {
@@ -193,25 +204,32 @@ class CacheGetMultipleUnitTest extends CacheTestCase {
   function testCacheMultiple() {
     $item1 = $this->randomName(10);
     $item2 = $this->randomName(10);
+    $item3 = $this->randomName(10);
+    $long_cid = str_repeat('a', 300);
     cache_set('item1', $item1, $this->default_bin);
     cache_set('item2', $item2, $this->default_bin);
+    cache_set($long_cid, $item3, $this->default_bin);
     $this->assertTrue($this->checkCacheExists('item1', $item1), 'Item 1 is cached.');
     $this->assertTrue($this->checkCacheExists('item2', $item2), 'Item 2 is cached.');
+    $this->assertTrue($this->checkCacheExists($long_cid, $item3), 'Item 3 is cached.');
 
-    // Fetch both records from the database with cache_get_multiple().
-    $item_ids = array('item1', 'item2');
+    // Fetch all records from the database with cache_get_multiple().
+    $item_ids = array('item1', 'item2', $long_cid);
     $items = cache_get_multiple($item_ids, $this->default_bin);
     $this->assertEqual($items['item1']->data, $item1, 'Item was returned from cache successfully.');
     $this->assertEqual($items['item2']->data, $item2, 'Item was returned from cache successfully.');
+    $this->assertEqual($items[$long_cid]->data, $item3, 'Item was returned from cache successfully.');
 
-    // Remove one item from the cache.
+    // Remove 2 items from the cache.
     cache_clear_all('item2', $this->default_bin);
+    cache_clear_all($long_cid, $this->default_bin);
 
     // Confirm that only one item is returned by cache_get_multiple().
     $item_ids = array('item1', 'item2');
     $items = cache_get_multiple($item_ids, $this->default_bin);
     $this->assertEqual($items['item1']->data, $item1, 'Item was returned from cache successfully.');
     $this->assertFalse(isset($items['item2']), 'Item was not returned from the cache.');
+    $this->assertFalse(isset($items[$long_cid]), 'Item was not returned from the cache.');
     $this->assertTrue(count($items) == 1, 'Only valid cache entries returned.');
   }
 }
@@ -246,60 +264,81 @@ class CacheClearCase extends CacheTestCase {
 
     $this->assertCacheRemoved(t('Cache was removed after clearing cid.'), 'test_cid_clear');
 
+    $long_cid = str_repeat('a', 300);
+    cache_set($long_cid, $this->default_value, $this->default_bin);
+    $this->assertCacheExists(t('Long cache was set for clearing cid.'), $this->default_value, $long_cid);
+    cache_clear_all($long_cid, $this->default_bin);
+    $this->assertCacheRemoved(t('Long cache was removed after clearing cid.'), $long_cid);
+
     cache_set('test_cid_clear1', $this->default_value, $this->default_bin);
     cache_set('test_cid_clear2', $this->default_value, $this->default_bin);
+    cache_set($long_cid, $this->default_value, $this->default_bin);
     $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value)
-                      && $this->checkCacheExists('test_cid_clear2', $this->default_value),
-                      'Two caches were created for checking cid "*" with wildcard false.');
+                      && $this->checkCacheExists('test_cid_clear2', $this->default_value)
+                      && $this->checkCacheExists($long_cid, $this->default_value),
+                      'Three caches were created for checking cid "*" with wildcard false.');
     cache_clear_all('*', $this->default_bin);
     $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value)
-                      && $this->checkCacheExists('test_cid_clear2', $this->default_value),
-                      'Two caches still exists after clearing cid "*" with wildcard false.');
+                      && $this->checkCacheExists('test_cid_clear2', $this->default_value)
+                      && $this->checkCacheExists($long_cid, $this->default_value),
+                      'Three caches still exists after clearing cid "*" with wildcard false.');
   }
 
   /**
    * Test clearing using wildcard.
    */
   function testClearWildcard() {
+    $long_cid = str_repeat('a', 300);
     cache_set('test_cid_clear1', $this->default_value, $this->default_bin);
     cache_set('test_cid_clear2', $this->default_value, $this->default_bin);
+    cache_set($long_cid, $this->default_value, $this->default_bin);
     $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value)
-                      && $this->checkCacheExists('test_cid_clear2', $this->default_value),
-                      'Two caches were created for checking cid "*" with wildcard true.');
+                      && $this->checkCacheExists('test_cid_clear2', $this->default_value)
+                      && $this->checkCacheExists($long_cid, $this->default_value),
+                      'Three caches were created for checking cid "*" with wildcard true.');
     cache_clear_all('*', $this->default_bin, TRUE);
     $this->assertFalse($this->checkCacheExists('test_cid_clear1', $this->default_value)
-                      || $this->checkCacheExists('test_cid_clear2', $this->default_value),
-                      'Two caches removed after clearing cid "*" with wildcard true.');
+                      || $this->checkCacheExists('test_cid_clear2', $this->default_value)
+                      || $this->checkCacheExists($long_cid, $this->default_value),
+                      'Three caches removed after clearing cid "*" with wildcard true.');
 
+    $long_cid = 'test_' . str_repeat('a', 300);
     cache_set('test_cid_clear1', $this->default_value, $this->default_bin);
     cache_set('test_cid_clear2', $this->default_value, $this->default_bin);
+    cache_set($long_cid, $this->default_value, $this->default_bin);
     $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value)
-                      && $this->checkCacheExists('test_cid_clear2', $this->default_value),
-                      'Two caches were created for checking cid substring with wildcard true.');
+                      && $this->checkCacheExists('test_cid_clear2', $this->default_value)
+                      && $this->checkCacheExists($long_cid, $this->default_value),
+                      'Three caches were created for checking cid substring with wildcard true.');
     cache_clear_all('test_', $this->default_bin, TRUE);
     $this->assertFalse($this->checkCacheExists('test_cid_clear1', $this->default_value)
-                      || $this->checkCacheExists('test_cid_clear2', $this->default_value),
-                      'Two caches removed after clearing cid substring with wildcard true.');
+                      || $this->checkCacheExists('test_cid_clear2', $this->default_value)
+                      || $this->checkCacheExists($long_cid, $this->default_value),
+                      'Three caches removed after clearing cid substring with wildcard true.');
   }
 
   /**
    * Test clearing using an array.
    */
   function testClearArray() {
-    // Create three cache entries.
+    // Create four cache entries.
+    $long_cid = str_repeat('a', 300);
     cache_set('test_cid_clear1', $this->default_value, $this->default_bin);
     cache_set('test_cid_clear2', $this->default_value, $this->default_bin);
     cache_set('test_cid_clear3', $this->default_value, $this->default_bin);
+    cache_set($long_cid, $this->default_value, $this->default_bin);
     $this->assertTrue($this->checkCacheExists('test_cid_clear1', $this->default_value)
                       && $this->checkCacheExists('test_cid_clear2', $this->default_value)
-                      && $this->checkCacheExists('test_cid_clear3', $this->default_value),
-                      'Three cache entries were created.');
+                      && $this->checkCacheExists('test_cid_clear3', $this->default_value)
+                      && $this->checkCacheExists($long_cid, $this->default_value),
+                      'Four cache entries were created.');
 
-    // Clear two entries using an array.
-    cache_clear_all(array('test_cid_clear1', 'test_cid_clear2'), $this->default_bin);
+    // Clear three entries using an array.
+    cache_clear_all(array('test_cid_clear1', 'test_cid_clear2', $long_cid), $this->default_bin);
     $this->assertFalse($this->checkCacheExists('test_cid_clear1', $this->default_value)
-                       || $this->checkCacheExists('test_cid_clear2', $this->default_value),
-                       'Two cache entries removed after clearing with an array.');
+                       || $this->checkCacheExists('test_cid_clear2', $this->default_value)
+                       || $this->checkCacheExists($long_cid, $this->default_value),
+                       'Three cache entries removed after clearing with an array.');
 
     $this->assertTrue($this->checkCacheExists('test_cid_clear3', $this->default_value),
                       'Entry was not cleared from the cache');
