May
15
2023
--

MongoDB 4.2 EOL… And Its Implications

MongoDB 4.2 EOL

Enjoy it while it lasts, as everything has its end.

It sounded a bit more cryptic than it was planned, but I hope that it gets the attention it needs, as it’s important to know that MongoDB 4.2 in April has reached its End of Life (EOL), and more versions are soon going to be decommissioned as well.

What does that mean for me?

If you are a user of MongoDB 4.2, whether the MongoDB Inc. version or Percona Server for MongoDB one, your database will no longer receive bug fixes, patches, or minor releases.

As defined in our Lifecycle Policy:

We will provide Operational Support for customers running EOL software on active platforms. For EOLed platforms, we provide Community Support.

And as stated in our Lifecycle Overview:

For software that Percona bases on an upstream build, we match the upstream EOL dates.

Our MongoDB Server follows the upstream EOL dates. This means that bug fixes and software builds will no longer be generated also for our release of MongoDB.

Also, with the Percona Server for MongoDB 4.2 reaching its end of life, the implications are as follows:

  • Percona Distribution for MongoDB 4.2 will no longer receive updates and bug fixes
  • Percona Backup for MongoDB (PBM) will no longer support 4.2 either. That means that testing with 4.2 has ceased, and while PBM may still successfully perform backups and restores, we cannot guarantee it anymore.

That being said, rest assured, you will not be left alone. Those that have or would like to sign up for a Percona Support Subscription will continue to receive operational support and services. Operational support includes but is not limited to:

  • Query optimization
  • MongoDB tuning (replica sets and sharded clusters)
  • MongoDB configuration, including our enterprise features such as LDAP
  • Upgrade support (from EOL versions, so, i.e., 3.6->4.0->4.2->…)
  • Setup and configuration of MongoDB clusters and tools such as Percona Backup for MongoDB and Percona Monitoring and Management (respecting the tool limitation for the EOL-ed version).
  • In case of crashes, although we do not report bugs, we can still track down known bugs and provide recommendations.

Still have questions about the 4.2 EOL?

In her recent blog post, MongoDB V4.2 EOL Is Coming: How To Upgrade Now and Watch Out for the Gotchas!, our MongoDB Tech Lead, Kimberly Wilkins, has covered the ins and outs of a MongoDB upgrade.

She has also hosted a webinar on the MongoDB 4.2 EOL common questions and challenges.

If you are our customer, please create a ticket for more assistance. Remember also that our Percona Community Forum is always open for any users of our software, as we believe that community is very important in building our products!

What’s next

I do not want to be the bearer of bad news, but we have seen the great popularity of MongoDB 4.2 and 4.4. If you are on 4.2 right now, it makes all the difference to move away from it ASAP. This version has just become a possible threat to your security.

As you see, 4.4 was mentioned as well. That’s right, this highly popular, last version in the 4.x family is scheduled to be EOL in February 2024. That’s less than one year to make preparations for upgrading.

Mongo 4.2 EOL

MongoDB EOL for the upcoming year or so.

While at it, notice that 5.0 is planned to be EOL in October 2024 as well, so next year, it’s worth considering upgrading to 6.0 to have at least till 2025 for the next EOL.

MongoDB eol

MongoDB 6.0 still has two years of life now.

If such an upgrade seems challenging and you want some help or at least advice around it, consider some of our premium services from MongoDB experts that can help you with migration by:

  • Support – Answering any operational questions
  • Managed Services – Playing the role of the remote DBA that handles all maintenance (including upgrades) for you
  • Consulting – Professionals that can come in and advise or even do the upgrade for you at any time
  • Training – So that your team can feel more comfortable with running the upgrades

Percona Distribution for MongoDB is a freely available MongoDB database alternative, giving you a single solution that combines the best and most important enterprise components from the open source community, designed and tested to work together.

Download Percona Distribution for MongoDB Today!

Apr
28
2023
--

Add More Security to Your Percona Server for MongoDB With AWS IAM integration!

MongoDB With AWS IAM Integration

Did you notice that Percona Server for MongoDB 6.0.5-4 was released just a few days ago? This time around, it introduced improvements to the way we handle master key rotation for data at rest encryption as well as AWS IAM integration.

One key to rule them all — improvements to master key rotation

With the improvements introduced in Percona Server for MongoDB 6.0.5-4, one key path can be used for all servers in a clustered environment. This allows us to use one vault key namespace for all nodes in a deployment while at the same time preserving key versions and allowing each node to perform key rotation without impact to the other nodes.

Changes introduced with Percona Server for MongoDB 6.0.5-4 now allow using the same key for all the members of a replica set if the user chooses so, without impact on functionality.

Why should you care about AWS IAM integration?

With all the systems users need to access daily, password management becomes a more pressing issue. The introduction of IAM systems to an enterprise has become somewhat of a security standard in large enterprises.

Our users approached us about integration with AWS IAM, commonly used in their organizations. It’s an integration missing from MongoDB Community Edition (CE) that is important for compliance with enterprise security policies of many companies. Integration with AWS IAM allows:

MongoDB AWS IAM integration

To set up this integration, follow the steps outlined in our documentation, and configure either the user or the role authentication. This will allow AWS Security Token Service (STS) to play the part of Identity Provider (IDP) in a SAML 2.0-based federation.

Your feedback matters!

We take pride in being open to feedback in Percona. Please do not hesitate to contact us via the community forums or this contact form.

What’s next

We are looking into the problems affecting large size datastores that are a pain to our users. Please let us know if there are any particular issues you are struggling with in MongoDB; we are always open to suggestions!

Learn more about Percona Server for MongoDB

Apr
13
2023
--

MongoDB V4.2 EOL Is Coming: How To Upgrade Now and Watch Out for the Gotchas!

MongoDB upgrade

MongoDB v4.2 was released in August 2019. And like previous versions, there is a time to go — and that End of Life (EOL) date approaches.

MongoDB v4.2 EOL is set for April 30, 2023. Since Percona Server for MongoDB (PSMDB) is a fully compatible replacement for the upstream MongoDB Community Edition, we try to follow the same EOL date as the upstream vendor. So let’s discuss why you should upgrade MongoDB, what the upgrade process looks like, and some of the potential gotchas that you may run into along the way.

First, consider why you even need to upgrade MongoDB.

You may think that everything is fine, your application is humming along, you have had no major problems with this version, and you don’t really see a reason to upgrade.  And that’s exactly why you want to upgrade; you want to keep it that way. There are multiple very good reasons to upgrade MongoDB.

Those reasons include the following:

  • Security, stability, compliance
  • Bug fixes 
  • New features, enhancements
  • 3rd party application requirements, code changes

The two most important reasons to upgrade MongoDB are around security and bug fixes.

The goal is always to ensure that your PSMDB/MongoDB environment stays as stable, secure, and performant as possible. 

According to Percona’s Software Release Lifecycle Overview, after a version has gone EOL, no new builds or updates will be provided. We will continue to offer Operation Support on Supported Platforms.

Don’t leave your database vulnerable because this version has gone on to the database software wasteland. Plan and execute your upgrade ASAP.

With new versions come new features that may be beneficial to your application. And some just like shiny new things. Some of the major new features that are available in more recent versions of MongoDB are Time Series Collections and Live Resharding in v5.0

Between v4.2 and v6.0, there are multiple enhancements to take advantage of.

Those include more resilient chunk migrations and the ability to at least refine your shard keys in v4.4, the above-mentioned v5.0 new features, and many changes under the hood to support those major new features. Then with v6.0, you get sync improvements, mandatory use of the new mongosh shell, many enhancements and tweaks to all of the major changes that v5.0 brought about, and a new default chunk size of 128M to help handle some of the recent changes to the auto-splitter, chunk migration, and balancer processes.

But there are quite a few hops between v4.2 and v6.0. So let’s debunk some of the reasons that you may have for NOT upgrading.

Those main potential blockers could include:

  • Lack of resources or staff
  • Lack of time/can’t afford the downtime
  • Legacy code
  • Outdated drivers
  • Stack incompatibility

But really, the danger of not having support or bug fixes for your business-critical databases and applications is generally a very good reason to overcome all of those blockers sooner rather than later.

Let’s look at the steps required to upgrade MongoDB and the different types of environments that you may have running. 

The types of systems include:

  • Standalone
  • Replica Sets
  • Sharded Clusters

Those systems or architectures look like the below:

types of mongodb systems

Now look at the components that make up those systems.

mongodb architectural components

That gives us an idea of what we will need to upgrade.

But we also have to consider the built-in Replication that MongoDB has. That, too, will impact our upgrade process.

replication via replica sets

Basic overall MongoDB upgrade steps

  • Take a backup
  • Check prerequisites, resolve as needed
    • Add resources if needed
    • Download new desired binaries
    • Keep FCV (Feature Compatibility Value) set to Current/Previous version
    • Shut down mongo processes in the correct order; rolling fashion according to system type
    • Replace current binaries with new binaries
    • Start up mongo processes in the correct order; rolling fashion as required by system type
    • Wait for an amount of time to ensure no problems
  • Set FCV to the new desired version

The Pre-Req Checks generally look like this:

upgrade pre-reqs

Once those are done, begin the upgrade for the standalone system type.

Upgrade a standalone system

It’s a single host or node with one process, so do the following:

  • Take a backup
  • Shut down the mongod process
  • Replace the current binary with the new binary
  • Keep FCV at the previous version until everything checks out after the upgrade
  • Restart the mongodb process using the original port (default 27017)
  • Check version, data, logs, etc.
  • When all is good, update FCV

