diff --git includes/file.inc includes/file.inc
index e8db634..84bf3cc 100644
--- includes/file.inc
+++ includes/file.inc
@@ -571,28 +571,38 @@ function file_load($fid) {
  * @see hook_file_update()
  */
 function file_save(stdClass $file) {
-  $file->timestamp = REQUEST_TIME;
-  $file->filesize = filesize($file->uri);
+  $transaction = db_transaction();
 
-  // Load the stored entity, if any.
-  if (!empty($file->fid) && !isset($file->original)) {
-    $file->original = entity_load_unchanged('file', $file->fid);
-  }
+  try {
+    $file->timestamp = REQUEST_TIME;
+    $file->filesize = filesize($file->uri);
+
+    // Load the stored entity, if any.
+    if (!empty($file->fid) && !isset($file->original)) {
+      $file->original = entity_load_unchanged('file', $file->fid);
+    }
+
+    if (empty($file->fid)) {
+      drupal_write_record('file_managed', $file);
+      // Inform modules about the newly added file.
+      module_invoke_all('file_insert', $file);
+      module_invoke_all('entity_insert', $file, 'file');
+    }
+    else {
+      drupal_write_record('file_managed', $file, 'fid');
+      // Inform modules that the file has been updated.
+      module_invoke_all('file_update', $file);
+      module_invoke_all('entity_update', $file, 'file');
+    }
 
-  if (empty($file->fid)) {
-    drupal_write_record('file_managed', $file);
-    // Inform modules about the newly added file.
-    module_invoke_all('file_insert', $file);
-    module_invoke_all('entity_insert', $file, 'file');
+    unset($file->original);
   }
-  else {
-    drupal_write_record('file_managed', $file, 'fid');
-    // Inform modules that the file has been updated.
-    module_invoke_all('file_update', $file);
-    module_invoke_all('entity_update', $file, 'file');
+  catch (Exception $e) {
+    $transaction->rollback('file');
+    watchdog_exception('file', $e);
+    throw $e;
   }
 
-  unset($file->original);
   return $file;
 }
 
diff --git includes/menu.inc includes/menu.inc
index 1488dc8..9aab8f3 100644
--- includes/menu.inc
+++ includes/menu.inc
@@ -2901,151 +2901,161 @@ function _menu_delete_item($item, $force = FALSE) {
  *   saved.
  */
 function menu_link_save(&$item) {
-  drupal_alter('menu_link', $item);
-
-  // This is the easiest way to handle the unique internal path '<front>',
-  // since a path marked as external does not need to match a router path.
-  $item['external'] = (url_is_external($item['link_path'])  || $item['link_path'] == '<front>') ? 1 : 0;
-  // Load defaults.
-  $item += array(
-    'menu_name' => 'navigation',
-    'weight' => 0,
-    'link_title' => '',
-    'hidden' => 0,
-    'has_children' => 0,
-    'expanded' => 0,
-    'options' => array(),
-    'module' => 'menu',
-    'customized' => 0,
-    'updated' => 0,
-  );
-  $existing_item = FALSE;
-  if (isset($item['mlid'])) {
-    if ($existing_item = db_query("SELECT * FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $item['mlid']))->fetchAssoc()) {
-      $existing_item['options'] = unserialize($existing_item['options']);
-    }
-  }
-
-  // Try to find a parent link. If found, assign it and derive its menu.
-  $parent = _menu_link_find_parent($item);
-  if (!empty($parent['mlid'])) {
-    $item['plid'] = $parent['mlid'];
-    $item['menu_name'] = $parent['menu_name'];
-  }
-  // If no corresponding parent link was found, move the link to the top-level.
-  else {
-    $item['plid'] = 0;
-  }
-  $menu_name = $item['menu_name'];
+  $transaction = db_transaction();
 
-  if (!$existing_item) {
-    $item['mlid'] = db_insert('menu_links')
-      ->fields(array(
-        'menu_name' => $item['menu_name'],
-        'plid' => $item['plid'],
-        'link_path' => $item['link_path'],
-        'hidden' => $item['hidden'],
-        'external' => $item['external'],
-        'has_children' => $item['has_children'],
-        'expanded' => $item['expanded'],
-        'weight' => $item['weight'],
-        'module' => $item['module'],
-        'link_title' => $item['link_title'],
-        'options' => serialize($item['options']),
-        'customized' => $item['customized'],
-        'updated' => $item['updated'],
-      ))
-      ->execute();
-  }
+  try {
+    drupal_alter('menu_link', $item);
 
-  // Directly fill parents for top-level links.
-  if ($item['plid'] == 0) {
-    $item['p1'] = $item['mlid'];
-    for ($i = 2; $i <= MENU_MAX_DEPTH; $i++) {
-      $item["p$i"] = 0;
+    // This is the easiest way to handle the unique internal path '<front>',
+    // since a path marked as external does not need to match a router path.
+    $item['external'] = (url_is_external($item['link_path'])  || $item['link_path'] == '<front>') ? 1 : 0;
+    // Load defaults.
+    $item += array(
+      'menu_name' => 'navigation',
+      'weight' => 0,
+      'link_title' => '',
+      'hidden' => 0,
+      'has_children' => 0,
+      'expanded' => 0,
+      'options' => array(),
+      'module' => 'menu',
+      'customized' => 0,
+      'updated' => 0,
+    );
+    $existing_item = FALSE;
+    if (isset($item['mlid'])) {
+      if ($existing_item = db_query("SELECT * FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $item['mlid']))->fetchAssoc()) {
+        $existing_item['options'] = unserialize($existing_item['options']);
+      }
     }
-    $item['depth'] = 1;
-  }
-  // Otherwise, ensure that this link's depth is not beyond the maximum depth
-  // and fill parents based on the parent link.
-  else {
-    if ($item['has_children'] && $existing_item) {
-      $limit = MENU_MAX_DEPTH - menu_link_children_relative_depth($existing_item) - 1;
+
+    // Try to find a parent link. If found, assign it and derive its menu.
+    $parent = _menu_link_find_parent($item);
+    if (!empty($parent['mlid'])) {
+      $item['plid'] = $parent['mlid'];
+      $item['menu_name'] = $parent['menu_name'];
     }
+    // If no corresponding parent link was found, move the link to the top-level.
     else {
-      $limit = MENU_MAX_DEPTH - 1;
+      $item['plid'] = 0;
     }
-    if ($parent['depth'] > $limit) {
-      return FALSE;
+    $menu_name = $item['menu_name'];
+
+    if (!$existing_item) {
+      $item['mlid'] = db_insert('menu_links')
+        ->fields(array(
+          'menu_name' => $item['menu_name'],
+          'plid' => $item['plid'],
+          'link_path' => $item['link_path'],
+          'hidden' => $item['hidden'],
+          'external' => $item['external'],
+          'has_children' => $item['has_children'],
+          'expanded' => $item['expanded'],
+          'weight' => $item['weight'],
+          'module' => $item['module'],
+          'link_title' => $item['link_title'],
+          'options' => serialize($item['options']),
+          'customized' => $item['customized'],
+          'updated' => $item['updated'],
+        ))
+        ->execute();
     }
-    $item['depth'] = $parent['depth'] + 1;
-    _menu_link_parents_set($item, $parent);
-  }
-  // Need to check both plid and menu_name, since plid can be 0 in any menu.
-  if ($existing_item && ($item['plid'] != $existing_item['plid'] || $menu_name != $existing_item['menu_name'])) {
-    _menu_link_move_children($item, $existing_item);
-  }
-  // Find the router_path.
-  if (empty($item['router_path'])  || !$existing_item || ($existing_item['link_path'] != $item['link_path'])) {
-    if ($item['external']) {
-      $item['router_path'] = '';
+
+    // Directly fill parents for top-level links.
+    if ($item['plid'] == 0) {
+      $item['p1'] = $item['mlid'];
+      for ($i = 2; $i <= MENU_MAX_DEPTH; $i++) {
+        $item["p$i"] = 0;
+      }
+      $item['depth'] = 1;
     }
+    // Otherwise, ensure that this link's depth is not beyond the maximum depth
+    // and fill parents based on the parent link.
     else {
-      // Find the router path which will serve this path.
-      $item['parts'] = explode('/', $item['link_path'], MENU_MAX_PARTS);
-      $item['router_path'] = _menu_find_router_path($item['link_path']);
+      if ($item['has_children'] && $existing_item) {
+        $limit = MENU_MAX_DEPTH - menu_link_children_relative_depth($existing_item) - 1;
+      }
+      else {
+        $limit = MENU_MAX_DEPTH - 1;
+      }
+      if ($parent['depth'] > $limit) {
+        return FALSE;
+      }
+      $item['depth'] = $parent['depth'] + 1;
+      _menu_link_parents_set($item, $parent);
     }
-  }
-  // If every value in $existing_item is the same in the $item, there is no
-  // reason to run the update queries or clear the caches. We use
-  // array_intersect_assoc() with the $item as the first parameter because
-  // $item may have additional keys left over from building a router entry.
-  // The intersect removes the extra keys, allowing a meaningful comparison.
-  if (!$existing_item || (array_intersect_assoc($item, $existing_item)) != $existing_item) {
-    db_update('menu_links')
-      ->fields(array(
-        'menu_name' => $item['menu_name'],
-        'plid' => $item['plid'],
-        'link_path' => $item['link_path'],
-        'router_path' => $item['router_path'],
-        'hidden' => $item['hidden'],
-        'external' => $item['external'],
-        'has_children' => $item['has_children'],
-        'expanded' => $item['expanded'],
-        'weight' => $item['weight'],
-        'depth' => $item['depth'],
-        'p1' => $item['p1'],
-        'p2' => $item['p2'],
-        'p3' => $item['p3'],
-        'p4' => $item['p4'],
-        'p5' => $item['p5'],
-        'p6' => $item['p6'],
-        'p7' => $item['p7'],
-        'p8' => $item['p8'],
-        'p9' => $item['p9'],
-        'module' => $item['module'],
-        'link_title' => $item['link_title'],
-        'options' => serialize($item['options']),
-        'customized' => $item['customized'],
-      ))
-      ->condition('mlid', $item['mlid'])
-      ->execute();
-    // Check the has_children status of the parent.
-    _menu_update_parental_status($item);
-    menu_cache_clear($menu_name);
-    if ($existing_item && $menu_name != $existing_item['menu_name']) {
-      menu_cache_clear($existing_item['menu_name']);
+    // Need to check both plid and menu_name, since plid can be 0 in any menu.
+    if ($existing_item && ($item['plid'] != $existing_item['plid'] || $menu_name != $existing_item['menu_name'])) {
+      _menu_link_move_children($item, $existing_item);
     }
-    // Notify modules we have acted on a menu item.
-    $hook = 'menu_link_insert';
-    if ($existing_item) {
-      $hook = 'menu_link_update';
+    // Find the router_path.
+    if (empty($item['router_path'])  || !$existing_item || ($existing_item['link_path'] != $item['link_path'])) {
+      if ($item['external']) {
+        $item['router_path'] = '';
+      }
+      else {
+        // Find the router path which will serve this path.
+        $item['parts'] = explode('/', $item['link_path'], MENU_MAX_PARTS);
+        $item['router_path'] = _menu_find_router_path($item['link_path']);
+      }
     }
-    module_invoke_all($hook, $item);
-    // Now clear the cache.
-    _menu_clear_page_cache();
+    // If every value in $existing_item is the same in the $item, there is no
+    // reason to run the update queries or clear the caches. We use
+    // array_intersect_assoc() with the $item as the first parameter because
+    // $item may have additional keys left over from building a router entry.
+    // The intersect removes the extra keys, allowing a meaningful comparison.
+    if (!$existing_item || (array_intersect_assoc($item, $existing_item)) != $existing_item) {
+      db_update('menu_links')
+        ->fields(array(
+          'menu_name' => $item['menu_name'],
+          'plid' => $item['plid'],
+          'link_path' => $item['link_path'],
+          'router_path' => $item['router_path'],
+          'hidden' => $item['hidden'],
+          'external' => $item['external'],
+          'has_children' => $item['has_children'],
+          'expanded' => $item['expanded'],
+          'weight' => $item['weight'],
+          'depth' => $item['depth'],
+          'p1' => $item['p1'],
+          'p2' => $item['p2'],
+          'p3' => $item['p3'],
+          'p4' => $item['p4'],
+          'p5' => $item['p5'],
+          'p6' => $item['p6'],
+          'p7' => $item['p7'],
+          'p8' => $item['p8'],
+          'p9' => $item['p9'],
+          'module' => $item['module'],
+          'link_title' => $item['link_title'],
+          'options' => serialize($item['options']),
+          'customized' => $item['customized'],
+        ))
+        ->condition('mlid', $item['mlid'])
+        ->execute();
+      // Check the has_children status of the parent.
+      _menu_update_parental_status($item);
+      menu_cache_clear($menu_name);
+      if ($existing_item && $menu_name != $existing_item['menu_name']) {
+        menu_cache_clear($existing_item['menu_name']);
+      }
+      // Notify modules we have acted on a menu item.
+      $hook = 'menu_link_insert';
+      if ($existing_item) {
+        $hook = 'menu_link_update';
+      }
+      module_invoke_all($hook, $item);
+      // Now clear the cache.
+      _menu_clear_page_cache();
+    }
+  }
+  catch (Exception $e) {
+    $transaction->rollback('menu link');
+    watchdog_exception('menu link', $e);
+    throw $e;
   }
-  return $item['mlid'];
+
+  return !empty($item['mlid']) ? $item['mlid'] : FALSE;
 }
 
 /**
@@ -3586,78 +3596,87 @@ function _menu_router_build($callbacks) {
  * Helper function to save data from menu_router_build() to the router table.
  */
 function _menu_router_save($menu, $masks) {
-  // Delete the existing router since we have some data to replace it.
-  db_truncate('menu_router')->execute();
-
-  // Prepare insert object.
-  $insert = db_insert('menu_router')
-    ->fields(array(
-      'path',
-      'load_functions',
-      'to_arg_functions',
-      'access_callback',
-      'access_arguments',
-      'page_callback',
-      'page_arguments',
-      'delivery_callback',
-      'fit',
-      'number_parts',
-      'context',
-      'tab_parent',
-      'tab_root',
-      'title',
-      'title_callback',
-      'title_arguments',
-      'theme_callback',
-      'theme_arguments',
-      'type',
-      'description',
-      'position',
-      'weight',
-      'include_file',
-    ));
-
-  $num_records = 0;
+  $transaction = db_transaction();
 
-  foreach ($menu as $path => $item) {
-    // Fill in insert object values.
-    $insert->values(array(
-      'path' => $item['path'],
-      'load_functions' => $item['load_functions'],
-      'to_arg_functions' => $item['to_arg_functions'],
-      'access_callback' => $item['access callback'],
-      'access_arguments' => serialize($item['access arguments']),
-      'page_callback' => $item['page callback'],
-      'page_arguments' => serialize($item['page arguments']),
-      'delivery_callback' => $item['delivery callback'],
-      'fit' => $item['_fit'],
-      'number_parts' => $item['_number_parts'],
-      'context' => $item['context'],
-      'tab_parent' => $item['tab_parent'],
-      'tab_root' => $item['tab_root'],
-      'title' => $item['title'],
-      'title_callback' => $item['title callback'],
-      'title_arguments' => ($item['title arguments'] ? serialize($item['title arguments']) : ''),
-      'theme_callback' => $item['theme callback'],
-      'theme_arguments' => serialize($item['theme arguments']),
-      'type' => $item['type'],
-      'description' => $item['description'],
-      'position' => $item['position'],
-      'weight' => $item['weight'],
-      'include_file' => $item['include file'],
-    ));
+  try {
+    // Delete the existing router since we have some data to replace it.
+    db_truncate('menu_router')->execute();
 
-    // Execute in batches to avoid the memory overhead of all of those records
-    // in the query object.
-    if (++$num_records == 20) {
-      $insert->execute();
-      $num_records = 0;
+    // Prepare insert object.
+    $insert = db_insert('menu_router')
+      ->fields(array(
+        'path',
+        'load_functions',
+        'to_arg_functions',
+        'access_callback',
+        'access_arguments',
+        'page_callback',
+        'page_arguments',
+        'delivery_callback',
+        'fit',
+        'number_parts',
+        'context',
+        'tab_parent',
+        'tab_root',
+        'title',
+        'title_callback',
+        'title_arguments',
+        'theme_callback',
+        'theme_arguments',
+        'type',
+        'description',
+        'position',
+        'weight',
+        'include_file',
+      ));
+
+    $num_records = 0;
+
+    foreach ($menu as $path => $item) {
+      // Fill in insert object values.
+      $insert->values(array(
+        'path' => $item['path'],
+        'load_functions' => $item['load_functions'],
+        'to_arg_functions' => $item['to_arg_functions'],
+        'access_callback' => $item['access callback'],
+        'access_arguments' => serialize($item['access arguments']),
+        'page_callback' => $item['page callback'],
+        'page_arguments' => serialize($item['page arguments']),
+        'delivery_callback' => $item['delivery callback'],
+        'fit' => $item['_fit'],
+        'number_parts' => $item['_number_parts'],
+        'context' => $item['context'],
+        'tab_parent' => $item['tab_parent'],
+        'tab_root' => $item['tab_root'],
+        'title' => $item['title'],
+        'title_callback' => $item['title callback'],
+        'title_arguments' => ($item['title arguments'] ? serialize($item['title arguments']) : ''),
+        'theme_callback' => $item['theme callback'],
+        'theme_arguments' => serialize($item['theme arguments']),
+        'type' => $item['type'],
+        'description' => $item['description'],
+        'position' => $item['position'],
+        'weight' => $item['weight'],
+        'include_file' => $item['include file'],
+      ));
+
+      // Execute in batches to avoid the memory overhead of all of those records
+      // in the query object.
+      if (++$num_records == 20) {
+        $insert->execute();
+        $num_records = 0;
+      }
     }
+    // Insert any remaining records.
+    $insert->execute();
+    // Store the masks.
+    variable_set('menu_masks', $masks);
+  }
+  catch (Exception $e) {
+    $transaction->rollback('menu router');
+    watchdog_exception('menu router', $e);
+    throw $e;
   }
-  // Insert any remaining records.
-  $insert->execute();
-  // Store the masks.
-  variable_set('menu_masks', $masks);
 
   return $menu;
 }
diff --git includes/path.inc includes/path.inc
index 83ebcb0..b64b64e 100644
--- includes/path.inc
+++ includes/path.inc
@@ -432,20 +432,29 @@ function path_load($conditions) {
  *   - language: (optional) The language of the alias.
  */
 function path_save(&$path) {
-  $path += array('pid' => NULL, 'language' => LANGUAGE_NONE);
+  $transaction = db_transaction();
 
-  // Insert or update the alias.
-  $status = drupal_write_record('url_alias', $path, (!empty($path['pid']) ? 'pid' : array()));
+  try {
+    $path += array('pid' => NULL, 'language' => LANGUAGE_NONE);
 
-  // Verify that a record was written.
-  if ($status) {
-    if ($status === SAVED_NEW) {
-      module_invoke_all('path_insert', $path);
-    }
-    else {
-      module_invoke_all('path_update', $path);
+    // Insert or update the alias.
+    $status = drupal_write_record('url_alias', $path, (!empty($path['pid']) ? 'pid' : array()));
+
+    // Verify that a record was written.
+    if ($status) {
+      if ($status === SAVED_NEW) {
+        module_invoke_all('path_insert', $path);
+      }
+      else {
+        module_invoke_all('path_update', $path);
+      }
+      drupal_clear_path_cache($path['source']);
     }
-    drupal_clear_path_cache($path['source']);
+  }
+  catch (Exception $e) {
+    $transaction->rollback('path');
+    watchdog_exception('path', $e);
+    throw $e;
   }
 }
 
diff --git modules/filter/filter.module modules/filter/filter.module
index 7babfc6..ea90edd 100644
--- modules/filter/filter.module
+++ modules/filter/filter.module
@@ -190,82 +190,92 @@ function filter_format_load($format_id) {
  *       See hook_filter_info() for details.
  */
 function filter_format_save($format) {
-  $format->name = trim($format->name);
-  $format->cache = _filter_format_is_cacheable($format);
-  if (!isset($format->status)) {
-    $format->status = 1;
-  }
-  if (!isset($format->weight)) {
-    $format->weight = 0;
-  }
+  $transaction = db_transaction();
+  $return = FALSE;
+
+  try {
+    $format->name = trim($format->name);
+    $format->cache = _filter_format_is_cacheable($format);
+    if (!isset($format->status)) {
+      $format->status = 1;
+    }
+    if (!isset($format->weight)) {
+      $format->weight = 0;
+    }
 
-  // Insert or update the text format.
-  $return = db_merge('filter_format')
-    ->key(array('format' => $format->format))
-    ->fields(array(
-      'name' => $format->name,
-      'cache' => (int) $format->cache,
-      'status' => (int) $format->status,
-      'weight' => (int) $format->weight,
-    ))
-    ->execute();
+    // Insert or update the text format.
+    $return = db_merge('filter_format')
+      ->key(array('format' => $format->format))
+      ->fields(array(
+        'name' => $format->name,
+        'cache' => (int) $format->cache,
+        'status' => (int) $format->status,
+        'weight' => (int) $format->weight,
+      ))
+      ->execute();
 
-  // Programmatic saves may not contain any filters.
-  if (!isset($format->filters)) {
-    $format->filters = array();
-  }
-  $filter_info = filter_get_filters();
-  foreach ($filter_info as $name => $filter) {
-    // Add new filters without weight to the bottom.
-    if (!isset($format->filters[$name]['weight'])) {
-      $format->filters[$name]['weight'] = 10;
+    // Programmatic saves may not contain any filters.
+    if (!isset($format->filters)) {
+      $format->filters = array();
     }
-    $format->filters[$name]['status'] = isset($format->filters[$name]['status']) ? $format->filters[$name]['status'] : 0;
-    $format->filters[$name]['module'] = $filter['module'];
+    $filter_info = filter_get_filters();
+    foreach ($filter_info as $name => $filter) {
+      // Add new filters without weight to the bottom.
+      if (!isset($format->filters[$name]['weight'])) {
+        $format->filters[$name]['weight'] = 10;
+      }
+      $format->filters[$name]['status'] = isset($format->filters[$name]['status']) ? $format->filters[$name]['status'] : 0;
+      $format->filters[$name]['module'] = $filter['module'];
 
-    // If settings were passed, only ensure default settings.
-    if (isset($format->filters[$name]['settings'])) {
-      if (isset($filter['default settings'])) {
-        $format->filters[$name]['settings'] = array_merge($filter['default settings'], $format->filters[$name]['settings']);
+      // If settings were passed, only ensure default settings.
+      if (isset($format->filters[$name]['settings'])) {
+        if (isset($filter['default settings'])) {
+          $format->filters[$name]['settings'] = array_merge($filter['default settings'], $format->filters[$name]['settings']);
+        }
+      }
+      // Otherwise, use default settings or fall back to an empty array.
+      else {
+        $format->filters[$name]['settings'] = isset($filter['default settings']) ? $filter['default settings'] : array();
       }
+
+      $fields = array();
+      $fields['weight'] = $format->filters[$name]['weight'];
+      $fields['status'] = $format->filters[$name]['status'];
+      $fields['module'] = $format->filters[$name]['module'];
+      $fields['settings'] = serialize($format->filters[$name]['settings']);
+
+      db_merge('filter')
+        ->key(array(
+          'format' => $format->format,
+          'name' => $name,
+        ))
+        ->fields($fields)
+        ->execute();
+    }
+
+    if ($return == SAVED_NEW) {
+      module_invoke_all('filter_format_insert', $format);
     }
-    // Otherwise, use default settings or fall back to an empty array.
     else {
-      $format->filters[$name]['settings'] = isset($filter['default settings']) ? $filter['default settings'] : array();
+      module_invoke_all('filter_format_update', $format);
+      // Explicitly indicate that the format was updated. We need to do this
+      // since if the filters were updated but the format object itself was not,
+      // the merge query above would not return an indication that anything had
+      // changed.
+      $return = SAVED_UPDATED;
+
+      // Clear the filter cache whenever a text format is updated.
+      cache_clear_all($format->format . ':', 'cache_filter', TRUE);
     }
 
-    $fields = array();
-    $fields['weight'] = $format->filters[$name]['weight'];
-    $fields['status'] = $format->filters[$name]['status'];
-    $fields['module'] = $format->filters[$name]['module'];
-    $fields['settings'] = serialize($format->filters[$name]['settings']);
-
-    db_merge('filter')
-      ->key(array(
-        'format' => $format->format,
-        'name' => $name,
-      ))
-      ->fields($fields)
-      ->execute();
-  }
-
-  if ($return == SAVED_NEW) {
-    module_invoke_all('filter_format_insert', $format);
+    filter_formats_reset();
   }
-  else {
-    module_invoke_all('filter_format_update', $format);
-    // Explicitly indicate that the format was updated. We need to do this
-    // since if the filters were updated but the format object itself was not,
-    // the merge query above would not return an indication that anything had
-    // changed.
-    $return = SAVED_UPDATED;
-
-    // Clear the filter cache whenever a text format is updated.
-    cache_clear_all($format->format . ':', 'cache_filter', TRUE);
+  catch (Exception $e) {
+    $transaction->rollback('filter format');
+    watchdog_exception('filter format', $e);
+    throw $e;
   }
 
-  filter_formats_reset();
-
   return $return;
 }
 
diff --git modules/image/image.module modules/image/image.module
index 4ca0e34..61e95c6 100644
--- modules/image/image.module
+++ modules/image/image.module
@@ -381,29 +381,38 @@ function image_image_default_styles() {
  */
 function image_image_style_save($style) {
   if (isset($style['old_name']) && $style['old_name'] != $style['name']) {
-    $instances = field_read_instances();
-    // Loop through all fields searching for image fields.
-    foreach ($instances as $instance) {
-      if ($instance['widget']['module'] == 'image') {
-        $instance_changed = FALSE;
-        foreach ($instance['display'] as $view_mode => $display) {
-          // Check if the formatter involves an image style.
-          if ($display['type'] == 'image' && $display['settings']['image_style'] == $style['old_name']) {
-            // Update display information for any instance using the image
-            // style that was just deleted.
-            $instance['display'][$view_mode]['settings']['image_style'] = $style['name'];
+    $transaction = db_transaction();
+
+    try {
+      $instances = field_read_instances();
+      // Loop through all fields searching for image fields.
+      foreach ($instances as $instance) {
+        if ($instance['widget']['module'] == 'image') {
+          $instance_changed = FALSE;
+          foreach ($instance['display'] as $view_mode => $display) {
+            // Check if the formatter involves an image style.
+            if ($display['type'] == 'image' && $display['settings']['image_style'] == $style['old_name']) {
+              // Update display information for any instance using the image
+              // style that was just deleted.
+              $instance['display'][$view_mode]['settings']['image_style'] = $style['name'];
+              $instance_changed = TRUE;
+            }
+          }
+          if ($instance['widget']['settings']['preview_image_style'] == $style['old_name']) {
+            $instance['widget']['settings']['preview_image_style'] = $style['name'];
             $instance_changed = TRUE;
           }
-        }
-        if ($instance['widget']['settings']['preview_image_style'] == $style['old_name']) {
-          $instance['widget']['settings']['preview_image_style'] = $style['name'];
-          $instance_changed = TRUE;
-        }
-        if ($instance_changed) {
-          field_update_instance($instance);
+          if ($instance_changed) {
+            field_update_instance($instance);
+          }
         }
       }
     }
+    catch (Exception $e) {
+      $transaction->rollback('image style');
+      watchdog_exception('image style', $e);
+      throw $e;
+    }
   }
 }
 
diff --git modules/menu/menu.module modules/menu/menu.module
index ded4bd2..33bf0f8 100644
--- modules/menu/menu.module
+++ modules/menu/menu.module
@@ -251,23 +251,32 @@ function menu_load_all() {
  * @see menu_load()
  */
 function menu_save($menu) {
-  $status = db_merge('menu_custom')
-    ->key(array('menu_name' => $menu['menu_name']))
-    ->fields(array(
-      'title' => $menu['title'],
-      'description' => $menu['description'],
-    ))
-    ->execute();
-  menu_cache_clear_all();
-
-  switch ($status) {
-    case SAVED_NEW:
-      module_invoke_all('menu_insert', $menu);
-      break;
-
-    case SAVED_UPDATED:
-      module_invoke_all('menu_update', $menu);
-      break;
+  $transaction = db_transaction();
+
+  try {
+    $status = db_merge('menu_custom')
+      ->key(array('menu_name' => $menu['menu_name']))
+      ->fields(array(
+        'title' => $menu['title'],
+        'description' => $menu['description'],
+      ))
+      ->execute();
+    menu_cache_clear_all();
+
+    switch ($status) {
+      case SAVED_NEW:
+        module_invoke_all('menu_insert', $menu);
+        break;
+
+      case SAVED_UPDATED:
+        module_invoke_all('menu_update', $menu);
+        break;
+    }
+  }
+  catch (Exception $e) {
+    $transaction->rollback('menu');
+    watchdog_exception('menu', $e);
+    throw $e;
   }
 }
 
diff --git modules/node/node.module modules/node/node.module
index 8535a3d..312a76d 100644
--- modules/node/node.module
+++ modules/node/node.module
@@ -490,52 +490,62 @@ function node_type_load($name) {
  *   Status flag indicating outcome of the operation.
  */
 function node_type_save($info) {
-  $is_existing = FALSE;
-  $existing_type = !empty($info->old_type) ? $info->old_type : $info->type;
-  $is_existing = (bool) db_query_range('SELECT 1 FROM {node_type} WHERE type = :type', 0, 1, array(':type' => $existing_type))->fetchField();
-  $type = node_type_set_defaults($info);
-
-  $fields = array(
-    'type' => (string) $type->type,
-    'name' => (string) $type->name,
-    'base' => (string) $type->base,
-    'has_title' => (int) $type->has_title,
-    'title_label' => (string) $type->title_label,
-    'description' => (string) $type->description,
-    'help' => (string) $type->help,
-    'custom' => (int) $type->custom,
-    'modified' => (int) $type->modified,
-    'locked' => (int) $type->locked,
-    'disabled' => (int) $type->disabled,
-    'module' => $type->module,
-  );
+  $transaction = db_transaction();
+  $status = FALSE;
 
-  if ($is_existing) {
-    db_update('node_type')
-      ->fields($fields)
-      ->condition('type', $existing_type)
-      ->execute();
+  try {
+    $is_existing = FALSE;
+    $existing_type = !empty($info->old_type) ? $info->old_type : $info->type;
+    $is_existing = (bool) db_query_range('SELECT 1 FROM {node_type} WHERE type = :type', 0, 1, array(':type' => $existing_type))->fetchField();
+    $type = node_type_set_defaults($info);
+
+    $fields = array(
+      'type' => (string) $type->type,
+      'name' => (string) $type->name,
+      'base' => (string) $type->base,
+      'has_title' => (int) $type->has_title,
+      'title_label' => (string) $type->title_label,
+      'description' => (string) $type->description,
+      'help' => (string) $type->help,
+      'custom' => (int) $type->custom,
+      'modified' => (int) $type->modified,
+      'locked' => (int) $type->locked,
+      'disabled' => (int) $type->disabled,
+      'module' => $type->module,
+    );
 
-    if (!empty($type->old_type) && $type->old_type != $type->type) {
-      field_attach_rename_bundle('node', $type->old_type, $type->type);
+    if ($is_existing) {
+      db_update('node_type')
+        ->fields($fields)
+        ->condition('type', $existing_type)
+        ->execute();
+
+      if (!empty($type->old_type) && $type->old_type != $type->type) {
+        field_attach_rename_bundle('node', $type->old_type, $type->type);
+      }
+      module_invoke_all('node_type_update', $type);
+      $status = SAVED_UPDATED;
     }
-    module_invoke_all('node_type_update', $type);
-    $status = SAVED_UPDATED;
-  }
-  else {
-    $fields['orig_type'] = (string) $type->orig_type;
-    db_insert('node_type')
-      ->fields($fields)
-      ->execute();
+    else {
+      $fields['orig_type'] = (string) $type->orig_type;
+      db_insert('node_type')
+        ->fields($fields)
+        ->execute();
 
-    field_attach_create_bundle('node', $type->type);
+      field_attach_create_bundle('node', $type->type);
 
-    module_invoke_all('node_type_insert', $type);
-    $status = SAVED_NEW;
-  }
+      module_invoke_all('node_type_insert', $type);
+      $status = SAVED_NEW;
+    }
 
-  // Clear the node type cache.
-  node_type_cache_reset();
+    // Clear the node type cache.
+    node_type_cache_reset();
+  }
+  catch (Exception $e) {
+    $transaction->rollback('node type');
+    watchdog_exception('node type', $e);
+    throw $e;
+  }
 
   return $status;
 }
diff --git modules/system/system.module modules/system/system.module
index 8a415ab..9838cf7 100644
--- modules/system/system.module
+++ modules/system/system.module
@@ -3759,41 +3759,50 @@ function system_date_format_type_delete($date_format_type) {
  *   identifier.
  */
 function system_date_format_save($date_format, $dfid = 0) {
-  $format = array();
-  $format['dfid'] = $dfid;
-  $format['type'] = $date_format['type'];
-  $format['format'] = $date_format['format'];
-  $format['locked'] = $date_format['locked'];
+  $transaction = db_transaction();
+
+  try {
+    $format = array();
+    $format['dfid'] = $dfid;
+    $format['type'] = $date_format['type'];
+    $format['format'] = $date_format['format'];
+    $format['locked'] = $date_format['locked'];
+
+    // Update date_format table.
+    if (!empty($date_format['is_new'])) {
+      drupal_write_record('date_formats', $format);
+    }
+    else {
+      $keys = ($dfid ? array('dfid') : array('format', 'type'));
+      drupal_write_record('date_formats', $format, $keys);
+    }
 
-  // Update date_format table.
-  if (!empty($date_format['is_new'])) {
-    drupal_write_record('date_formats', $format);
-  }
-  else {
-    $keys = ($dfid ? array('dfid') : array('format', 'type'));
-    drupal_write_record('date_formats', $format, $keys);
-  }
-
-  $languages = language_list('enabled');
-  $languages = $languages[1];
-
-  $locale_format = array();
-  $locale_format['type'] = $date_format['type'];
-  $locale_format['format'] = $date_format['format'];
-
-  // Check if the suggested language codes are configured and enabled.
-  if (!empty($date_format['locales'])) {
-    foreach ($date_format['locales'] as $langcode) {
-      // Only proceed if language is enabled.
-      if (in_array($langcode, $languages)) {
-        $is_existing = (bool) db_query_range('SELECT 1 FROM {date_format_locale} WHERE type = :type AND language = :language', 0, 1, array(':type' => $date_format['type'], ':language' => $langcode))->fetchField();
-        if (!$is_existing) {
-          $locale_format['language'] = $langcode;
-          drupal_write_record('date_format_locale', $locale_format);
+    $languages = language_list('enabled');
+    $languages = $languages[1];
+
+    $locale_format = array();
+    $locale_format['type'] = $date_format['type'];
+    $locale_format['format'] = $date_format['format'];
+
+    // Check if the suggested language codes are configured and enabled.
+    if (!empty($date_format['locales'])) {
+      foreach ($date_format['locales'] as $langcode) {
+        // Only proceed if language is enabled.
+        if (in_array($langcode, $languages)) {
+          $is_existing = (bool) db_query_range('SELECT 1 FROM {date_format_locale} WHERE type = :type AND language = :language', 0, 1, array(':type' => $date_format['type'], ':language' => $langcode))->fetchField();
+          if (!$is_existing) {
+            $locale_format['language'] = $langcode;
+            drupal_write_record('date_format_locale', $locale_format);
+          }
         }
       }
     }
   }
+  catch (Exception $e) {
+    $transaction->rollback('system date format');
+    watchdog_exception('system date format', $e);
+    throw $e;
+  }
 }
 
 /**
diff --git modules/taxonomy/taxonomy.module modules/taxonomy/taxonomy.module
index a78436e..c285c17 100644
--- modules/taxonomy/taxonomy.module
+++ modules/taxonomy/taxonomy.module
@@ -384,46 +384,56 @@ function taxonomy_admin_vocabulary_title_callback($vocabulary) {
  * Save a vocabulary given a vocabulary object.
  */
 function taxonomy_vocabulary_save($vocabulary) {
-  // Prevent leading and trailing spaces in vocabulary names.
-  if (!empty($vocabulary->name)) {
-    $vocabulary->name = trim($vocabulary->name);
-  }
-  // Load the stored entity, if any.
-  if (!empty($vocabulary->vid)) {
-    if (!isset($vocabulary->original)) {
-      $vocabulary->original = entity_load_unchanged('taxonomy_vocabulary', $vocabulary->vid);
+  $transaction = db_transaction();
+  $status = FALSE;
+
+  try {
+    // Prevent leading and trailing spaces in vocabulary names.
+    if (!empty($vocabulary->name)) {
+      $vocabulary->name = trim($vocabulary->name);
+    }
+    // Load the stored entity, if any.
+    if (!empty($vocabulary->vid)) {
+      if (!isset($vocabulary->original)) {
+        $vocabulary->original = entity_load_unchanged('taxonomy_vocabulary', $vocabulary->vid);
+      }
+      // Make sure machine name changes are easily detected.
+      // @todo: Remove in Drupal 8, as it is deprecated by directly reading from
+      // $vocabulary->original.
+      $vocabulary->old_machine_name = $vocabulary->original->machine_name;
     }
-    // Make sure machine name changes are easily detected.
-    // @todo: Remove in Drupal 8, as it is deprecated by directly reading from
-    // $vocabulary->original.
-    $vocabulary->old_machine_name = $vocabulary->original->machine_name;
-  }
 
-  if (!isset($vocabulary->module)) {
-    $vocabulary->module = 'taxonomy';
-  }
+    if (!isset($vocabulary->module)) {
+      $vocabulary->module = 'taxonomy';
+    }
 
-  module_invoke_all('taxonomy_vocabulary_presave', $vocabulary);
+    module_invoke_all('taxonomy_vocabulary_presave', $vocabulary);
 
-  if (!empty($vocabulary->vid) && !empty($vocabulary->name)) {
-    $status = drupal_write_record('taxonomy_vocabulary', $vocabulary, 'vid');
-    if ($vocabulary->old_machine_name != $vocabulary->machine_name) {
-      field_attach_rename_bundle('taxonomy_term', $vocabulary->old_machine_name, $vocabulary->machine_name);
+    if (!empty($vocabulary->vid) && !empty($vocabulary->name)) {
+      $status = drupal_write_record('taxonomy_vocabulary', $vocabulary, 'vid');
+      if ($vocabulary->old_machine_name != $vocabulary->machine_name) {
+        field_attach_rename_bundle('taxonomy_term', $vocabulary->old_machine_name, $vocabulary->machine_name);
+      }
+      module_invoke_all('taxonomy_vocabulary_update', $vocabulary);
+      module_invoke_all('entity_update', $vocabulary, 'taxonomy_vocabulary');
+    }
+    elseif (empty($vocabulary->vid)) {
+      $status = drupal_write_record('taxonomy_vocabulary', $vocabulary);
+      field_attach_create_bundle('taxonomy_term', $vocabulary->machine_name);
+      module_invoke_all('taxonomy_vocabulary_insert', $vocabulary);
+      module_invoke_all('entity_insert', $vocabulary, 'taxonomy_vocabulary');
     }
-    module_invoke_all('taxonomy_vocabulary_update', $vocabulary);
-    module_invoke_all('entity_update', $vocabulary, 'taxonomy_vocabulary');
+
+    unset($vocabulary->original);
+    cache_clear_all();
+    entity_get_controller('taxonomy_vocabulary')->resetCache(array($vocabulary->vid));
   }
-  elseif (empty($vocabulary->vid)) {
-    $status = drupal_write_record('taxonomy_vocabulary', $vocabulary);
-    field_attach_create_bundle('taxonomy_term', $vocabulary->machine_name);
-    module_invoke_all('taxonomy_vocabulary_insert', $vocabulary);
-    module_invoke_all('entity_insert', $vocabulary, 'taxonomy_vocabulary');
+  catch (Exception $e) {
+    $transaction->rollback('taxonomy vocabulary');
+    watchdog_exception('taxonomy vocabulary', $e);
+    throw $e;
   }
 
-  unset($vocabulary->original);
-  cache_clear_all();
-  entity_get_controller('taxonomy_vocabulary')->resetCache(array($vocabulary->vid));
-
   return $status;
 }
 
@@ -540,72 +550,82 @@ function taxonomy_check_vocabulary_hierarchy($vocabulary, $changed_term) {
  *   Status constant indicating if term was inserted or updated.
  */
 function taxonomy_term_save($term) {
-  // Prevent leading and trailing spaces in term names.
-  $term->name = trim($term->name);
-  if (!isset($term->vocabulary_machine_name)) {
-    $vocabulary = taxonomy_vocabulary_load($term->vid);
-    $term->vocabulary_machine_name = $vocabulary->machine_name;
-  }
+  $transaction = db_transaction();
+  $status = FALSE;
 
-  // Load the stored entity, if any.
-  if (!empty($term->tid) && !isset($term->original)) {
-    $term->original = entity_load_unchanged('taxonomy_term', $term->tid);
-  }
+  try {
+    // Prevent leading and trailing spaces in term names.
+    $term->name = trim($term->name);
+    if (!isset($term->vocabulary_machine_name)) {
+      $vocabulary = taxonomy_vocabulary_load($term->vid);
+      $term->vocabulary_machine_name = $vocabulary->machine_name;
+    }
+
+    // Load the stored entity, if any.
+    if (!empty($term->tid) && !isset($term->original)) {
+      $term->original = entity_load_unchanged('taxonomy_term', $term->tid);
+    }
 
-  field_attach_presave('taxonomy_term', $term);
-  module_invoke_all('taxonomy_term_presave', $term);
+    field_attach_presave('taxonomy_term', $term);
+    module_invoke_all('taxonomy_term_presave', $term);
 
-  if (empty($term->tid)) {
-    $op = 'insert';
-    $status = drupal_write_record('taxonomy_term_data', $term);
-    field_attach_insert('taxonomy_term', $term);
-    if (!isset($term->parent)) {
-      $term->parent = array(0);
+    if (empty($term->tid)) {
+      $op = 'insert';
+      $status = drupal_write_record('taxonomy_term_data', $term);
+      field_attach_insert('taxonomy_term', $term);
+      if (!isset($term->parent)) {
+        $term->parent = array(0);
+      }
     }
-  }
-  else {
-    $op = 'update';
-    $status = drupal_write_record('taxonomy_term_data', $term, 'tid');
-    field_attach_update('taxonomy_term', $term);
-    if (isset($term->parent)) {
-      db_delete('taxonomy_term_hierarchy')
-        ->condition('tid', $term->tid)
-        ->execute();
+    else {
+      $op = 'update';
+      $status = drupal_write_record('taxonomy_term_data', $term, 'tid');
+      field_attach_update('taxonomy_term', $term);
+      if (isset($term->parent)) {
+        db_delete('taxonomy_term_hierarchy')
+          ->condition('tid', $term->tid)
+          ->execute();
+      }
     }
-  }
 
-  if (isset($term->parent)) {
-    if (!is_array($term->parent)) {
-      $term->parent = array($term->parent);
-    }
-    $query = db_insert('taxonomy_term_hierarchy')
-      ->fields(array('tid', 'parent'));
-    foreach ($term->parent as $parent) {
-      if (is_array($parent)) {
-        foreach ($parent as $tid) {
+    if (isset($term->parent)) {
+      if (!is_array($term->parent)) {
+        $term->parent = array($term->parent);
+      }
+      $query = db_insert('taxonomy_term_hierarchy')
+        ->fields(array('tid', 'parent'));
+      foreach ($term->parent as $parent) {
+        if (is_array($parent)) {
+          foreach ($parent as $tid) {
+            $query->values(array(
+              'tid' => $term->tid,
+              'parent' => $tid
+            ));
+          }
+        }
+        else {
           $query->values(array(
             'tid' => $term->tid,
-            'parent' => $tid
+            'parent' => $parent
           ));
         }
       }
-      else {
-        $query->values(array(
-          'tid' => $term->tid,
-          'parent' => $parent
-        ));
-      }
+      $query->execute();
     }
-    $query->execute();
-  }
 
-  // Reset the taxonomy term static variables.
-  taxonomy_terms_static_reset();
+    // Reset the taxonomy term static variables.
+    taxonomy_terms_static_reset();
 
-  // Invoke the taxonomy hooks.
-  module_invoke_all("taxonomy_term_$op", $term);
-  module_invoke_all("entity_$op", $term, 'taxonomy_term');
-  unset($term->original);
+    // Invoke the taxonomy hooks.
+    module_invoke_all("taxonomy_term_$op", $term);
+    module_invoke_all("entity_$op", $term, 'taxonomy_term');
+    unset($term->original);
+  }
+  catch (Exception $e) {
+    $transaction->rollback('taxonomy term');
+    watchdog_exception('taxonomy term', $e);
+    throw $e;
+  }
 
   return $status;
 }
diff --git modules/user/user.module modules/user/user.module
index 4a636da..76c5c25 100644
--- modules/user/user.module
+++ modules/user/user.module
@@ -2803,29 +2803,39 @@ function user_role_load_by_name($role_name) {
  *   performed.
  */
 function user_role_save($role) {
-  if ($role->name) {
-    // Prevent leading and trailing spaces in role names.
-    $role->name = trim($role->name);
-  }
-  if (!isset($role->weight)) {
-    // Set a role weight to make this new role last.
-    $query = db_select('role');
-    $query->addExpression('MAX(weight)');
-    $role->weight = $query->execute()->fetchField() + 1;
-  }
-  if (!empty($role->rid) && $role->name) {
-    $status = drupal_write_record('role', $role, 'rid');
-    module_invoke_all('user_role_update', $role);
+  $transaction = db_transaction();
+  $status = FALSE;
+
+  try {
+    if ($role->name) {
+      // Prevent leading and trailing spaces in role names.
+      $role->name = trim($role->name);
+    }
+    if (!isset($role->weight)) {
+      // Set a role weight to make this new role last.
+      $query = db_select('role');
+      $query->addExpression('MAX(weight)');
+      $role->weight = $query->execute()->fetchField() + 1;
+    }
+    if (!empty($role->rid) && $role->name) {
+      $status = drupal_write_record('role', $role, 'rid');
+      module_invoke_all('user_role_update', $role);
+    }
+    else {
+      $status = drupal_write_record('role', $role);
+      module_invoke_all('user_role_insert', $role);
+    }
+
+    // Clear the user access cache.
+    drupal_static_reset('user_access');
+    drupal_static_reset('user_role_permissions');
   }
-  else {
-    $status = drupal_write_record('role', $role);
-    module_invoke_all('user_role_insert', $role);
+  catch (Exception $e) {
+    $transaction->rollback('user role');
+    watchdog_exception('user role', $e);
+    throw $e;
   }
 
-  // Clear the user access cache.
-  drupal_static_reset('user_access');
-  drupal_static_reset('user_role_permissions');
-
   return $status;
 }
 
