.. index:: balancing; operations
.. index:: balancing; configure

===============================
Manage Sharded Cluster Balancer
===============================

.. default-domain:: mongodb

.. contents:: On this page
   :local:
   :backlinks: none
   :depth: 1
   :class: singlecol

.. versionchanged:: 3.4

   The balancer process has moved from the :binary:`~bin.mongos` instances
   to the primary member of the config server replica set.

This page describes common administrative procedures related
to balancing. For an introduction to balancing, see
:ref:`sharding-balancing`. For lower level information on balancing, see
:ref:`sharding-balancing-internals`.

.. important::

   Use the version of the :binary:`~bin.mongo` shell that corresponds to
   the version of the sharded cluster. For example, do not use a 3.2 or
   earlier version of :binary:`~bin.mongo` shell against the 3.4 sharded
   cluster.

Check the Balancer State
------------------------

:method:`sh.getBalancerState()` checks if the balancer is enabled (i.e. that the
balancer is permitted to run). :method:`sh.getBalancerState()` does not check if the balancer
is actively balancing chunks.

To see if the balancer is enabled in your :term:`sharded cluster`,
issue the following command, which returns a boolean:

.. code-block:: javascript

   sh.getBalancerState()

You can also see if the balancer is enabled using :method:`sh.status()`.
The :data:`~sh.status.balancer.currently-enabled` field indicates
whether the balancer is enabled, while the
:data:`~sh.status.balancer.currently-running` field indicates if the
balancer is currently running.

.. _sharding-balancing-is-running:

Check if Balancer is Running
----------------------------

To see if the balancer process is active in your :term:`cluster
<sharded cluster>`:

.. important::

   Use the version of the :binary:`~bin.mongo` shell that corresponds to
   the version of the sharded cluster. For example, do not use a 3.2 or
   earlier version of :binary:`~bin.mongo` shell against the 3.4 sharded
   cluster.

#. Connect to any :binary:`~bin.mongos` in the cluster using the
   :binary:`~bin.mongo` shell.

#. Use the following operation to determine if the balancer is running:

   .. code-block:: javascript

      sh.isBalancerRunning()

.. _sharded-cluster-config-default-chunk-size:

Configure Default Chunk Size
----------------------------

The default chunk size for a sharded cluster is 64 megabytes. In most
situations, the default size is appropriate for splitting and migrating
chunks. For information on how chunk size affects deployments, see
details, see :ref:`sharding-chunk-size`.

Changing the default chunk size affects chunks that are processes during
migrations and auto-splits but does not retroactively affect all chunks.

To configure default chunk size, see
:doc:`modify-chunk-size-in-sharded-cluster`.


.. _sharding-schedule-balancing-window:
.. _sharded-cluster-config-balancing-window:

Schedule the Balancing Window
-----------------------------

In some situations, particularly when your data set grows slowly and a
migration can impact performance, it is useful to ensure
that the balancer is active only at certain times. The following
procedure specifies the ``activeWindow``, 
which is the timeframe during which the :term:`balancer` will
be able to migrate chunks:

.. include:: /includes/steps/schedule-balancer-window.rst

.. _sharding-balancing-remove-window:

Remove a Balancing Window Schedule
----------------------------------

If you have :ref:`set the balancing window
<sharding-schedule-balancing-window>` and wish to remove the schedule
so that the balancer is always running, use :update:`$unset` to clear
the ``activeWindow``, as in the following:

.. code-block:: javascript

   use config
   db.settings.update({ _id : "balancer" }, { $unset : { activeWindow : true } })

.. _sharding-balancing-disable-temporally:
.. _sharding-balancing-disable-temporarily:

Disable the Balancer
--------------------

By default, the balancer may run at any time and only moves chunks as
needed. To disable the balancer for a short period of time and prevent
all migration, use the following procedure:

#. Connect to any :binary:`~bin.mongos` in the cluster using the
   :binary:`~bin.mongo` shell.

#. Issue the following operation to disable the balancer:

   .. code-block:: javascript

      sh.stopBalancer()

   If a migration is in progress, the system will complete the
   in-progress migration before stopping.
   
   .. include:: /includes/extracts/4.2-changes-stop-balancer-autosplit.rst