Now let’s look at the steps for the other two system types.

First, the Replica Set upgrade steps:

replica set upgrade mongodb

*Note* that there is a warning there.

You ALWAYS want to upgrade MongoDB to the latest version available – well, after checking the bug list, of course. We’ll review that warning when discussing the “Gotchas” later.

For Replica Set upgrades – upgrade binaries in a rolling manner. Start with the secondaries, then force the election of a new PRIMARY, and then upgrade the binary for the former PRIMARY.

Basic Replica Set upgrade steps

Upgrade Secondaries in a Rolling Method – SECONDARY 1, SECONDARY 2,  force election to new PRIMARY, upgrade old PRIMARY/new SECONDARY.

Step 1 – Upgrade SECONDARY 1 

 – Shutdown Secondary 1

 – Take Secondary 1 out of the replica set by restarting it with another port number (ex. port 3333)

 – Change Binaries to new version

 – Start Secondary 1 back up with its original replica set port number (ex. 27017)

Step 2 – Upgrade SECONDARY 2 – repeat that process with Secondary 2

Shutdown Secondary 2

 – Take Secondary 2 out of the replica set by restarting it with another port number (ex. port 3333)

 – Change Binaries to new version

 – Start Secondary 2 back up with its original replica set port number (ex. 27017)

Step 3 – Upgrade the current PRIMARY

Step Down the current Primary force election of a new PRIMARY – make sure state is good

Upgrade old PRIMARY, now new Secondary

Shut down old PRIMARY, now new Secondary 3

 – Take new Secondary 3 out of the replica set by restarting it with another port number (ex. port 3333)

 – Change Binaries to new version

 – Start new Secondary 3 backup with its original replica set port number (ex. 27017)

Wait, check the data and logs. If there are no problems, update FCV to the new version

Done.

Now move on to the Sharded Cluster Upgrade process, where there are more components to consider and upgrade.

Reminder – those components are:

mongodb Sharded Cluster Upgrade

*Note* When Upgrading a Sharded Cluster, the order in which you upgrade the components matters.

You have the additional components (the balancer, config server replica set, the main data bearing mongod shard nodes, and the query router process mongoS’s.) 

Order Matters … with this system type upgrade.

Stop Balancer

  • Upgrade Config Servers
  • Upgrade Shard nodes – MongoD’s
  • Upgrade the MongoS’s

Start Balancer

Below is an infogram to show that order when upgrading a sharded cluster:

upgrading a sharded cluster

Downgrades

If, for whatever reason, you run into any problem, you can perform a downgrade.

Downgrades basically go in reverse order – more applicable to sharded clusters.

Stop Balancer

  • Downgrade MongoS’s
  • Downgrade Shard Nodes – MongoD’s
  • Downgrade the Config Servers

ReStart Balancer

* This happens all in a rolling manner at the replset level again.

sharded cluster downgrade mongodb

That covers the basic steps.

I will do a more technical series of blogs in the coming months covering running MongoDB in Kubernetes and using the Percona Operator for MongoDB. Those blogs will contain commands, example results, etc., used when managing in that containerized environment. One of the planned blogs will cover upgrades to that environment.

For now, you can see the actual commands used when upgrading a Percona Server for MongoDB replica set or a sharded cluster in Sudhir’s blog. 

Now let’s take a look at some of the potential gotchas.

Gotchas — AKA things to watch out for

Whenever you are changing versions via an upgrade, there are different groups of things to watch out for or be aware of.

Those general buckets are:

  • Compatibility issues – whether programming language or driver related
  • Deprecated functions or tools
  • Behavior changes – ex TTL behavior changed significantly between v4.4 and v6
  • Bugs – newly discovered or already reported but not fixed yet

Below are some specific examples for those buckets.

Deprecated – Simple Network Management Protocol (SNMP) v6.0

Starting in MongoDB 6.0, SNMP is deprecated and will be removed in the next release.

Deprecated – old mongo shell “mongo” in v5.0

– Some legacy methods unavailable or replaced …

– mongosh uses the same syntax as old mongo shell

– Beware check your code

Behavior changes

v4.2 –Faster stepdowns 

Autosplitter process moved from mongos to the PRIMARY member of the replica set. This led to knowing more truth about chunk balance, so more chunk splits and more chunk migrations. Many more. It caused added write pressure.

v4.4 –Adjustments to the management of jumbo chunks – no longer getting stuck forever due to memory usage limit. Started adding in some of the changes that would be needed for v5.0 when Live Resharding would be hitting.

v5.0 – Deprecated old shell; major changes to the WiredTiger engine and Core Server to support Live ReSharding and Time Series Collections. It took a while for this major release to be fully baked. 😉 

v6.0 Default chunk size increased to 128M to help against too frequent chunk splitting and chunk moves by the Balancer. Removed the old shell. Changes to Initial sync and resync. New Operators; New Functions.

MongoDB version

Those are just some of the changes.

More about some of the negative impacts.

Things to watch out for – bugs!

Along with all of the major changes that went into v5.0, there were many bugs for quite a while. Making this even more impactful – the v5.0 changes were backported in v4.4.

So early on for v5.0.x, the same bugs also broke versions of 4.4 from 4.4.1 up through v4.4.8 but really up into v4.9 and v4.10 if you look at the JIRA tickets closely. 

Compatibility for Supported Life Cycle and OS Host Software – ex. MongoDB v5.0.x Community Edition drops support for RHEL/CentOS/Oracle 6 on x86_64 and other OS support changes

Here are some screenshots that I took along the way during the many releases for the version.

patch releases

Make sure to use the latest minor release version when upgrading MongoDB

For v4.4

These various bugs last pretty much ALL the way Through 4.4.8 – Serious bugs that cause checkpoint issues, possible data inconsistencies, missing documents/data loss, duplicate unique key, problems restarting, omitting a page or pages of data, unclean restarts, data loss, etc.

Examples: SERVER-61483  SERVER-61633   SERVER-61945  SERVER-61950 – problems restarting nodes     WT-8104   WT-8204 – race conditions, memory leaks. WT-8395 – upgrade related –data in an “inconsistent state”, missing documents      WT-8534    WT-8551 

Performance impact? There are also a few postings online talking about the newer versions possibly having a negative impact on performance.

There was a recently reported slowdown due to the new mongosh shell and a bug there, but seems to be with certain combinations and using a ruby driver …? Below are links for that issue and bug: 

Ok, enough of that. What should we do?

Upgrade of course!

Slow and Steady wins the race!

percona mongodb

percona server for mongodb versions

And what else?

Migrations!

Consider moving over to Percona Server for MongoDB

 

That migration — it’s really just a lift and shift.

Normally a binary change between PSMDB and MGDB CE will take care of it.  No need for data type changes, and no loss of triggers and procedures to deal with.

Remember, tick-tock … Plan your MongoDB upgrade and migrations today.

Thanks all!

Apr
12
2023
--

Is MongoDB Truly Open Source? A Critical Look at SSPL

MongoDB open sourceThis post was originally published in April 2023 and was updated in April 2025. When asked “Is MongoDB open source?”, at Percona, our definitive answer is “no.” Let’s start with this: MongoDB is accurately referred to as source-available software. Whereas many open source software offerings — like the community version of MySQL — use the […]

Apr
10
2023
--

Important Note for Users and Customers Using the Physical Backup Feature in Percona Backup for MongoDB

percona backup for mongodb

Percona Backup for MongoDB (PBM) is an open source, distributed, and low-impact solution for consistent backups of MongoDB sharded clusters and replica sets.

With PBM v2.0.0, the ability to take physical backups, in addition to logical ones, has been made Generally Available. Physical backups were added since v1.7.0 as a technical preview.

In March 2023, we discovered an issue with physical backups, which, under certain conditions, can cause the restore to fail (PBM-1058).

This article includes additional details about the following:

  • The conditions under which bug PBM-1058 is triggered.
  • The available workarounds.
  • How to permanently resolve the issue and our recommendations to affected users and customers.

Issue description

If you use PBM v2.0.4 or earlier, and your dbPath contains a trailing slash (for example dbPath is /var/lib/mongodb/), the backup process fails to correctly trim the dbPath from the file path.

As a result, when attempting to restore a backup taken in the above scenario, the restore process will fail as it will copy the files into the wrong location inside dbPath. For instance, “fileName” will be copied into dbPath/dbPath/fileName instead of dbPath/fileName, as in the following example:

  • dbPath:
    • /var/lib/mongodb/
  • fileName:
    • Index-19-2519978004532031907.wt
  • Location of fileName after the restore:
    • /var/lib/mongodb/var/lib/mongodb/index-19-2519978004532031907.wt
  • Expected location of fileName after the restore:
    • /var/lib/mongodb/index-19-2519978004532031907.wt

Am I affected?

You are affected by PBM-1058 if all conditions of one of the following two cases apply to you:

Case one

  • You are using PBM v2.0.4 or earlier.
  • You are taking physical backups.
  • Your mongod’s dbPath option has a trailing slash.
    • Example: your dbPath is path-to-some-directory/

Case two

  • You are using PBM v2.0.4 or earlier.
  • You are taking physical or incremental backups.
  • replsets[].files[].filename fields in the backup metadata start with a forward slash /.

Available workarounds

We have identified some workarounds that can be used with PBM v2.0.4 or earlier. The permanent solution to the issue described in this article is available with PBM v2.0.5 (see next section for more details).

