diff --git a/core/includes/database/mysql/database.inc b/core/includes/database/mysql/database.inc
index 7d5d85998dbd53bafcf5458458c5c18bc96f1dc7..a57f7dd022836e96347eb3d35c135a311e6e1c60 100644
--- a/core/includes/database/mysql/database.inc
+++ b/core/includes/database/mysql/database.inc
@@ -37,14 +37,20 @@ public function __construct(array $connection_options = array()) {
       $dsn = 'mysql:host=' . $connection_options['host'] . ';port=' . (empty($connection_options['port']) ? 3306 : $connection_options['port']);
     }
     $dsn .= ';dbname=' . $connection_options['database'];
-    parent::__construct($dsn, $connection_options['username'], $connection_options['password'], array(
+    // Allow PDO options to be overridden.
+    $connection_options += array(
+      'pdo' => array(),
+    );
+    $connection_options['pdo'] += array(
       // So we don't have to mess around with cursors and unbuffered queries by default.
       PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
       // Because MySQL's prepared statements skip the query cache, because it's dumb.
       PDO::ATTR_EMULATE_PREPARES => TRUE,
       // Force column names to lower case.
       PDO::ATTR_CASE => PDO::CASE_LOWER,
-    ));
+    );
+
+    parent::__construct($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
 
     // Force MySQL to use the UTF-8 character set. Also set the collation, if a
     // certain one has been set; otherwise, MySQL defaults to 'utf8_general_ci'
@@ -56,14 +62,22 @@ public function __construct(array $connection_options = array()) {
       $this->exec('SET NAMES utf8');
     }
 
-    // Force MySQL's behavior to conform more closely to SQL standards.
-    // This allows Drupal to run almost seamlessly on many different
-    // kinds of database systems. These settings force MySQL to behave
-    // the same as postgresql, or sqlite in regards to syntax interpretation
-    // and invalid data handling. See http://drupal.org/node/344575 for
-    // further discussion. Also, as MySQL 5.5 changed the meaning of
-    // TRADITIONAL we need to spell out the modes one by one.
-    $this->exec("SET sql_mode='ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER'");
+    // Set MySQL init_commands if not already defined.  Default Drupal's MySQL
+    // behavior to conform more closely to SQL standards.  This allows Drupal
+    // to run almost seamlessly on many different kinds of database systems.
+    // These settings force MySQL to behave the same as postgresql, or sqlite
+    // in regards to syntax interpretation and invalid data handling.  See
+    // http://drupal.org/node/344575 for further discussion. Also, as MySQL 5.5
+    // changed the meaning of TRADITIONAL we need to spell out the modes one by
+    // one.
+    $connection_options += array(
+      'init_commands' => array(),
+    );
+    $connection_options['init_commands'] += array(
+      'sql_mode' => "SET sql_mode = 'ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER'",
+    );
+    // Set connection options.
+    $this->exec(implode('; ', $connection_options['init_commands']));
   }
 
   public function queryRange($query, $from, $count, array $args = array(), array $options = array()) {
diff --git a/core/includes/database/pgsql/database.inc b/core/includes/database/pgsql/database.inc
index 39b4e9b6960c0476404c736bc4b45ea27424e938..d42a1cc3c63b454a31368c82c6418843a1212770 100644
--- a/core/includes/database/pgsql/database.inc
+++ b/core/includes/database/pgsql/database.inc
@@ -47,7 +47,12 @@ public function __construct(array $connection_options = array()) {
     $this->connectionOptions = $connection_options;
 
     $dsn = 'pgsql:host=' . $connection_options['host'] . ' dbname=' . $connection_options['database'] . ' port=' . $connection_options['port'];
-    parent::__construct($dsn, $connection_options['username'], $connection_options['password'], array(
+
+    // Allow PDO options to be overridden.
+    $connection_options += array(
+      'pdo' => array(),
+    );
+    $connection_options['pdo'] += array(
       // Prepared statements are most effective for performance when queries
       // are recycled (used several times). However, if they are not re-used,
       // prepared statements become ineffecient. Since most of Drupal's
@@ -59,10 +64,16 @@ public function __construct(array $connection_options = array()) {
       PDO::ATTR_STRINGIFY_FETCHES => TRUE,
       // Force column names to lower case.
       PDO::ATTR_CASE => PDO::CASE_LOWER,
-    ));
+    );
+    parent::__construct($dsn, $connection_options['username'], $connection_options['password'], $connection_options['pdo']);
 
     // Force PostgreSQL to use the UTF-8 character set by default.
     $this->exec("SET NAMES 'UTF8'");
+
+    // Execute PostgreSQL init_commands.
+    if (isset($connection_options['init_commands'])) {
+      $this->exec(implode('; ', $connection_options['init_commands']));
+    }
   }
 
   public function query($query, array $args = array(), $options = array()) {
diff --git a/core/includes/database/sqlite/database.inc b/core/includes/database/sqlite/database.inc
index 4cef16416736c4d8cca4b3164d2ce9348084d95a..98b35a260708c2cbf6c383c53a97d99a1df733a9 100644
--- a/core/includes/database/sqlite/database.inc
+++ b/core/includes/database/sqlite/database.inc
@@ -63,12 +63,17 @@ public function __construct(array $connection_options = array()) {
 
     $this->connectionOptions = $connection_options;
 
-    parent::__construct('sqlite:' . $connection_options['database'], '', '', array(
+    // Allow PDO options to be overridden.
+    $connection_options += array(
+      'pdo' => array(),
+    );
+    $connection_options['pdo'] += array(
       // Force column names to lower case.
       PDO::ATTR_CASE => PDO::CASE_LOWER,
       // Convert numeric values to strings when fetching.
       PDO::ATTR_STRINGIFY_FETCHES => TRUE,
-    ));
+    );
+    parent::__construct('sqlite:' . $connection_options['database'], '', '', $connection_options['pdo']);
 
     // Attach one database for each registered prefix.
     $prefixes = $this->prefixes;
@@ -103,6 +108,11 @@ public function __construct(array $connection_options = array()) {
     $this->sqliteCreateFunction('substring', array($this, 'sqlFunctionSubstring'), 3);
     $this->sqliteCreateFunction('substring_index', array($this, 'sqlFunctionSubstringIndex'), 3);
     $this->sqliteCreateFunction('rand', array($this, 'sqlFunctionRand'));
+
+    // Execute sqlite init_commands.
+    if (isset($connection_options['init_commands'])) {
+      $this->exec(implode('; ', $connection_options['init_commands']));
+    }
   }
 
   /**
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 330ebcc9671663ad0ee270b1f269e5e60d3692e0..360e556ffd49761b8d33c54d58707f32f609903f 100644
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -153,6 +153,29 @@
  * @endcode
  * NOTE: MySQL and SQLite's definition of a schema is a database.
  *
+ * Advanced users can add or override initial commands to execute when
+ * connecting to the database server, as well as PDO connection settings. For
+ * example, to enable MySQL SELECT queries to exceed the max_join_size system
+ * variable, and to reduce the database connection timeout to 5 seconds:
+ *
+ * @code
+ * $databases['default']['default'] = array(
+ *   'init_commands' => array(
+ *     'big_selects' => 'SET SQL_BIG_SELECTS=1',
+ *   ),
+ *   'pdo' => array(
+ *     PDO::ATTR_TIMEOUT => 5,
+ *   ),
+ * );
+ * @endcode
+ *
+ * WARNING: These defaults are designed for database portability. Changing them
+ * may cause unexpected behavior, including potential data loss.
+ *
+ * @see DatabaseConnection_mysql::__construct
+ * @see DatabaseConnection_pgsql::__construct
+ * @see DatabaseConnection_sqlite::__construct
+ *
  * Database configuration format:
  * @code
  *   $databases['default']['default'] = array(