#. To verify that the balancer will not start, issue the following command,
   which returns ``false`` if the balancer is disabled:

   .. code-block:: javascript

      sh.getBalancerState()

   Optionally, to verify no migrations are in progress after disabling,
   issue the following operation in the :binary:`~bin.mongo` shell:

   .. code-block:: javascript

      use config
      while( sh.isBalancerRunning() ) {
                print("waiting...");
                sleep(1000);
      }

.. note::

   To disable the balancer from a driver,
   use the :command:`balancerStop` command against the ``admin`` database,
   as in the following:

   .. code-block:: javascript

      db.adminCommand( { balancerStop: 1 } )

.. _sharding-balancing-re-enable:
.. _sharding-balancing-enable:

Enable the Balancer
-------------------

Use this procedure if you have disabled the balancer and are ready to
re-enable it:

#. Connect to any :binary:`~bin.mongos` in the cluster using the
   :binary:`~bin.mongo` shell.

#. Issue one of the following operations to enable the balancer:

   From the :binary:`~bin.mongo` shell, issue:

   .. code-block:: javascript

      sh.startBalancer()

   .. note::

      To enable the balancer from a driver, use the :command:`balancerStart`
      command against the ``admin`` database, as in the following:

      .. code-block:: javascript

         db.adminCommand( { balancerStart: 1 } )

   .. include:: /includes/extracts/4.2-changes-start-balancer-autosplit.rst

Disable Balancing During Backups
--------------------------------

If MongoDB migrates a :term:`chunk` during a :doc:`backup
</core/backups>`, you can end with an inconsistent snapshot
of your :term:`sharded cluster`. Never run a backup while the balancer is
active. To ensure that the balancer is inactive during your backup
operation:

- Set the :ref:`balancing window <sharding-schedule-balancing-window>`
  so that the balancer is inactive during the backup. Ensure that the
  backup can complete while you have the balancer disabled.

- :ref:`manually disable the balancer <sharding-balancing-disable-temporarily>`
  for the duration of the backup procedure.

If you turn the balancer off while it is in the middle of a balancing round,
the shut down is not instantaneous. The balancer completes the chunk
move in-progress and then ceases all further balancing rounds.

Before starting a backup operation, confirm that the balancer is not
active. You can use the following command to determine if the balancer
is active:

.. code-block:: javascript

   !sh.getBalancerState() && !sh.isBalancerRunning()

When the backup procedure is complete you can reactivate
the balancer process.

Disable Balancing on a Collection
---------------------------------

You can disable balancing for a specific collection with the
:method:`sh.disableBalancing()` method. You may want to disable the
balancer for a specific collection to support maintenance operations or
atypical workloads, for example, during data ingestions or data exports.

When you disable balancing on a collection, MongoDB will not interrupt in
progress migrations.

To disable balancing on a collection, connect to a :binary:`~bin.mongos`
with the :binary:`~bin.mongo` shell and call the
:method:`sh.disableBalancing()` method.

For example:

.. code-block:: javascript

   sh.disableBalancing("students.grades")

The :method:`sh.disableBalancing()` method accepts as its parameter the
full :term:`namespace` of the collection.

Enable Balancing on a Collection
--------------------------------

You can enable balancing for a specific collection with the
:method:`sh.enableBalancing()` method.

When you enable balancing for a collection, MongoDB will not *immediately*
begin balancing data. However, if the data in your sharded collection is
not balanced, MongoDB will be able to begin distributing the data more
evenly.

To enable balancing on a collection, connect to a :binary:`~bin.mongos`
with the :binary:`~bin.mongo` shell and call the
:method:`sh.enableBalancing()` method.

For example:

.. code-block:: javascript

   sh.enableBalancing("students.grades")

The :method:`sh.enableBalancing()` method accepts as its parameter the
full :term:`namespace` of the collection.

Confirm Balancing is Enabled or Disabled
----------------------------------------

To confirm whether balancing for a collection is enabled or disabled,
query the ``collections`` collection in the ``config`` database for the
collection :term:`namespace` and check the ``noBalance`` field. For
example:

.. code-block:: javascript

   db.getSiblingDB("config").collections.findOne({_id : "students.grades"}).noBalance;

This operation will return a null error, ``true``, ``false``, or no output:

- A null error indicates the collection namespace is incorrect.

- If the result is ``true``, balancing is disabled.

- If the result is ``false``, balancing is enabled currently but has been
  disabled in the past for the collection. Balancing of this collection
  will begin the next time the balancer runs.

- If the operation returns no output, balancing is enabled currently and
  has never been disabled in the past for this collection. Balancing of
  this collection will begin the next time the balancer runs.

You can also see if the balancer is enabled using :method:`sh.status()`.
The :data:`~sh.status.balancer.currently-enabled` field indicates if the
balancer is enabled.

.. index:: balancing; secondary throttle
.. index:: secondary throttle

Change Replication Behavior for Chunk Migration
-----------------------------------------------

.. _sharded-cluster-config-secondary-throttle:

Secondary Throttle
~~~~~~~~~~~~~~~~~~

During chunk migration, the ``_secondaryThrottle`` value determines
when the migration proceeds with next document in the chunk.

In the :data:`config.settings` collection:


- If the ``_secondaryThrottle`` setting for the balancer is set to a
  write concern, each document move during chunk migration must receive
  the requested acknowledgement before proceeding with the next
  document.

- If the ``_secondaryThrottle`` setting for the balancer is set to
  ``true``, each document move during chunk migration must receive
  acknowledgement from at least one secondary before the migration
  proceeds with the next document in the chunk. This is equivalent to a
  write concern of :writeconcern:`{ w: 2 } <\<number\>>`.

- If the ``_secondaryThrottle`` setting is unset, the migration process
  does not wait for replication to a secondary and instead continues
  with the next document.
  
  Default behavior for :ref:`WiredTiger <storage-wiredtiger>` starting
  in MongoDB 3.4.

To change the ``_secondaryThrottle`` setting, connect to a
:binary:`~bin.mongos` instance and directly update the
``_secondaryThrottle`` value in the :data:`~config.settings` collection
of the :ref:`config database <config-database>`. For example, from a
:binary:`~bin.mongo` shell connected to a :binary:`~bin.mongos`, issue
the following command:

.. code-block:: javascript

   use config
   db.settings.update(
      { "_id" : "balancer" },
      { $set : { "_secondaryThrottle" : { "w": "majority" }  } },
      { upsert : true }
   )

The effects of changing the ``_secondaryThrottle`` setting may not be
immediate. To ensure an immediate effect, stop and restart the balancer
to enable the selected value of ``_secondaryThrottle``.

For more information on the replication behavior during various steps
of chunk migration, see :ref:`chunk-migration-replication`.

For the :dbcommand:`moveChunk` command, you can use the command's
``_secondaryThrottle`` and ``writeConcern`` options to specify the
behavior during the command. For details, see :dbcommand:`moveChunk`
command.

.. _wait-for-delete-setting:

Wait for Delete
~~~~~~~~~~~~~~~

The ``_waitForDelete`` setting of the balancer and the
:dbcommand:`moveChunk` command affects how the balancer migrates
multiple chunks from a shard. By default, the balancer does not wait
for the on-going migration's delete phase to complete before starting
the next chunk migration. To have the delete phase **block** the start
of the next chunk migration, you can set the ``_waitForDelete`` to
true.

For details on chunk migration, see :ref:`sharding-chunk-migration`.
For details on the chunk migration queuing behavior, see
:ref:`chunk-migration-queuing`.

The ``_waitForDelete`` is generally for internal testing purposes. To
change the balancer's ``_waitForDelete`` value:

#. Connect to a :binary:`~bin.mongos` instance.

#. Update the ``_waitForDelete`` value in the :data:`~config.settings`
   collection of the :ref:`config database <config-database>`. For
   example:

   .. code-block:: javascript

      use config
      db.settings.update(
         { "_id" : "balancer" },
         { $set : { "_waitForDelete" : true } },
         { upsert : true }
      )