If you are using PBM v2.0.4 or earlier and you are affected by PBM-1058, we recommend one of the following workarounds, depending on if you can restart your MongoDB and take a new backup or not.

Workaround one

If you can take a new backup, please follow these steps:

  1. Plan a short downtime window.
  2. Change your mongod dbpath (in any script you use to start MongoDB and in its configuration file /etc/mongo.conf) to remove any trailing slash.
  3. Restart your mongod.
  4. Take a new physical backup.

At this time, your new physical backup will not be affected by PBM-1058, and its restore will work normally.

Workaround two

If taking a new backup is not possible, and you are in the need of restoring an already taken backup that is affected by PBM-1058, please follow the following steps:

  1. In the backup meta on storage (<backup_name>.pbm.json) trim the “path-to-some-directory/” prefix in all “filename” fields.
  2. Move these files on the disk accordingly.
    • Example: Move “Timestamp/Shard_0/path-to-some-directory/fileName” to “Timestamp/Shard_0/fileName”
  3. Run the command pbm config –force-resync.
  4. Restore the backup.

Permanent issue resolution

The permanent fix for PBM-1058 has been merged via Pull Request #802.

PBM v2.0.5 includes this fix and was released on March 23, 2023. Packages can be downloaded from this link, and release notes are available here.

Starting with PBM v2.0.5, any newly taken backup will not be affected by PBM-1058, even if your dbPath contains a trailing slash.

