diff --git a/mollom.install b/mollom.install
index 094c0ba..d4b48e1 100644
--- a/mollom.install
+++ b/mollom.install
@@ -118,14 +118,14 @@ function mollom_schema() {
         'not null' => TRUE,
         'default' => '',
       ),
-      'contentId' => array(
+      'content_id' => array(
         'description' => 'Content ID returned by Mollom.',
         'type' => 'varchar',
         'length' => 128,
         'not null' => TRUE,
         'default' => '',
       ),
-      'captchaId' => array(
+      'captcha_id' => array(
         'description' => 'CAPTCHA ID returned by Mollom.',
         'type' => 'varchar',
         'length' => 128,
@@ -156,13 +156,13 @@ function mollom_schema() {
       // would have an unintended meaning. Also, values are stored in individual
       // columns, so as to be able to join and filter/sort on these values for
       // improved content moderation.
-      'spamScore' => array(
+      'spam_score' => array(
         'description' => 'Text analysis spam check result.',
         'type' => 'float',
         'size' => 'tiny',
         'not null' => FALSE,
       ),
-      'spamClassification' => array(
+      'spam_classification' => array(
         'description' => 'Text analysis final spam classification result.',
         'type' => 'varchar',
         'length' => 16,
@@ -174,13 +174,13 @@ function mollom_schema() {
         'size' => 'tiny',
         'not null' => FALSE,
       ),
-      'qualityScore' => array(
+      'quality_score' => array(
         'description' => 'Text analysis quality check result.',
         'type' => 'float',
         'size' => 'tiny',
         'not null' => FALSE,
       ),
-      'profanityScore' => array(
+      'profanity_score' => array(
         'description' => 'Text analysis profanity check result.',
         'type' => 'float',
         'size' => 'tiny',
@@ -237,8 +237,8 @@ function mollom_schema() {
        ),
     ),
     'indexes' => array(
-      'contentId' => array('contentId'),
-      'captchaId' => array('captchaId'),
+      'content_id' => array('content_id'),
+      'captcha_id' => array('captcha_id'),
     ),
     'primary key' => array('entity', 'id'),
     'foreign keys' => array(
@@ -1070,3 +1070,61 @@ function mollom_update_6211() {
   variable_set('mollom_fai_dialog', variable_get('mollom_fai_dialog', 'mollom'));
   return array();
 }
+
+/**
+ * Change all mixedCase database columns and indexes to underscore separated.
+ */
+function mollom_udpate_6212() {
+  $ret = array();
+  db_drop_index($ret, 'mollom', 'contentId');
+  db_drop_index($ret, 'mollom', 'captchaId');
+  if (db_column_exists('mollom', 'contentId')) {
+    db_change_field($ret, 'mollom', 'contentId', 'content_id', array(
+      'description' => 'Content ID returned by Mollom.',
+      'type' => 'varchar',
+      'length' => 128,
+      'not null' => TRUE,
+      'default' => '',
+    ));
+  }
+  if (db_column_exists('mollom', 'captchaId')) {
+    db_change_field($ret, 'mollom', 'captchaId', 'captcha_id', array(
+      'description' => 'CAPTCHA ID returned by Mollom.',
+      'type' => 'varchar',
+      'length' => 128,
+    ));
+  }
+  if (db_column_exists('mollom', 'spamScore')) {
+    db_change_field($ret, 'mollom', 'spamScore', 'spam_score', array(
+      'description' => 'Text analysis spam check result.',
+      'type' => 'float',
+      'size' => 'tiny',
+      'not null' => FALSE,
+    ));
+  }
+  if (db_column_exists('mollom', 'spamClassification')) {
+    db_change_field($ret, 'mollom', 'spamClassification', 'spam_classification', array(
+      'description' => 'Test analysis final spam classification result.',
+      'type' => 'varchar',
+      'length' => 16,
+    ));
+  }
+  if (db_column_exists('mollom', 'qualityScore')) {
+    db_change_field($ret, 'mollom', 'qualityScore', 'quality_score', array(
+      'description' => 'Text analysis quality check result.',
+      'type' => 'float',
+      'size' => 'tiny',
+      'not null' => FALSE,
+    ));
+  }
+  if (db_column_exists('mollom', 'profanityScore')) {
+    db_change_field($ret, 'mollom', 'profanityScore', 'profanity_score', array(
+      'description' => 'Text analysis profanity check result.',
+      'type' => 'float',
+      'size' => 'tiny',
+      'not null' => FALSE,
+    ));
+  }
+  db_add_index($ret, 'mollom', 'content_id', array('content_id'));
+  db_add_index($ret, 'mollom', 'captcha_id', array('captcha_id'));
+}
diff --git a/mollom.module b/mollom.module
index 3a7d846..4bb374c 100644
--- a/mollom.module
+++ b/mollom.module
@@ -305,8 +305,8 @@ function _mollom_access($permission = FALSE) {
  * primarily used for mails, messages, and posts, which pertain to forms
  * protected by Mollom that do no result in stored entities after submission.
  * For example, Contact module's contact form. They can be reported by anyone
- * having the link. $id is expected to be either a {mollom}.contentId or
- * {mollom}.captchaId respectively.
+ * having the link. $id is expected to be either a {mollom}.content_id or
+ * {mollom}.captcha_id respectively.
  *
  * @see mollom_mail_add_report_link()
  *
@@ -378,13 +378,56 @@ function mollom_cron() {
 }
 
 /**
+ * Helper function to convert database column names to variable names.
+ *
+ * Database column names are separated by underscore, while some variable names
+ * are camelcased for backwards compatibility.
+ *
+ * @param stdClass $db_result
+ *   The database result object to convert.
+ * @param bool $reverse
+ *   True if the conversion should be run in reverse, from variable names to
+ *   database names.
+ * @return stdClass
+ *   The updated object with converted field names.
+ */
+function _mollom_convert_db_names($db_result, $reverse = FALSE) {
+  if (!is_object($db_result)) {
+    return $db_result;
+  }
+  $replace = array(
+    'content_id' => 'contentId',
+    'captcha_id' => 'captchaId',
+    'spam_score' => 'spamScore',
+    'spam_classification' => 'spamClassification',
+    'quality_score' => 'qualityScore',
+    'profanity_score' => 'profanityScore',
+  );
+  if ($reverse) {
+    $replace = array_flip($replace);
+  }
+  // Don't update the original data object but return a new converted one.
+  $clone = new stdClass();
+  foreach($db_result as $prop => $value) {
+    if (array_key_exists($prop, $replace)) {
+      $clone->{$replace[$prop]} = $value;
+    }
+    else {
+      $clone->{$prop} = $value;
+    }
+  }
+  return $clone;
+}
+
+/**
  * Load a Mollom data record by contentId.
  *
  * @param $contentId
  *   The contentId to retrieve data for.
  */
 function mollom_content_load($contentId) {
-  return db_fetch_object(db_query_range("SELECT * FROM {mollom} WHERE contentId = '%s'", array($contentId), 0, 1));
+  $data = db_fetch_object(db_query_range("SELECT * FROM {mollom} WHERE content_id = '%s'", array($contentId), 0, 1));
+  return _mollom_convert_db_names($data);
 }
 
 /**
@@ -396,7 +439,8 @@ function mollom_content_load($contentId) {
  *   The entity id to retrieve data for.
  */
 function mollom_data_load($entity, $id) {
-  return db_fetch_object(db_query_range("SELECT * FROM {mollom} WHERE entity = '%s' AND id = '%s'", array($entity, $id), 0, 1));
+  $data = db_fetch_object(db_query_range("SELECT * FROM {mollom} WHERE entity = '%s' AND id = '%s'", array($entity, $id), 0, 1));
+  return _mollom_convert_db_names($data);
 }
 
 /**
@@ -412,7 +456,7 @@ function mollom_entity_type_load($type) {
   $results = db_query("SELECT * FROM {mollom} WHERE entity = '%s'", array($type));
   $entities = array();
   while ($row = db_fetch_object($results)) {
-    $entities[$row->id] = $row;
+    $entities[$row->id] = _mollom_convert_db_names($row);
   }
   return $entities;
 }
@@ -462,9 +506,13 @@ function mollom_data_save($data) {
     $data->languages = implode(',', $languages);
   }
 
+  // Convert mixed case variable names to lower-case _ separated database names.
+  $converted = _mollom_convert_db_names($data, TRUE);
+
   $update = db_result(db_query_range("SELECT 'id' FROM {mollom} WHERE entity = '%s' AND id = '%s'", $data->entity, $data->id, 0, 1));
-  drupal_write_record('mollom', $data, $update ? array('entity', $update) : array());
+  drupal_write_record('mollom', $converted, $update ? array('entity', $update) : array());
 
+  // Pass unconverted data to other modules for backwards compatibility.
   if (!$update) {
     module_invoke_all('mollom_data_insert', $data);
   }
@@ -3078,7 +3126,8 @@ function mollom_mail_add_report_link(array &$message, array $mollom) {
       $data = mollom_content_load($mollom['response']['content']['id']);
     }
     elseif (!empty($mollom['response']['captcha']['id'])) {
-      $data = db_fetch_object(db_query_range("SELECT * FROM {mollom} WHERE captchaId = '%s'", array($mollom['response']['captcha']['id']), 0, 1));
+      $db_data = db_fetch_object(db_query_range("SELECT * FROM {mollom} WHERE captcha_id = '%s'", array($mollom['response']['captcha']['id']), 0, 1));
+      $data = _mollom_convert_db_names($db_data);
     }
     if (!$data) {
       // @todo Mollom session data should have been saved earlier already;
