diff --git a/db/Provision/Service/db/mysql.php b/db/Provision/Service/db/mysql.php
index d1d95fccf916ebea3bc0eec04c066eb07c025a1f..dfc5fe1d8381b97de0ea30f0bebb87decb2d95a2 100644
--- a/db/Provision/Service/db/mysql.php
+++ b/db/Provision/Service/db/mysql.php
@@ -124,8 +124,74 @@ class Provision_Service_db_mysql extends Provision_Service_db_pdo {
     // non-readable by the webserver.
     umask(0077);
     // Mixed copy-paste of drush_shell_exec and provision_shell_exec.
-    $cmd = sprintf("mysqldump --defaults-file=/dev/fd/3 --single-transaction --quick --no-autocommit %s | sed 's|/\\*!50001 CREATE ALGORITHM=UNDEFINED \\*/|/\\*!50001 CREATE \\*/|g; s|/\\*!50017 DEFINER=`[^`]*`@`[^`]*`\s*\\*/||g' | sed '/\\*!50013 DEFINER=.*/ d' > %s/database.sql", escapeshellcmd(drush_get_option('db_name')), escapeshellcmd(d()->site_path));
-    $success = $this->safe_shell_exec($cmd, drush_get_option('db_host'), urldecode(drush_get_option('db_user')), urldecode(drush_get_option('db_passwd')));
+    $cmd = sprintf("mysqldump --defaults-file=/dev/fd/3 --single-transaction --quick --no-autocommit %s", escapeshellcmd(drush_get_option('db_name')));
+
+    $db_host = drush_get_option('db_host');
+    $db_user = urldecode(drush_get_option('db_user'));
+    $db_passwd = urldecode(drush_get_option('db_passwd')));
+
+    // duplicate safe_shell_exec() because we want to replace the output
+    // inline
+    $mycnf = sprintf('[client]
+host=%s
+user=%s
+password="%s"
+port=%s
+', $db_host, $db_user, $db_passwd, $this->server->db_port);
+
+
+    // fail if db file already exists
+    $dumpfile = fopen(d()->site_path . '/database.sql', 'x');
+    if ($dump_file === FALSE) {
+      drush_set_error('PROVISION_BACKUP_FAILED', dt('Could not write database backup file mysqldump'));
+    }
+    else {
+      $process = proc_open($cmd, $descriptorspec, $pipes);
+      if (is_resource($process)) {
+        fwrite($pipes[3], $mycnf);
+        fclose($pipes[3]);
+
+        // okay, at this point we have opened a pipe to that mysqldump
+        // command, now we want to read it one line at a time and do our
+        // replacement
+        while (($buffer = fgets($pipes[1], 4096)) !== false) {
+          // remove DEFINER entries
+          // XXX: this should be anchored at ^
+          // original sed regex: /\\*!50013 DEFINER=.*/d
+          if (preg_match('#/\\*!50013 DEFINER=.*/#', $buffer)) {
+            continue;
+          }
+          // remove another kind of DEFINER line
+          // original sed regex: s|/\\*!50017 DEFINER=`[^`]*`@`[^`]*`\s*\\*/||g
+          // XXX: should also be anchored
+          // XXX: why the hell is there *another* DEFINER regex here?!
+          $buffer = preg_replace('#/\\*!50017 DEFINER=`[^`]*`@`[^`]*`\s*\\*/#', '', $buffer);
+          if (is_null($buffer)) {
+            // preg exploded in our face, oops.
+            drush_set_error('PROVISION_BACKUP_FAILED', dt('Error while running regular expression'));
+          }
+          // remove broken CREATE ALGORITHM entries
+          // original sed regex: s|/\\*!50001 CREATE ALGORITHM=UNDEFINED \\*/|/\\*!50001 CREATE \\*/|g
+          // XXX: should also be anchored
+          $buffer = preg_replace('#/\\*!50001 CREATE ALGORITHM=UNDEFINED \\*/#', '/\\*!50001 CREATE \\*/', $buffer);
+          // write the resulting line in the backup file
+          if (fwrite($dumpfile, $buffer) === FALSE) {
+            drush_set_error('PROVISION_BACKUP_FAILED', dt('Could not write database backup file mysqldump'));
+          }
+        }
+        // catch errors returned by mysqldump
+        fclose($pipes[1]);
+        // close stderr as well
+        $err = fread($pipes[2], 4096);
+        fclose($pipes[2]);
+        if (proc_close($process) != 0) {
+          drush_set_error('PROVISION_BACKUP_FAILED', dt('Could not write database backup file mysqldump (error: %msg)', array('%msg' => $err)));
+        }
+      }
+      else {
+        drush_set_error('PROVISION_BACKUP_FAILED', dt('Could not run mysqldump for backups'));
+      }
+    }
 
     $dump_size_too_small = filesize(d()->site_path . '/database.sql') < 1024;
     if ((!$success || $dump_size_too_small) && !drush_get_option('force', FALSE)) {