Furthermore, starting with v2.0.5, during the restore process, PBM will identify if the backup (taken with PBM v2.0.4 or earlier) is affected by PBM-1058. If yes, it will attempt to auto-resolve the issue during the restore process (Pull Request #805).

The previously mentioned workaround two will still be useful in all other cases.

Recommendations

We recommend all PBM users and customers affected by PBM-1058 upgrade to PBM v2.0.5 or higher and take a new backup as soon as possible. This will avoid any possible issues in the future.

Additional questions

For any additional questions, Percona customers can open a new support ticket.

Community users can use the usual community support channels to request help.

Percona Distribution for MongoDB is a freely available MongoDB database alternative, giving you a single solution that combines the best and most important enterprise components from the open source community, designed and tested to work together.

 

Download Percona Distribution for MongoDB Today!

Apr
10
2023
--

Important Note for Users and Customers Using the Physical Backup Feature in Percona Backup for MongoDB

percona backup for mongodb

Percona Backup for MongoDB (PBM) is an open source, distributed, and low-impact solution for consistent backups of MongoDB sharded clusters and replica sets.

With PBM v2.0.0, the ability to take physical backups, in addition to logical ones, has been made Generally Available. Physical backups were added since v1.7.0 as a technical preview.

In March 2023, we discovered an issue with physical backups, which, under certain conditions, can cause the restore to fail (PBM-1058).

This article includes additional details about the following:

  • The conditions under which bug PBM-1058 is triggered.
  • The available workarounds.
  • How to permanently resolve the issue and our recommendations to affected users and customers.

Issue description

If you use PBM v2.0.4 or earlier, and your dbPath contains a trailing slash (for example dbPath is /var/lib/mongodb/), the backup process fails to correctly trim the dbPath from the file path.

As a result, when attempting to restore a backup taken in the above scenario, the restore process will fail as it will copy the files into the wrong location inside dbPath. For instance, “fileName” will be copied into dbPath/dbPath/fileName instead of dbPath/fileName, as in the following example:

  • dbPath:
    • /var/lib/mongodb/
  • fileName:
    • Index-19-2519978004532031907.wt
  • Location of fileName after the restore:
    • /var/lib/mongodb/var/lib/mongodb/index-19-2519978004532031907.wt
  • Expected location of fileName after the restore:
    • /var/lib/mongodb/index-19-2519978004532031907.wt

Am I affected?

You are affected by PBM-1058 if all conditions of one of the following two cases apply to you:

Case one

  • You are using PBM v2.0.4 or earlier.
  • You are taking physical backups.
  • Your mongod’s dbPath option has a trailing slash.
    • Example: your dbPath is path-to-some-directory/

Case two

  • You are using PBM v2.0.4 or earlier.
  • You are taking physical or incremental backups.
  • replsets[].files[].filename fields in the backup metadata start with a forward slash /.

Available workarounds

We have identified some workarounds that can be used with PBM v2.0.4 or earlier. The permanent solution to the issue described in this article is available with PBM v2.0.5 (see next section for more details).

If you are using PBM v2.0.4 or earlier and you are affected by PBM-1058, we recommend one of the following workarounds, depending on if you can restart your MongoDB and take a new backup or not.

Workaround one

If you can take a new backup, please follow these steps:

  1. Plan a short downtime window.
  2. Change your mongod dbpath (in any script you use to start MongoDB and in its configuration file /etc/mongo.conf) to remove any trailing slash.
  3. Restart your mongod.
  4. Take a new physical backup.

At this time, your new physical backup will not be affected by PBM-1058, and its restore will work normally.

Workaround two

If taking a new backup is not possible, and you are in the need of restoring an already taken backup that is affected by PBM-1058, please follow the following steps:

  1. In the backup meta on storage (<backup_name>.pbm.json) trim the “path-to-some-directory/” prefix in all “filename” fields.
  2. Move these files on the disk accordingly.
    • Example: Move “Timestamp/Shard_0/path-to-some-directory/fileName” to “Timestamp/Shard_0/fileName”
  3. Run the command pbm config –force-resync.
  4. Restore the backup.

Permanent issue resolution

The permanent fix for PBM-1058 has been merged via Pull Request #802.

PBM v2.0.5 includes this fix and was released on March 23, 2023. Packages can be downloaded from this link, and release notes are available here.

Starting with PBM v2.0.5, any newly taken backup will not be affected by PBM-1058, even if your dbPath contains a trailing slash.

Furthermore, starting with v2.0.5, during the restore process, PBM will identify if the backup (taken with PBM v2.0.4 or earlier) is affected by PBM-1058. If yes, it will attempt to auto-resolve the issue during the restore process (Pull Request #805).

The previously mentioned workaround two will still be useful in all other cases.

Recommendations

We recommend all PBM users and customers affected by PBM-1058 upgrade to PBM v2.0.5 or higher and take a new backup as soon as possible. This will avoid any possible issues in the future.

Additional questions

For any additional questions, Percona customers can open a new support ticket.

Community users can use the usual community support channels to request help.

Percona Distribution for MongoDB is a freely available MongoDB database alternative, giving you a single solution that combines the best and most important enterprise components from the open source community, designed and tested to work together.

 

Download Percona Distribution for MongoDB Today!

Mar
27
2023
--

How To Fix Oplog Restore Error: E11000 Duplicate Key Error Collection Using Percona Backup for MongoDB

error E11000 Percona Backup for MongoDB

E11000 duplicate key error’ is an error that you might have encountered during the restore process. In this blog, we will talk about in what scenario you might face this error when restoring Oplog for PITR (point-in-time recovery).

You might wonder why this error will come during PITR as the operations in the Oplog are idempotent, meaning they always result in the same change to the database no matter how many times they’re performed. Now let’s see in which scenario you might face this error while applying Oplog.

I created a collection book with four documents with a unique compound index. So as per the application logic, the document is first inserted, updated, and deleted, but when a new document is re-inserted, it is created with the same keys and values on which a unique index is created.

Index:

{
                "v" : 2,
                "unique" : true,
                "key" : {
                        "number" : 1,
                        "author" : 1
                },
                "name" : "number_1_author_1"
        }

Now your application logic is written in such a way that it is doing insert, update, delete, and again inserting the document with the same values in the number and author keys on which the unique index is created. Below we have already inserted four docs, and now, we will update one of the below documents.

  1. First insert:

    rs1:PRIMARY> db.book.find()
    { "_id" : ObjectId("641c11bfd0495f80ac5e610c"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610d"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610e"), "number" : 3, "title" : "2 states", "author" : "Peter" }
    { "_id" : ObjectId("641c11c1d0495f80ac5e610f"), "number" : 4, "title" : "a time to kill", "author" : "Graham" }
    rs1:PRIMARY> Date()
    Thu Mar 23 2023 08:45:55 GMT+0000 (UTC)
    rs1:PRIMARY>

    Corresponding ops in Oplog:

    rs1:PRIMARY> db.oplog.rs.find({ns:"london.book"})
    { "op" : "i", "ns" : "london.book", "ui" : UUID("9cb7ae0a-6974-4363-ae24-0de30f0cd915"), "o" : { "_id" : ObjectId("641c11bfd0495f80ac5e610c"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }, "ts" : Timestamp(1679561151, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T08:45:51.775Z") }
    { "op" : "i", "ns" : "london.book", "ui" : UUID("9cb7ae0a-6974-4363-ae24-0de30f0cd915"), "o" : { "_id" : ObjectId("641c11bfd0495f80ac5e610d"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }, "ts" : Timestamp(1679561151, 2), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T08:45:51.778Z") }
    { "op" : "i", "ns" : "london.book", "ui" : UUID("9cb7ae0a-6974-4363-ae24-0de30f0cd915"), "o" : { "_id" : ObjectId("641c11bfd0495f80ac5e610e"), "number" : 3, "title" : "2 states", "author" : "Peter" }, "ts" : Timestamp(1679561151, 3), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T08:45:51.781Z") }
    { "op" : "i", "ns" : "london.book", "ui" : UUID("9cb7ae0a-6974-4363-ae24-0de30f0cd915"), "o" : { "_id" : ObjectId("641c11c1d0495f80ac5e610f"), "number" : 4, "title" : "a time to kill", "author" : "Graham" }, "ts" : Timestamp(1679561153, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T08:45:53.302Z") }
    rs1:PRIMARY>
  2. After update:

    rs1:PRIMARY> db.book.update({"number":4},{$set: {title: "Minion"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    rs1:PRIMARY> Date()
    Thu Mar 23 2023 08:47:29 GMT+0000 (UTC)
    rs1:PRIMARY> db.book.find()
    { "_id" : ObjectId("641c11bfd0495f80ac5e610c"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610d"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610e"), "number" : 3, "title" : "2 states", "author" : "Peter" }
    { "_id" : ObjectId("641c11c1d0495f80ac5e610f"), "number" : 4, "title" : "Minion", "author" : "Graham" }
    rs1:PRIMARY>

    Corresponding op in Oplog:

    rs1:PRIMARY> db.oplog.rs.find({ns:"london.book"}).sort({$natural:-1}).limit(1)
    { "op" : "u", "ns" : "london.book", "ui" : UUID("9cb7ae0a-6974-4363-ae24-0de30f0cd915"), "o" : { "$v" : 1, "$set" : { "title" : "Minion" } }, "o2" : { "_id" : ObjectId("641c11c1d0495f80ac5e610f") }, "ts" : Timestamp(1679561243, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T08:47:23.448Z") }
    rs1:PRIMARY>
  3. After remove:

    rs1:PRIMARY> db.book.remove({number: 4})
    WriteResult({ "nRemoved" : 1 })
    rs1:PRIMARY> Date()
    Thu Mar 23 2023 08:48:37 GMT+0000 (UTC)
    rs1:PRIMARY> db.book.find()
    { "_id" : ObjectId("641c11bfd0495f80ac5e610c"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610d"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610e"), "number" : 3, "title" : "2 states", "author" : "Peter" }
    rs1:PRIMARY>

    Corresponding op in Oplog:

    rs1:PRIMARY> db.oplog.rs.find({ns:"london.book"}).sort({$natural:-1}).limit(1)
    { "op" : "d", "ns" : "london.book", "ui" : UUID("9cb7ae0a-6974-4363-ae24-0de30f0cd915"), "o" : { "_id" : ObjectId("641c11c1d0495f80ac5e610f") }, "ts" : Timestamp(1679561315, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T08:48:35.203Z") }
    rs1:PRIMARY>
  4. Below we will insert a new document:

    rs1:PRIMARY> db.book.insert({"number" : 4, "title" : "Stranger things", "author" : "Graham" })
    WriteResult({ "nInserted" : 1 })
    rs1:PRIMARY> Date()
    Thu Mar 23 2023 08:50:46 GMT+0000 (UTC)
    rs1:PRIMARY> db.book.find()
    { "_id" : ObjectId("641c11bfd0495f80ac5e610c"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610d"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610e"), "number" : 3, "title" : "2 states", "author" : "Peter" }
    { "_id" : ObjectId("641c12e4d0495f80ac5e6111"), "number" : 4, "title" : "Stranger things", "author" : "Graham" }
    rs1:PRIMARY>

    Corresponding op in Oplog:

    rs1:PRIMARY> db.oplog.rs.find({ns:"london.book"}).sort({$natural:-1}).limit(1)
    { "op" : "i", "ns" : "london.book", "ui" : UUID("9cb7ae0a-6974-4363-ae24-0de30f0cd915"), "o" : { "_id" : ObjectId("641c12e4d0495f80ac5e6111"), "number" : 4, "title" : "Stranger things", "author" : "Graham" }, "ts" : Timestamp(1679561444, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T08:50:44.861Z") }
    rs1:PRIMARY>
  5. Take mongodump of database london:

    # mongodump
    2023-03-23T08:52:01.032+0000    writing admin.system.version to dump/admin/system.version.bson
    2023-03-23T08:52:01.033+0000    done dumping admin.system.version (1 document)
    2023-03-23T08:52:01.033+0000    writing london.book to dump/london/book.bson
    2023-03-23T08:52:01.034+0000    done dumping london.book (4 documents)
    #
  6. We will again insert a new doc:

    rs1:PRIMARY> db.book.insert({"number" : 5, "title" : "Stranger things", "author" : "Graham" })
    WriteResult({ "nInserted" : 1 })
    rs1:PRIMARY> Date()
    Thu Mar 23 2023 08:52:37 GMT+0000 (UTC)
    rs1:PRIMARY> db.book.find()
    { "_id" : ObjectId("641c11bfd0495f80ac5e610c"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610d"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610e"), "number" : 3, "title" : "2 states", "author" : "Peter" }
    { "_id" : ObjectId("641c12e4d0495f80ac5e6111"), "number" : 4, "title" : "Stranger things", "author" : "Graham" }
    { "_id" : ObjectId("641c1352673573868f17cacf"), "number" : 5, "title" : "Stranger things", "author" : "Graham" }
    rs1:PRIMARY>

    Corresponding op in Oplog:

    rs1:PRIMARY> db.oplog.rs.find({ns:"london.book"}).sort({$natural:-1}).limit(1)
    { "op" : "i", "ns" : "london.book", "ui" : UUID("9cb7ae0a-6974-4363-ae24-0de30f0cd915"), "o" : { "_id" : ObjectId("641c1352673573868f17cacf"), "number" : 5, "title" : "Stranger things", "author" : "Graham" }, "ts" : Timestamp(1679561554, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T08:52:34.739Z") }
    rs1:PRIMARY>
  7. Take incremental Oplog backup.

    After first Oplog dump:

    # mongodump --db=local --collection=oplog.rs --query '{"ts":{"$gte":{"$timestamp": {"i":1, "t": 1679561120}}, "$lte":{"$timestamp": {"i":2, "t": 1679561151}}}}'
    2023-03-23T08:59:29.667+0000    writing local.oplog.rs to dump/local/oplog.rs.bson
    2023-03-23T08:59:29.668+0000    done dumping local.oplog.rs (7 documents)
    #
    # cd dump/local/
    # ls -ltrh
    total 8.0K
    -rw-r--r-- 1 root root  193 Mar 23 08:59 oplog.rs.metadata.json
    -rw-r--r-- 1 root root 1.1K Mar 23 08:59 oplog.rs.bson
    # mv oplog.rs.metadata.json oplog_1.rs.metadata.json
    # mv oplog.rs.bson oplog_1.rs.bson
    # ls -ltr
    total 8
    -rw-r--r-- 1 root root  193 Mar 23 08:59 oplog_1.rs.metadata.json
    -rw-r--r-- 1 root root 1.1K Mar 23 08:59 oplog_1.rs.bson
    #
    # bsondump oplog_1.rs.bson | tail -n 1
    
    2023-03-23T09:01:50.590+0000    7 objects found
    {"op":"i","ns":"london.book","ui":{"$binary":{"base64":"nLeuCml0Q2OuJA3jDwzZFQ==","subType":"04"}},"o":{"_id":{"$oid":"641c11bfd0495f80ac5e610d"},"number":{"$numberDouble":"2.0"},"title":"game of thrones","author":"chetan"},"ts":{"$timestamp":{"t":1679561151,"i":2}},"t":{"$numberLong":"1"},"v":{"$numberLong":"2"},"wall":{"$date":{"$numberLong":"1679561151778"}}}
    #

    Above is the last document of the first Oplog backup, i.e., till {“$timestamp”:{“t”:1679561151,”i”:2}}.

    After second Oplog dump (incremental):

    # mongodump --db=local --collection=oplog.rs --query '{"ts":{"$gt":{"$timestamp": {"i":2, "t": 1679561151}}, "$lte":{"$timestamp": {"i":1, "t": 1679562180}}}}'
    2023-03-23T09:03:27.070+0000    writing local.oplog.rs to dump/local/oplog.rs.bson
    2023-03-23T09:03:27.071+0000    done dumping local.oplog.rs (107 documents)
    #
    # ls -ltrh
    total 24K
    -rw-r--r-- 1 root root  193 Mar 23 08:59 oplog_1.rs.metadata.json
    -rw-r--r-- 1 root root 1.1K Mar 23 08:59 oplog_1.rs.bson
    -rw-r--r-- 1 root root  193 Mar 23 09:03 oplog.rs.metadata.json
    -rw-r--r-- 1 root root  12K Mar 23 09:03 oplog.rs.bson
    #
    # bsondump oplog.rs.bson | head -n 1
    2023-03-23T09:04:28.976+0000    107 objects found
    {"op":"i","ns":"london.book","ui":{"$binary":{"base64":"nLeuCml0Q2OuJA3jDwzZFQ==","subType":"04"}},"o":{"_id":{"$oid":"641c11bfd0495f80ac5e610e"},"number":{"$numberDouble":"3.0"},"title":"2 states","author":"Peter"},"ts":{"$timestamp":{"t":1679561151,"i":3}},"t":{"$numberLong":"1"},"v":{"$numberLong":"2"},"wall":{"$date":{"$numberLong":"1679561151781"}}}
    #

    Above is the starting document of the second/incremental Oplog backup i.e., $timestamp”:{“t”:1679561151,”i”:3}}

     

  8. Drop database:

    rs1:PRIMARY> db.dropDatabase()
    {
            "dropped" : "london",
            "ok" : 1,
            "$clusterTime" : {
                    "clusterTime" : Timestamp(1679562380, 2),
                    "signature" : {
                            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                            "keyId" : NumberLong(0)
                    }
            },
            "operationTime" : Timestamp(1679562380, 2)
    }
    rs1:PRIMARY> Date()
    Thu Mar 23 2023 09:06:37 GMT+0000 (UTC)
    rs1:PRIMARY>

    Corresponding op in Oplog:

    rs1:PRIMARY> db.oplog.rs.find({ns:"london.$cmd"}).sort({$natural:-1}).limit(1)
    { "op" : "c", "ns" : "london.$cmd", "o" : { "dropDatabase" : 1 }, "ts" : Timestamp(1679562380, 2), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T09:06:20.121Z") }
    rs1:PRIMARY>

  9. First, we will restore the database from the dump, which we took in step five:

    # mongorestore dump/london/book.bson
    2023-03-23T09:09:05.433+0000    checking for collection data in dump/london/book.bson
    2023-03-23T09:09:05.433+0000    reading metadata for london.book from dump/london/book.metadata.json
    2023-03-23T09:09:05.448+0000    restoring london.book from dump/london/book.bson
    2023-03-23T09:09:05.490+0000    finished restoring london.book (4 documents, 0 failures)
    2023-03-23T09:09:05.490+0000    restoring indexes for collection london.book from metadata
    2023-03-23T09:09:05.490+0000    index: &idx.IndexDocument{Options:primitive.M{"name":"number_1_author_1", "unique":true, "v":2}, Key:primitive.D{primitive.E{Key:"number", Value:1}, primitive.E{Key:"author", Value:1}}, PartialFilterExpression:primitive.D(nil)}
    2023-03-23T09:09:05.526+0000    4 document(s) restored successfully. 0 document(s) failed to restore.
    #

    The above-restored documents match until step five before taking the dump of london database:

    rs1:PRIMARY> db.book.find()
    { "_id" : ObjectId("641c11bfd0495f80ac5e610c"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610d"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }
    { "_id" : ObjectId("641c11bfd0495f80ac5e610e"), "number" : 3, "title" : "2 states", "author" : "Peter" }
    { "_id" : ObjectId("641c12e4d0495f80ac5e6111"), "number" : 4, "title" : "Stranger things", "author" : "Graham" }
    rs1:PRIMARY>

    Corresponding ops in Oplog after restore from dump:

    { "lsid" : { "id" : UUID("ce17fa90-9f06-4710-9b3b-3f4e9484e213"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }, "txnNumber" : NumberLong(1), "op" : "i", "ns" : "london.book", "ui" : UUID("9e30c316-b21a-4f43-bbcc-d80593001391"), "o" : { "_id" : ObjectId("641c12e4d0495f80ac5e6111"), "number" : 4, "title" : "Stranger things", "author" : "Graham" }, "ts" : Timestamp(1679562545, 5), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T09:09:05.451Z"), "stmtId" : 3, "prevOpTime" : { "ts" : Timestamp(1679562545, 4), "t" : NumberLong(1) } }
    
    { "lsid" : { "id" : UUID("ce17fa90-9f06-4710-9b3b-3f4e9484e213"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }, "txnNumber" : NumberLong(1), "op" : "i", "ns" : "london.book", "ui" : UUID("9e30c316-b21a-4f43-bbcc-d80593001391"), "o" : { "_id" : ObjectId("641c11bfd0495f80ac5e610e"), "number" : 3, "title" : "2 states", "author" : "Peter" }, "ts" : Timestamp(1679562545, 4), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T09:09:05.451Z"), "stmtId" : 2, "prevOpTime" : { "ts" : Timestamp(1679562545, 3), "t" : NumberLong(1) } }
    
    { "lsid" : { "id" : UUID("ce17fa90-9f06-4710-9b3b-3f4e9484e213"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }, "txnNumber" : NumberLong(1), "op" : "i", "ns" : "london.book", "ui" : UUID("9e30c316-b21a-4f43-bbcc-d80593001391"), "o" : { "_id" : ObjectId("641c11bfd0495f80ac5e610d"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }, "ts" : Timestamp(1679562545, 3), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T09:09:05.451Z"), "stmtId" : 1, "prevOpTime" : { "ts" : Timestamp(1679562545, 2), "t" : NumberLong(1) } }
    
    { "lsid" : { "id" : UUID("ce17fa90-9f06-4710-9b3b-3f4e9484e213"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }, "txnNumber" : NumberLong(1), "op" : "i", "ns" : "london.book", "ui" : UUID("9e30c316-b21a-4f43-bbcc-d80593001391"), "o" : { "_id" : ObjectId("641c11bfd0495f80ac5e610c"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }, "ts" : Timestamp(1679562545, 2), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T09:09:05.451Z"), "stmtId" : 0, "prevOpTime" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) } }

  10. Now we will check in Oplog backup to which document the data has been recovered and from which Oplog file we need to apply ops. We can see that documents in the first Oplog backup have been restored in step nine. To verify, below is the last ops entry in the first Oplog backup:
    # bsondump oplog_1.rs.bson | tail -n 1
    2023-03-23T09:11:40.539+0000    7 objects found
    {"op":"i","ns":"london.book","ui":{"$binary":{"base64":"nLeuCml0Q2OuJA3jDwzZFQ==","subType":"04"}},"o":{"_id":{"$oid":"641c11bfd0495f80ac5e610d"},"number":{"$numberDouble":"2.0"},"title":"game of thrones","author":"chetan"},"ts":{"$timestamp":{"t":1679561151,"i":2}},"t":{"$numberLong":"1"},"v":{"$numberLong":"2"},"wall":{"$date":{"$numberLong":"1679561151778"}}}
    #

    Now we need to replay the second Oplog backup just before the drop command ops (we already have the time of drop database command in step eight) for PITR (we can see below ops is already available, but we cannot split the BSON file based on the time or ops, so we need to apply full Oplog slice):

    # bsondump oplog.rs.bson | head -n 1
    2023-03-23T09:12:31.646+0000    107 objects found
    {"op":"i","ns":"london.book","ui":{"$binary":{"base64":"nLeuCml0Q2OuJA3jDwzZFQ==","subType":"04"}},"o":{"_id":{"$oid":"641c11bfd0495f80ac5e610e"},"number":{"$numberDouble":"3.0"},"title":"2 states","author":"Peter"},"ts":{"$timestamp":{"t":1679561151,"i":3}},"t":{"$numberLong":"1"},"v":{"$numberLong":"2"},"wall":{"$date":{"$numberLong":"1679561151781"}}}
    #
    #mongorestore --oplogFile=oplog.rs.bson --oplogReplay --oplogLimit 1679562370:1 /root/dump/local/
    2023-03-23T09:13:18.969+0000    preparing collections to restore from
    2023-03-23T09:13:18.969+0000    don't know what to do with file "/root/dump/local/oplog.rs.bson", skipping…
    2023-03-23T09:13:18.969+0000    don't know what to do with file "/root/dump/local/oplog.rs.metadata.json", skipping…
    2023-03-23T09:13:18.969+0000    don't know what to do with file "/root/dump/local/oplog_1.rs.bson", skipping…
    2023-03-23T09:13:18.969+0000    don't know what to do with file "/root/dump/local/oplog_1.rs.metadata.json", skipping…
    2023-03-23T09:13:18.969+0000    replaying oplog
    2023-03-23T09:13:18.978+0000    Failed: restore error: error applying oplog: applyOps: (DuplicateKey) E11000 duplicate key error collection: london.book index: number_1_author_1 dup key: { number: 4.0, author: "Graham" }
    2023-03-23T09:13:18.978+0000    0 document(s) restored successfully. 0 document(s) failed to restore.
    #

    We can see Oplog replay got failed due to a unique index constraint, as we can see the ops associated with { number: 4.0, author: “Graham” } is already present in the database:

    { "_id" : ObjectId("641c12e4d0495f80ac5e6111"), "number" : 4, "title" : "Stranger things", "author" : "Graham" }

    Below are the ops from the incremental Oplog backup slice associated with { number: 4.0, author: “Graham” }. So if you see the first ops below is an insert op with a different _id (“o”:{“_id”:{“$oid”:”641c11c1d0495f80ac5e610f“}) which was inserted in the beginning. When Oplog tries to replay the below op, it sees that there is already a document with a different _id  associated with { number: 4.0, author: “Graham” }, and it cannot apply this op due to a unique index violation. Thus failing to apply the Oplog and PITR.

    # bsondump oplog.rs.bson | grep Graham 
    {"op":"i","ns":"london.book","ui":{"$binary":{"base64":"nLeuCml0Q2OuJA3jDwzZFQ==","subType":"04"}},"o":{"_id":{"$oid":"641c11c1d0495f80ac5e610f"},"number":{"$numberDouble":"4.0"},"title":"a time to kill","author":"Graham"},"ts":{"$timestamp":{"t":1679561153,"i":1}},"t":{"$numberLong":"1"},"v":{"$numberLong":"2"},"wall":{"$date":{"$numberLong":"1679561153302"}}}
    {"op":"i","ns":"london.book","ui":{"$binary":{"base64":"nLeuCml0Q2OuJA3jDwzZFQ==","subType":"04"}},"o":{"_id":{"$oid":"641c12e4d0495f80ac5e6111"},"number":{"$numberDouble":"4.0"},"title":"Stranger things","author":"Graham"},"ts":{"$timestamp":{"t":1679561444,"i":1}},"t":{"$numberLong":"1"},"v":{"$numberLong":"2"},"wall":{"$date":{"$numberLong":"1679561444861"}}}
    {"op":"i","ns":"london.book","ui":{"$binary":{"base64":"nLeuCml0Q2OuJA3jDwzZFQ==","subType":"04"}},"o":{"_id":{"$oid":"641c1352673573868f17cacf"},"number":{"$numberDouble":"5.0"},"title":"Stranger things","author":"Graham"},"ts":{"$timestamp":{"t":1679561554,"i":1}},"t":{"$numberLong":"1"},"v":{"$numberLong":"2"},"wall":{"$date":{"$numberLong":"1679561554739"}}}
    2023-03-23T09:14:34.118+0000    107 objects found
    #

     

There are two solutions for the above issue:

    1. If the incremental Oplog backup is having only ops starting since the last op that is in the database backup.
    2. Have Percona Backup for MongoDB (PBM) configured and let PBM handle all the above manual processes (restoring dump + applying Oplog for PITR) automatically.

To overcome the above issue, I configured the PBM on the same replica set and took a backup (both full and incremental Oplog). Here’s how to install, set up, and configure PBM.

Below is the process I followed again from step one to step six for PBM, and below are the corresponding ops in Oplog:

rs1:PRIMARY> db.oplog.rs.find({ns:"london.book"})
{ "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c3b0a6eddc54ce4f75df8"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }, "ts" : Timestamp(1679571722, 2), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T11:42:02.988Z") }
{ "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c3b0a6eddc54ce4f75df9"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }, "ts" : Timestamp(1679571722, 3), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T11:42:02.990Z") }
{ "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c3b0a6eddc54ce4f75dfa"), "number" : 3, "title" : "2 states", "author" : "Peter" }, "ts" : Timestamp(1679571722, 4), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T11:42:02.992Z") }
{ "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c3b0b6eddc54ce4f75dfb"), "number" : 4, "title" : "a time to kill", "author" : "Graham" }, "ts" : Timestamp(1679571723, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T11:42:03.840Z") }
{ "op" : "u", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "$v" : 1, "$set" : { "title" : "Minion" } }, "o2" : { "_id" : ObjectId("641c3b0b6eddc54ce4f75dfb") }, "ts" : Timestamp(1679571914, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T11:45:14.026Z") }
{ "op" : "d", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c3b0b6eddc54ce4f75dfb") }, "ts" : Timestamp(1679573573, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T12:12:53.817Z") }
{ "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c42519662ff210d35343e"), "number" : 4, "title" : "Stranger things", "author" : "Graham" }, "ts" : Timestamp(1679573585, 3), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T12:13:05.567Z") }
{ "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c433b474b755a080f10bb"), "number" : 5, "title" : "Stranger things", "author" : "Graham" }, "ts" : Timestamp(1679573819, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T12:16:59.806Z") }

Below are the two full backups taken + incremental Oplog backup:

# pbm list
Backup snapshots:
  2023-03-23T11:52:05Z <logical> [restore_to_time: 2023-03-23T11:52:10Z]
  2023-03-23T12:14:04Z <logical> [restore_to_time: 2023-03-23T12:14:08Z]
PITR <off>:
  2023-03-23T11:52:11Z - 2023-03-23T13:06:45Z
#

Above, you can see the latest backup was taken till 2023-03-23T12:14:08, and incremental Oplog backup was taken till 2023-03-23T13:06:45.

Now we will drop the database:

rs1:PRIMARY> db.dropDatabase()
{
        "dropped" : "london",
        "ok" : 1,
        "$clusterTime" : {
                "clusterTime" : Timestamp(1679576445, 4),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        },
        "operationTime" : Timestamp(1679576445, 4)
}
rs1:PRIMARY> Date()
Thu Mar 23 2023 13:00:51 GMT+0000 (UTC)

Now we will restore the database and perform PITR using PBM:

# pbm restore --time="2023-03-23T13:00:44"

Below are the logs for restore + PITR:

# pbm logs --tail=100 | grep -i restore
2023-03-23T13:07:37Z I [rs1/127.0.0.1:27017] got command pitrestore [name: 2023-03-23T13:07:37.410117048Z, point-in-time ts: 1679576444] <ts: 1679576857>
2023-03-23T13:07:37Z I [rs1/127.0.0.1:27017] [pitrestore/2023-03-23T13:07:37.410117048Z] to time: 2023-03-23T13:00:44Z
2023-03-23T13:07:37Z I [rs1/127.0.0.1:27017] [pitrestore/2023-03-23T13:07:37.410117048Z] recovery started
2023-03-23T13:07:38Z I [rs1/127.0.0.1:27017] [pitrestore/2023-03-23T13:07:37.410117048Z] moving to state running
2023-03-23T13:07:41Z I [rs1/127.0.0.1:27017] [pitrestore/2023-03-23T13:07:37.410117048Z] restoring users and roles
2023-03-23T13:07:41Z I [rs1/127.0.0.1:27017] [pitrestore/2023-03-23T13:07:37.410117048Z] moving to state dumpDone
2023-03-23T13:07:43Z I [rs1/127.0.0.1:27017] [pitrestore/2023-03-23T13:07:37.410117048Z] starting oplog replay
2023-03-23T13:07:43Z I [rs1/127.0.0.1:27017] [pitrestore/2023-03-23T13:07:37.410117048Z] oplog replay finished on {1679576440 2}
2023-03-23T13:07:44Z I [rs1/127.0.0.1:27017] [pitrestore/2023-03-23T13:07:37.410117048Z] recovery successfully finished

Below are the documents after restore + PITR via PBM:

rs1:PRIMARY> db.book.find()
{ "_id" : ObjectId("641c3b0a6eddc54ce4f75df8"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }
{ "_id" : ObjectId("641c3b0a6eddc54ce4f75df9"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }
{ "_id" : ObjectId("641c3b0a6eddc54ce4f75dfa"), "number" : 3, "title" : "2 states", "author" : "Peter" }
{ "_id" : ObjectId("641c42519662ff210d35343e"), "number" : 4, "title" : "Stranger things", "author" : "Graham" }
{ "_id" : ObjectId("641c433b474b755a080f10bb"), "number" : 5, "title" : "Stranger things", "author" : "Graham"
rs1:PRIMARY>

Below are the Oplog entries after PBM restore, and we can see that PBM restored the relevant base backup first and started applying Oplog after the last op in the base backup.

rs1:PRIMARY> db.oplog.rs.find({ns:/^london/}).sort({$natural:-1})
{ "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c433b474b755a080f10bb"), "number" : 5, "title" : "Stranger things", "author" : "Graham" }, "ts" : Timestamp(1679576863, 9), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T13:07:43.222Z") }
{ "op" : "c", "ns" : "london.$cmd", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "commitIndexBuild" : "book", "indexBuildUUID" : UUID("c95a669a-9e62-4a59-974a-a702c52127da"), "indexes" : [ { "v" : 2, "unique" : true, "key" : { "number" : 1, "author" : 1 }, "name" : "number_1_author_1" } ] }, "ts" : Timestamp(1679576861, 8), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T13:07:41.159Z") }
{ "op" : "c", "ns" : "london.$cmd", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "startIndexBuild" : "book", "indexBuildUUID" : UUID("c95a669a-9e62-4a59-974a-a702c52127da"), "indexes" : [ { "v" : 2, "unique" : true, "key" : { "number" : 1, "author" : 1 }, "name" : "number_1_author_1" } ] }, "ts" : Timestamp(1679576861, 6), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T13:07:41.152Z") }
{ "lsid" : { "id" : UUID("6ec94b0c-098b-4986-a971-078c36761cf5"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }, "txnNumber" : NumberLong(3), "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c42519662ff210d35343e"), "number" : 4, "title" : "Stranger things", "author" : "Graham" }, "ts" : Timestamp(1679576861, 4), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T13:07:41.006Z"), "stmtId" : 3, "prevOpTime" : { "ts" : Timestamp(1679576861, 3), "t" : NumberLong(1) } }
{ "lsid" : { "id" : UUID("6ec94b0c-098b-4986-a971-078c36761cf5"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }, "txnNumber" : NumberLong(3), "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c3b0a6eddc54ce4f75dfa"), "number" : 3, "title" : "2 states", "author" : "Peter" }, "ts" : Timestamp(1679576861, 3), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T13:07:41.006Z"), "stmtId" : 2, "prevOpTime" : { "ts" : Timestamp(1679576861, 2), "t" : NumberLong(1) } }
{ "lsid" : { "id" : UUID("6ec94b0c-098b-4986-a971-078c36761cf5"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }, "txnNumber" : NumberLong(3), "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c3b0a6eddc54ce4f75df9"), "number" : 2, "title" : "game of thrones", "author" : "chetan" }, "ts" : Timestamp(1679576861, 2), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T13:07:41.006Z"), "stmtId" : 1, "prevOpTime" : { "ts" : Timestamp(1679576861, 1), "t" : NumberLong(1) } }
{ "lsid" : { "id" : UUID("6ec94b0c-098b-4986-a971-078c36761cf5"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }, "txnNumber" : NumberLong(3), "op" : "i", "ns" : "london.book", "ui" : UUID("5959bd53-6986-4d0d-a72a-9fac81113934"), "o" : { "_id" : ObjectId("641c3b0a6eddc54ce4f75df8"), "number" : 1, "title" : "harry potter", "author" : "shakespear" }, "ts" : Timestamp(1679576861, 1), "t" : NumberLong(1), "v" : NumberLong(2), "wall" : ISODate("2023-03-23T13:07:41.006Z"), "stmtId" : 0, "prevOpTime" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) } }


Above, you can see that PBM has applied the latest backup and performed the PITR automatically. The reason that we didn’t face the ‘
E11000 duplicate key error’ during PITR using PBM is that PBM handles it automatically, from which Oplog entry it needs to apply the ops after the restore from a full backup. PBM will ensure consistency while restoring a full backup + incremental Oplog backup.

Here’s how Percona Backup for MongoDB works.

Conclusion

So above, we can see how to avoid the ‘E11000 duplicate key error’ using PBM automatically. Another way is also possible, as explained above, but that will require a manual process. Why go with a manual process when PBM is open source, does not require any license, and can handle it automatically?

Please check out our products for Percona Server for MongoDB, Percona Backup for MongoDB, and Percona Operator for MongoDB. We also recommend checking out our blog MongoDB: Why Pay for Enterprise When Open Source Has You Covered?

Percona Distribution for MongoDB is a freely available MongoDB database alternative, giving you a single solution that combines the best and most important enterprise components from the open source community, designed and tested to work together.

 

Download Percona Distribution for MongoDB Today!

Feb
27
2023
--

Run Percona Server for MongoDB on Your ARM-based MacBooks and More

Percona Server for MongoDB on Your Arm-based MacBooks

The transition to Apple Silicon (the M1, M2 ARM-based CPUs) has been great for macOS fans in many ways, but it’s added some friction when you want to run containers locally for testing or development. The good news is we’ve got you covered with ARM64 container images for Percona Server for MongoDB 6.

While it’s possible to run x86_64 images on an ARM-based Mac, it’s not the most efficient or performant way to do so. Unfortunately, this has been the only way to do so until now.

With the release of Percona Server for MongoDB 6.0.4, we’ve added native Docker container images for ARM64. These run without needing Rosetta 2 translation or emulation on your ARM-based Macs.

Running the ARM64 MongoDB container image on your Mac

If you have Docker or Docker Desktop installed on your Mac, you can run Percona Server for MongoDB with a one-liner as described in our documentation:

$ docker run -d --name psmdb --restart always \
percona/percona-server-mongodb:6.0.4-3-arm64

Note that you’ll want to replace 6.0.4-3-arm64 with the appropriate image tag. You can check Docker Hub to find the current Arm64 version.

Prefer working with Podman? Just replace docker with podman:

$ podman run -d --name psmdb --restart always \
percona/percona-server-mongodb:6.0.4-3-arm64

If you’re using Podman Desktop, you can just drop into the terminal to start testing your container with mongosh:

Podman Desktop

Figure 1: Podman Desktop running ARM64 MongoDB containers

This gives you a quick way to access the MongoDB instance inside the container. Or you can connect by running mongosh externally and connecting to the MongoDB port exposed by the container. You’ll find more documentation on docs.percona.com, “Run Percona Server for MongoDB in a Docker container.”

Using `mongosh` inside the Percona arm64 container

Figure 2: Using mongosh inside the Percona ARM64 container

Please put Percona Server for MongoDB ARM container images through their paces! We’d love to know if you encounter any problems or if you have any tips to share!

Graviton and other ARM platforms

You should also be able to run the Percona Server for MongoDB ARM container images on AWS Graviton instances and other ARM64 platforms. We haven’t done extensive testing there, but we expect these images to work unmodified on Raspberry Pi. If you encounter any issues, please let us know in the forums or file a bug in Jira.

What’s next for ARM64 builds and Percona Server for MongoDB?

This is the first step we are taking to address the ARM support needs. We have started with Docker for Percona Server for MongoDB, but of course we plan to expand the rest of the software for MongoDB and packages.

We aim to incrementally provide full support for the ARM64 architecture for the full Percona Distribution for MongoDB. We are also looking into Arm needs for other Percona products!

Percona Server for MongoDB is a source-available, enterprise-grade drop-in replacement for MongoDB Community Edition.

Learn more about Percona Server for MongoDB

Feb
24
2023
--

Percona Server for MongoDB 6 Adds Support for Red Hat Enterprise Linux 9

Percona Server for MongoDB 6 Adds Support for Red Hat Enterprise Linux 9

We’re pleased to announce that Percona Server for MongoDB 6.0.4 adds support for Red Hat Enterprise Linux (RHEL) 9 and compatible Linux distributions.

With the 6.0.4 release you can now run Percona Server for MongoDB 6 on RHEL 7, 8, and 9, as well as Debian 10 and 11, and Ubuntu 18.04, 20.04, and 22.04 LTS.

We aim to support our software on the most widely used Linux distributions, coupled with support across several versions. As you’re planning your operating system and application strategies, we want to ensure that Percona software is available where you need it.

You can also, of course, run Percona Server for MongoDB in a Docker container as well. Have questions, comments, observations, or need help? Let’s chat in the Percona Forums!

Percona Server for MongoDB is a source-available, enterprise-grade drop-in replacement for MongoDB Community Edition.

Learn more about Percona Server for MongoDB

Nov
25
2022
--

Percona Operator for MongoDB Backup and Restore on S3-Compatible Storage – Backblaze

Percona Operator for MongoDB Backblaze

Percona Operator for MongoDB BackblazeOne of the main features that I like about the Percona Operator for MongoDB is the integration with Percona Backup for MongoDB (PBM) tool and the ability to backup/restore the database without manual intervention. The Operator allows backing up the DB to S3-compatible cloud storage and so you can use AWS, Azure, etc.

One of our customers asked about the integration between Backblaze and the Operator for backup and restore purposes. So I was checking for it and found that it is S3-compatible and provides a free account with 10GB of cloud storage. So I jumped into testing it with our Operator. Also, I saw in our forum that a few users are using Backblaze cloud storage. So making this blog post for everyone to utilize if they want to test/use Backblaze S3-compatible cloud storage for testing our Operator and PBM.

S3-compatible storage configuration

The Operator supports backup to S3-compatible storage. The steps for backup to AWS or Azure blob are given here. So you can try that as well. In this blog let me focus on B2 cloud storage configuring as the backup location and restore it to another deployment.

Let’s configure the Percona Server for MongoDB (PSMDB) Sharded Cluster using the Operator (with minimal config as explained here). I have used PSMDB operator v1.12.0 and PBM 1.8.1 for the test below. You can sign up for the free account here – https://www.backblaze.com/b2/cloud-storage-b.html. Then log in to your account. You can first create a key pair to access the storage from your operator as follows in the “App Keys” tab:

Add Application Key GUI

 

Then you can create a bucket with your desired name and note down the S3-compatible storage’s details like bucketname (shown in the picture below) and the endpointUrl to point here to send the backup files. The details of endpointUrl can be obtained from the provider and the region is specified in the prefix of the endpointURL variable.

Create Bucket

 

Deploy the cluster

Now let’s download the Operator from GitHub (I used v1.12.0) and configure the files for deploying the MongoDB sharded cluster. Here, I am using cr-minimal.yaml for deploying a very minimal setup of single member replicaset for a shard, config db, and a mongos.

#using an alias for the kubectl command
$ alias "k=kubectl"
$ cd percona-server-mongodb-operator

# Add a backup section in the cr file as shown below. Use the appropriate values from your setup
$ cat deploy/cr-minimal.yaml
apiVersion: psmdb.percona.com/v1-12-0
kind: PerconaServerMongoDB
metadata:
  name: minimal-cluster
spec:
  crVersion: 1.12.0
  image: percona/percona-server-mongodb:5.0.7-6
  allowUnsafeConfigurations: true
  upgradeOptions:
    apply: 5.0-recommended
    schedule: "0 2 * * *"
  secrets:
    users: minimal-cluster
  replsets:
  - name: rs0
    size: 1
    volumeSpec:
      persistentVolumeClaim:
        resources:
          requests:
            storage: 3Gi
  sharding:
    enabled: true
    configsvrReplSet:
      size: 1
      volumeSpec:
        persistentVolumeClaim:
          resources:
            requests:
              storage: 3Gi
    mongos:
      size: 1

  backup:
    enabled: true
    image: percona/percona-backup-mongodb:1.8.1
    serviceAccountName: percona-server-mongodb-operator
    pitr:
      enabled: false
      compressionType: gzip
      compressionLevel: 6
    storages:
      s3-us-west:
        type: s3
        s3:
          bucket: psmdbbackupBlaze
          credentialsSecret: my-cluster-name-backup-s3
          region: us-west-004
          endpointUrl: https://s3.us-west-004.backblazeb2.com/
#          prefix: ""
#          uploadPartSize: 10485760
#          maxUploadParts: 10000
#          storageClass: STANDARD
#          insecureSkipTLSVerify: false

 

The backup-s3.yaml contains the key details to access the B2 cloud storage. Encode the Key ID and Access Details (retrieved from Backblaze as mentioned here) as follows to use inside the backup-s3.yaml file. The key name: my-cluster-name-backup-s3 should be unique which is used to refer to the other yaml files:

# First use base64 to encode your keyid and access key:
$ echo "key-sample" | base64 --wrap=0
XXXX==
$ echo "access-key-sample" | base64 --wrap=0
XXXXYYZZ==

$ cat deploy/backup-s3.yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-cluster-name-backup-s3
type: Opaque
data:
 AWS_ACCESS_KEY_ID: XXXX==
 AWS_SECRET_ACCESS_KEY: XXXXYYZZ==

 

Then deploy the cluster as mentioned below and deploy backup-s3.yaml as well.

$ k apply -f ./deploy/bundle.yaml
customresourcedefinition.apiextensions.k8s.io/perconaservermongodbs.psmdb.percona.com created
customresourcedefinition.apiextensions.k8s.io/perconaservermongodbbackups.psmdb.percona.com created
customresourcedefinition.apiextensions.k8s.io/perconaservermongodbrestores.psmdb.percona.com created
role.rbac.authorization.k8s.io/percona-server-mongodb-operator created
serviceaccount/percona-server-mongodb-operator created
rolebinding.rbac.authorization.k8s.io/service-account-percona-server-mongodb-operator created
deployment.apps/percona-server-mongodb-operator created

$ k apply -f ./deploy/cr-minimal.yaml
perconaservermongodb.psmdb.percona.com/minimal-cluster created

$ k apply -f ./deploy/backup-s3.yaml 
secret/my-cluster-name-backup-s3 created

After starting the Operator and applying the yaml files, the setup looks like the below:

$ k get pods
NAME                                               READY   STATUS    RESTARTS   AGE
minimal-cluster-cfg-0                              2/2     Running   0          39m
minimal-cluster-mongos-0                           1/1     Running   0          70m
minimal-cluster-rs0-0                              2/2     Running   0          38m
percona-server-mongodb-operator-665cd69f9b-44tq5   1/1     Running   0          74m

$ k get svc
NAME                     TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)     AGE
kubernetes               ClusterIP   10.96.0.1     <none>        443/TCP     76m
minimal-cluster-cfg      ClusterIP   None          <none>        27017/TCP   72m
minimal-cluster-mongos   ClusterIP   10.100.7.70   <none>        27017/TCP   72m
minimal-cluster-rs0      ClusterIP   None          <none>        27017/TCP   72m

 

Backup

After deploying the cluster, the DB is ready for backup anytime. Other than the scheduled backup, you can create a backup-custom.yaml file to take a backup whenever you need it (you will need to provide a unique backup name each time, or else a new backup will not work). Our backup yaml file looks like the below one:

$ cat deploy/backup/backup-custom.yaml
apiVersion: psmdb.percona.com/v1
kind: PerconaServerMongoDBBackup
metadata:
  finalizers:
  - delete-backup
  name: backup1
spec:
  clusterName: minimal-cluster
  storageName: s3-us-west
#  compressionType: gzip
#  compressionLevel: 6

Now load some data into the database and then start the backup now:

$ k apply -f deploy/backup/backup-custom.yaml 
perconaservermongodbbackup.psmdb.percona.com/backup1 configured

The backup progress looks like the below:

$ k get perconaservermongodbbackup.psmdb.percona.com
NAME      CLUSTER           STORAGE      DESTINATION            STATUS      COMPLETED   AGE
backup1   minimal-cluster   s3-us-west   2022-09-08T03:21:58Z   requested               43s
$ k get perconaservermongodbbackup.psmdb.percona.com
NAME      CLUSTER           STORAGE      DESTINATION            STATUS      COMPLETED   AGE
backup1   minimal-cluster   s3-us-west   2022-09-08T03:22:19Z   requested               46s
$ k get perconaservermongodbbackup.psmdb.percona.com
NAME      CLUSTER           STORAGE      DESTINATION            STATUS    COMPLETED   AGE
backup1   minimal-cluster   s3-us-west   2022-09-08T03:22:19Z   running               49s

Here, if you have any issues with the backup, you can view the backup logs from the backup agent sidecar as follows:

$ k logs pod/minimal-cluster-rs0 -c backup-agent

To start another backup, edit backup-custom.yaml and change the backup name followed by applying it (using name:backup2):

$ k apply -f deploy/backup/backup-custom.yaml 
perconaservermongodbbackup.psmdb.percona.com/backup2 configured 

Monitor the backup process (you can use -w option to watch the progress continuously). It should show the status as READY:

$ k get perconaservermongodbbackup.psmdb.percona.com -w
NAME      CLUSTER           STORAGE      DESTINATION            STATUS   COMPLETED   AGE
backup1   minimal-cluster   s3-us-west   2022-09-08T03:22:19Z   ready    12m         14m
backup2   minimal-cluster   s3-us-west                                               8s
backup2   minimal-cluster   s3-us-west   2022-09-08T03:35:56Z   requested               21s
backup2   minimal-cluster   s3-us-west   2022-09-08T03:35:56Z   running                 26s
backup2   minimal-cluster   s3-us-west   2022-09-08T03:35:56Z   ready       0s          41s

From the bucket on Backblaze, the backup files are listed as they were sent from the backup:

Backup Files in B2 cloud Storage

 

Restore

You can restore the cluster from the backup into another similar deployment or into the same cluster. List the backups and restore one of them as follows. The configuration restore-custom.yaml has the backup information to restore. If you are using another deployment, then you can also include backupSource section which I commented on below for your reference, from which the restore process finds the source of the backup. In this case, make sure you create a secret my-cluster-name-backup-s3 before restoring as well to access the backup.

$ cat deploy/backup/restore-custom.yaml 
apiVersion: psmdb.percona.com/v1
kind: PerconaServerMongoDBRestore
metadata:
  name: restore2
spec:
  clusterName: minimal-cluster
  backupName: backup2
#  pitr:
#    type: date
#    date: YYYY-MM-DD HH:MM:SS
#  backupSource:
#    destination: s3://S3-BACKUP-BUCKET-NAME-HERE/BACKUP-DESTINATION
#    s3:
#      credentialsSecret: my-cluster-name-backup-s3
#      region: us-west-004
#      bucket: S3-BACKUP-BUCKET-NAME-HERE
#      endpointUrl: https://s3.us-west-004.backblazeb2.com/
#      prefix: ""
#    azure:
#      credentialsSecret: SECRET-NAME
#      prefix: PREFIX-NAME
#      container: CONTAINER-NAME

Listing the backup:

$ k get psmdb-backup
NAME      CLUSTER           STORAGE      DESTINATION            STATUS   COMPLETED   AGE
backup1   minimal-cluster   s3-us-west   2022-09-08T03:22:19Z   ready    3h5m        3h6m
backup2   minimal-cluster   s3-us-west   2022-09-08T03:35:56Z   ready    171m        172m
backup3   minimal-cluster   s3-us-west   2022-09-08T04:16:39Z   ready    130m        131m

 

To verify the restore process, I write some data into a collection vinodh.testData after the backup and before the restore. So the newly inserted document shouldn’t be there after the restore:

# Using mongosh from the mongo container to see the data
# Listing data from collection vinodh.testData
$ kubectl run -i --rm --tty mongo-client --image=mongo:5.0.7 --restart=Never -- bash -c "mongosh --host=10.96.30.92 --username=root --password=password --authenticationDatabase=admin --eval \"db.getSiblingDB('vinodh').testData.find()\" --quiet "
If you don't see a command prompt, try pressing enter.
[ { _id: ObjectId("631956cc70e60e9ed3ecf76d"), id: 1 } ]
pod "mongo-client" deleted

Inserting a document into it:

$ kubectl run -i --rm --tty mongo-client --image=mongo:5.0.7 --restart=Never -- bash -c "mongosh --host=10.96.30.92 --username=root --password=password --authenticationDatabase=admin --eval \"db.getSiblingDB('vinodh').testData.insert({id:2})\" --quiet "
If you don't see a command prompt, try pressing enter.
DeprecationWarning: Collection.insert() is deprecated. Use insertOne, insertMany, or bulkWrite.
{
  acknowledged: true,
  insertedIds: { '0': ObjectId("631980fe07180f860bd22534") }
}
pod "mongo-client" delete

Listing it again to verify:

$ kubectl run -i --rm --tty mongo-client --image=mongo:5.0.7 --restart=Never -- bash -c "mongosh --host=10.96.30.92 --username=root --password=password --authenticationDatabase=admin --eval \"db.getSiblingDB('vinodh').testData.find()\" --quiet "
If you don't see a command prompt, try pressing enter.
[
  { _id: ObjectId("631956cc70e60e9ed3ecf76d"), id: 1 },
  { _id: ObjectId("631980fe07180f860bd22534"), id: 2 }
]
pod "mongo-client" deleted

Running restore as follows:

$ k apply -f deploy/backup/restore-custom.yaml
perconaservermongodbrestore.psmdb.percona.com/restore2 created

Now check the data again in vinodh.testData collection and verify whether the restore is done properly. The below data proves that the collection was restored from the backup as it is listing only the record from the backup:

$ kubectl run -i --rm --tty mongo-client --image=mongo:5.0.7 --restart=Never -- bash -c "mongosh --host=minimal-cluster-mongos --username=root --password=password --authenticationDatabase=admin --eval \"db.getSiblingDB('vinodh').testData.find()\" --quiet "
If you don't see a command prompt, try pressing enter.
[ { _id: ObjectId("631956cc70e60e9ed3ecf76d"), id: 1 } ]

 

Hope this helps you! Now you can try the same from your end to check and use Backblaze in your production if it suits your requirements. I haven’t tested the performance of the network yet. If you have used Backblaze or similar S3-compatible storage for backup, then you can share your experience with us in the comments.

The Percona Kubernetes Operators automate the creation, alteration, or deletion of members in your Percona Distribution for MySQL, MongoDB, or PostgreSQL environment.

Learn More About Percona Kubernetes Operators

Powered by WordPress | Theme: Aeros 2.0 by TheBuckmaker.com