Once set to ``true``, to revert to the default behavior:

#. Connect to a :binary:`~bin.mongos` instance.

#. Update or unset the ``_waitForDelete`` field in the
   :data:`~config.settings` collection of the :ref:`config database
   <config-database>`:

   .. code-block:: javascript

      use config
      db.settings.update(
         { "_id" : "balancer", "_waitForDelete": true },
         { $unset : { "_waitForDelete" : "" } }
      )

.. _balance-chunks-that-exceed-size-limit:

Balance Chunks that Exceed Size Limit
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

By default, MongoDB cannot move a chunk if the number of documents in
the chunk is greater than 1.3 times the result of dividing the
configured :ref:`chunk size<sharding-chunk-size>` by the average
document size.

Starting in MongoDB 4.4, by specifying the balancer setting
``attemptToBalanceJumboChunks`` to ``true``, the balancer can migrate
these large chunks as long as they have not been labeled as
:ref:`jumbo <jumbo-chunk>`. 

To set the balancer's ``attemptToBalanceJumboChunks`` setting, connect
to a :binary:`~bin.mongos` instance and directly update the
:data:`config.settings` collection. For example, from a
:binary:`~bin.mongo` shell connected to a :binary:`~bin.mongos`
instance, issue the following command:

.. code-block:: javascript

   db.getSiblingDB("config").settings.updateOne(
      { _id: "balancer" },
      { $set: { attemptToBalanceJumboChunks : true } },
      { upsert: true }
   )

When the balancer attempts to move the chunk, if the queue of writes
that modify any documents being migrated surpasses 500MB of memory the
migration will fail. For details on the migration procedure, see
:ref:`chunk-migration-procedure`.

If the chunk you want to move is labeled ``jumbo``, you can
:ref:`manually clear the jumbo flag <clear-jumbo-flag-manually>` to
have the balancer attempt to migrate the chunk.

Alternatively, you can use the :dbcommand:`moveChunk` command with
:ref:`forceJumbo: true <movechunk-forceJumbo>` to manually migrate
chunks that exceed the size limit (with or without the ``jumbo``
label). However, when you run :dbcommand:`moveChunk` with
:ref:`forceJumbo: true <movechunk-forceJumbo>`, write operations to the
collection may block for a long period of time during the migration.

.. _sharded-cluster-config-max-shard-size:

Change the Maximum Storage Size for a Given Shard
-------------------------------------------------

By default shards have no constraints in storage size. However, you can set a
maximum storage size for a given shard in the sharded cluster. When 
selecting potential destination shards, the balancer ignores shards 
where a migration would exceed the configured maximum storage size.

The :data:`~config.shards` collection in the :ref:`config
database<config-database>` stores configuration data related to shards. 

.. code-block:: javascript

   { "_id" : "shard0000", "host" : "shard1.example.com:27100" }
   { "_id" : "shard0001", "host" : "shard2.example.com:27200" }
   
To limit the storage size for a given shard, use the
:method:`db.collection.updateOne()` method with the :update:`$set` operator to
create the ``maxSize`` field and assign it an ``integer`` value. The
``maxSize`` field represents the maximum storage size for the shard in
``megabytes``.

The following operation sets a maximum size on a shard of ``1024 megabytes``:

.. code-block:: javascript

   config = db.getSiblingDB("config")
   config.shards.updateOne( { "_id" : "<shard>"}, { $set : { "maxSize" : 1024 } } )

This value includes the mapped size of *all* data files on the
shard, including the ``local`` and ``admin`` databases.

By default, ``maxSize`` is not specified, allowing shards to consume the
total amount of available space on their machines if necessary.

You can also set ``maxSize`` when adding a shard.

To set ``maxSize`` when adding a shard, set the :dbcommand:`addShard`
command's ``maxSize`` parameter to the maximum size in ``megabytes``. The
following command run in the :binary:`~bin.mongo` shell adds a shard with a
maximum size of 125 megabytes:

.. code-block:: javascript

   config = db.getSiblingDB("config")
   config.runCommand( { addshard : "example.net:34008", maxSize : 125 } )
