diff --git a/core/modules/dblog/dblog.admin.inc b/core/modules/dblog/dblog.admin.inc
index 2b08878..c75658e 100644
--- a/core/modules/dblog/dblog.admin.inc
+++ b/core/modules/dblog/dblog.admin.inc
@@ -21,7 +21,7 @@
 function dblog_filters() {
   $filters = array();
 
-  foreach (_dblog_get_message_types() as $type) {
+  foreach (\Drupal::service('storage.dblog')->getTypes() as $type) {
     $types[$type] = t($type);
   }
 
diff --git a/core/modules/dblog/dblog.module b/core/modules/dblog/dblog.module
index 06fef10..d4eb15f 100644
--- a/core/modules/dblog/dblog.module
+++ b/core/modules/dblog/dblog.module
@@ -61,34 +61,20 @@ function dblog_cron() {
   // Cleanup the watchdog table.
   $row_limit = \Drupal::config('dblog.settings')->get('row_limit');
 
-  // For row limit n, get the wid of the nth row in descending wid order.
-  // Counting the most recent n rows avoids issues with wid number sequences,
-  // e.g. auto_increment value > 1 or rows deleted directly from the table.
-  if ($row_limit > 0) {
-    $min_row = db_select('watchdog', 'w')
-      ->fields('w', array('wid'))
-      ->orderBy('wid', 'DESC')
-      ->range($row_limit - 1, 1)
-      ->execute()->fetchField();
-
-    // Delete all table entries older than the nth row, if nth row was found.
-    if ($min_row) {
-      db_delete('watchdog')
-        ->condition('wid', $min_row, '<')
-        ->execute();
-    }
-  }
+  \Drupal::service('storage.dblog')->deleteOldItems($row_limit);
 }
 
 /**
  * Gathers a list of uniquely defined database log message types.
  *
+ * @deprecated in Drupal 8.4.x and will be removed before 9.0.0. Use
+ *   \Drupal::service('storage.dblog')->getTypes() instead.
+ *
  * @return array
  *   List of uniquely defined database log message types.
  */
 function _dblog_get_message_types() {
-  return db_query('SELECT DISTINCT(type) FROM {watchdog} ORDER BY type')
-    ->fetchAllKeyed(0, 0);
+  return \Drupal::service('storage.dblog')->getTypes();
 }
 
 /**
diff --git a/core/modules/dblog/dblog.services.yml b/core/modules/dblog/dblog.services.yml
index 96ac2ee..7277bad 100644
--- a/core/modules/dblog/dblog.services.yml
+++ b/core/modules/dblog/dblog.services.yml
@@ -1,7 +1,12 @@
 services:
+  storage.dblog:
+    class: Drupal\dblog\Storage\DbLogStorage
+    arguments: ['@database']
+    tags:
+      - { name: backend_overridable }
   logger.dblog:
     class: Drupal\dblog\Logger\DbLog
-    arguments: ['@database', '@logger.log_message_parser']
+    arguments: ['@storage.dblog', '@logger.log_message_parser']
     tags:
       - { name: logger }
       - { name: backend_overridable }
diff --git a/core/modules/dblog/dblog.views.inc b/core/modules/dblog/dblog.views.inc
index dfc1fde..59b15ca 100644
--- a/core/modules/dblog/dblog.views.inc
+++ b/core/modules/dblog/dblog.views.inc
@@ -68,8 +68,7 @@ function dblog_views_data() {
       'id' => 'string',
     ),
     'filter' => array(
-      'id' => 'in_operator',
-      'options callback' => '_dblog_get_message_types',
+      'id' => 'dblog_types',
     ),
     'sort' => array(
       'id' => 'standard',
diff --git a/core/modules/dblog/src/Controller/DbLogController.php b/core/modules/dblog/src/Controller/DbLogController.php
index 36ee204..2b60908 100644
--- a/core/modules/dblog/src/Controller/DbLogController.php
+++ b/core/modules/dblog/src/Controller/DbLogController.php
@@ -6,12 +6,12 @@
 use Drupal\Component\Utility\Unicode;
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Controller\ControllerBase;
-use Drupal\Core\Database\Connection;
 use Drupal\Core\Datetime\DateFormatterInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormBuilderInterface;
 use Drupal\Core\Logger\RfcLogLevel;
 use Drupal\Core\Url;
+use Drupal\dblog\Storage\DbLogStorageInterface;
 use Drupal\user\Entity\User;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -21,13 +21,6 @@
 class DbLogController extends ControllerBase {
 
   /**
-   * The database service.
-   *
-   * @var \Drupal\Core\Database\Connection
-   */
-  protected $database;
-
-  /**
    * The module handler service.
    *
    * @var \Drupal\Core\Extension\ModuleHandlerInterface
@@ -56,35 +49,42 @@ class DbLogController extends ControllerBase {
   protected $userStorage;
 
   /**
+   * The dblog storage service.
+   *
+   * @var \Drupal\dblog\Logger\DbLogStorageInterface
+   */
+  protected $dblogStorage;
+
+  /**
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('database'),
       $container->get('module_handler'),
       $container->get('date.formatter'),
-      $container->get('form_builder')
+      $container->get('form_builder'),
+      $container->get('storage.dblog')
     );
   }
 
   /**
    * Constructs a DbLogController object.
    *
-   * @param \Drupal\Core\Database\Connection $database
-   *   A database connection.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   A module handler.
    * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
    *   The date formatter service.
    * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
    *   The form builder service.
+   * @param Drupal\dblog\Logger\DbLogInterface $dblog_storage
+   *   The dblogStorage service.
    */
-  public function __construct(Connection $database, ModuleHandlerInterface $module_handler, DateFormatterInterface $date_formatter, FormBuilderInterface $form_builder) {
-    $this->database = $database;
+  public function __construct(ModuleHandlerInterface $module_handler, DateFormatterInterface $date_formatter, FormBuilderInterface $form_builder, DbLogStorageInterface $dblog_storage) {
     $this->moduleHandler = $module_handler;
     $this->dateFormatter = $date_formatter;
     $this->formBuilder = $form_builder;
     $this->userStorage = $this->entityManager()->getStorage('user');
+    $this->dblogStorage = $dblog_storage;
   }
 
   /**
@@ -120,7 +120,6 @@ public static function getLogLevelClassMap() {
    */
   public function overview() {
 
-    $filter = $this->buildFilterQuery();
     $rows = array();
 
     $classes = static::getLogLevelClassMap();
@@ -151,28 +150,14 @@ public function overview() {
         'class' => array(RESPONSIVE_PRIORITY_LOW)),
     );
 
-    $query = $this->database->select('watchdog', 'w')
-      ->extend('\Drupal\Core\Database\Query\PagerSelectExtender')
-      ->extend('\Drupal\Core\Database\Query\TableSortExtender');
-    $query->fields('w', array(
-      'wid',
-      'uid',
-      'severity',
-      'type',
-      'timestamp',
-      'message',
-      'variables',
-      'link',
-    ));
-    $query->leftJoin('users_field_data', 'ufd', 'w.uid = ufd.uid');
-
-    if (!empty($filter['where'])) {
-      $query->where($filter['where'], $filter['args']);
-    }
-    $result = $query
-      ->limit(50)
-      ->orderByHeader($header)
-      ->execute();
+    $filter = $this->buildFilterQuery();
+    $sortingOptions = $header;
+
+    $result = $this->dblogStorage->loadMultiple(
+      $filter,
+      $sortingOptions,
+      50
+    );
 
     foreach ($result as $dblog) {
       $message = $this->formatMessage($dblog);
@@ -237,9 +222,10 @@ public function overview() {
    */
   public function eventDetails($event_id) {
     $build = array();
-    if ($dblog = $this->database->query('SELECT w.*, u.uid FROM {watchdog} w LEFT JOIN {users} u ON u.uid = w.uid WHERE w.wid = :id', array(':id' => $event_id))->fetchObject()) {
+    if ($dblog = $this->dblogStorage->load($event_id)) {
       $severity = RfcLogLevel::getLevels();
       $message = $this->formatMessage($dblog);
+
       $username = array(
         '#theme' => 'username',
         '#account' => $dblog->uid ? $this->userStorage->load($dblog->uid) : User::getAnonymousUser(),
@@ -303,7 +289,7 @@ public function eventDetails($event_id) {
    */
   protected function buildFilterQuery() {
     if (empty($_SESSION['dblog_overview_filter'])) {
-      return;
+      return [];
     }
 
     $this->moduleHandler->loadInclude('dblog', 'admin.inc');
@@ -378,33 +364,17 @@ public function formatMessage($row) {
    *   A build array in the format expected by drupal_render().
    */
   public function topLogMessages($type) {
+    $result = $this->dblogStorage->mostFrequentLogs($type);
+
     $header = array(
       array('data' => $this->t('Count'), 'field' => 'count', 'sort' => 'desc'),
       array('data' => $this->t('Message'), 'field' => 'message'),
     );
 
-    $count_query = $this->database->select('watchdog');
-    $count_query->addExpression('COUNT(DISTINCT(message))');
-    $count_query->condition('type', $type);
-
-    $query = $this->database->select('watchdog', 'w')
-      ->extend('\Drupal\Core\Database\Query\PagerSelectExtender')
-      ->extend('\Drupal\Core\Database\Query\TableSortExtender');
-    $query->addExpression('COUNT(wid)', 'count');
-    $query = $query
-      ->fields('w', array('message', 'variables'))
-      ->condition('w.type', $type)
-      ->groupBy('message')
-      ->groupBy('variables')
-      ->limit(30)
-      ->orderByHeader($header);
-    $query->setCountQuery($count_query);
-    $result = $query->execute();
-
     $rows = array();
-    foreach ($result as $dblog) {
-      if ($message = $this->formatMessage($dblog)) {
-        $rows[] = array($dblog->count, $message);
+    foreach ($result as $row) {
+      if ($message = $this->formatMessage($row['log'])) {
+        $rows[] = [$row['count'], $message];
       }
     }
 
diff --git a/core/modules/dblog/src/Form/DblogClearLogConfirmForm.php b/core/modules/dblog/src/Form/DblogClearLogConfirmForm.php
index b1710df..5192b29 100644
--- a/core/modules/dblog/src/Form/DblogClearLogConfirmForm.php
+++ b/core/modules/dblog/src/Form/DblogClearLogConfirmForm.php
@@ -2,10 +2,10 @@
 
 namespace Drupal\dblog\Form;
 
+use Drupal\Core\Form\ConfirmFormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
-use Drupal\Core\Database\Connection;
-use Drupal\Core\Form\ConfirmFormBase;
+use Drupal\dblog\Storage\DbLogStorageInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -14,20 +14,20 @@
 class DblogClearLogConfirmForm extends ConfirmFormBase {
 
   /**
-   * The database connection.
+   * The dblog storage service.
    *
-   * @var \Drupal\Core\Database\Connection
+   * @var \Drupal\dblog\Storage\DbLogStorageInterface
    */
-  protected $connection;
+  protected $dblogStorage;
 
   /**
    * Constructs a new DblogClearLogConfirmForm.
    *
-   * @param \Drupal\Core\Database\Connection $connection
-   *   The database connection.
+   * @param Drupal\dblog\Storage\DbLogStorageInterface $dblog_storage
+   *   The dblogStorage service.
    */
-  public function __construct(Connection $connection) {
-    $this->connection = $connection;
+  public function __construct(DbLogStorageInterface $dblog_storage) {
+    $this->dblogStorage = $dblog_storage;
   }
 
   /**
@@ -35,7 +35,7 @@ public function __construct(Connection $connection) {
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('database')
+      $container->get('storage.dblog')
     );
   }
 
@@ -65,7 +65,7 @@ public function getCancelUrl() {
    */
   public function submitForm(array &$form, FormStateInterface $form_state) {
     $_SESSION['dblog_overview_filter'] = array();
-    $this->connection->truncate('watchdog')->execute();
+    $this->dblogStorage->deleteAll();
     drupal_set_message($this->t('Database log cleared.'));
     $form_state->setRedirectUrl($this->getCancelUrl());
   }
diff --git a/core/modules/dblog/src/Logger/DbLog.php b/core/modules/dblog/src/Logger/DbLog.php
index af77be4..ea56c48 100644
--- a/core/modules/dblog/src/Logger/DbLog.php
+++ b/core/modules/dblog/src/Logger/DbLog.php
@@ -2,13 +2,11 @@
 
 namespace Drupal\dblog\Logger;
 
-use Drupal\Component\Utility\Unicode;
-use Drupal\Core\Database\Connection;
-use Drupal\Core\Database\Database;
-use Drupal\Core\Database\DatabaseException;
 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Drupal\Core\Logger\LogMessageParserInterface;
 use Drupal\Core\Logger\RfcLoggerTrait;
+use Drupal\dblog\Log;
+use Drupal\dblog\Storage\DbLogStorageInterface;
 use Psr\Log\LoggerInterface;
 
 /**
@@ -22,13 +20,13 @@ class DbLog implements LoggerInterface {
    * The dedicated database connection target to use for log entries.
    */
   const DEDICATED_DBLOG_CONNECTION_TARGET = 'dedicated_dblog';
-
+  
   /**
-   * The database connection object.
+   * The log storage system.
    *
-   * @var \Drupal\Core\Database\Connection
+   * @var \Drupal\dblog\Storage\DbLogStorageInterface
    */
-  protected $connection;
+  protected $storage;
 
   /**
    * The message's placeholders parser.
@@ -40,13 +38,13 @@ class DbLog implements LoggerInterface {
   /**
    * Constructs a DbLog object.
    *
-   * @param \Drupal\Core\Database\Connection $connection
-   *   The database connection object.
+   * @param \Drupal\dblog\Storage\DbLogStorageInterface $storage
+   *   The storage handler for logs.
    * @param \Drupal\Core\Logger\LogMessageParserInterface $parser
    *   The parser to use when extracting message variables.
    */
-  public function __construct(Connection $connection, LogMessageParserInterface $parser) {
-    $this->connection = $connection;
+  public function __construct(DbLogStorageInterface $storage, LogMessageParserInterface $parser) {
+    $this->storage = $storage;
     $this->parser = $parser;
   }
 
@@ -61,52 +59,28 @@ public function log($level, $message, array $context = array()) {
     // translated too in runtime.
     $message_placeholders = $this->parser->parseMessagePlaceholders($message, $context);
 
-    try {
-      $this->connection
-        ->insert('watchdog')
-        ->fields(array(
-          'uid' => $context['uid'],
-          'type' => Unicode::substr($context['channel'], 0, 64),
-          'message' => $message,
-          'variables' => serialize($message_placeholders),
-          'severity' => $level,
-          'link' => $context['link'],
-          'location' => $context['request_uri'],
-          'referer' => $context['referer'],
-          'hostname' => Unicode::substr($context['ip'], 0, 128),
-          'timestamp' => $context['timestamp'],
-        ))
-        ->execute();
-    }
-    catch (\Exception $e) {
-      // When running Drupal on MySQL or MariaDB you can run into several errors
-      // that corrupt the database connection. Some examples for these kind of
-      // errors on the database layer are "1100 - Table 'xyz' was not locked
-      // with LOCK TABLES" and "1153 - Got a packet bigger than
-      // 'max_allowed_packet' bytes". If such an error happens, the MySQL server
-      // invalidates the connection and answers all further requests in this
-      // connection with "2006 - MySQL server had gone away". In that case the
-      // insert statement above results in a database exception. To ensure that
-      // the causal error is written to the log we try once to open a dedicated
-      // connection and write again.
-      if (
-        // Only handle database related exceptions.
-        ($e instanceof DatabaseException || $e instanceof \PDOException) &&
-        // Avoid an endless loop of re-write attempts.
-        $this->connection->getTarget() != self::DEDICATED_DBLOG_CONNECTION_TARGET
-      ) {
-        // Open a dedicated connection for logging.
-        $key = $this->connection->getKey();
-        $info = Database::getConnectionInfo($key);
-        Database::addConnectionInfo($key, self::DEDICATED_DBLOG_CONNECTION_TARGET, $info['default']);
-        $this->connection = Database::getConnection(self::DEDICATED_DBLOG_CONNECTION_TARGET, $key);
-        // Now try once to log the error again.
-        $this->log($level, $message, $context);
-      }
-      else {
-        throw $e;
-      }
-    }
+    $log = new Log([
+      'uid' => $context['uid'],
+      'message' => $message,
+      'severity' => $level,
+      'type' => $context['channel'],
+      'variables' => serialize($message_placeholders),
+      'link' => $context['link'],
+      'location' => $context['request_uri'],
+      'referer' => $context['referer'],
+      'hostname' => $context['ip'],
+      'timestamp' => $context['timestamp'],
+    ]);
+
+    $this->storage->save($log);
+  }
+
+  /**
+   * Returns the storage handler for logs.
+   * @return \Drupal\dblog\Storage\DbLogStorageInterface
+   */
+  public function getStorage() {
+    return $this->storage;
   }
 
 }
diff --git a/core/modules/dblog/src/Plugin/rest/resource/DBLogResource.php b/core/modules/dblog/src/Plugin/rest/resource/DBLogResource.php
index 4ac76f0..82fba2d 100644
--- a/core/modules/dblog/src/Plugin/rest/resource/DBLogResource.php
+++ b/core/modules/dblog/src/Plugin/rest/resource/DBLogResource.php
@@ -38,10 +38,10 @@ class DBLogResource extends ResourceBase {
    */
   public function get($id = NULL) {
     if ($id) {
-      $record = db_query("SELECT * FROM {watchdog} WHERE wid = :wid", array(':wid' => $id))
-        ->fetchAssoc();
-      if (!empty($record)) {
-        return new ResourceResponse($record);
+      $log = \Drupal::service('storage.dblog')->load($id);
+
+      if (!empty($log)) {
+        return new ResourceResponse($log->toArray());
       }
 
       throw new NotFoundHttpException(t('Log entry with ID @id was not found', array('@id' => $id)));
