diff --git a/conf.py b/conf.py index ceaca920f5..75dce04dd0 100644 --- a/conf.py +++ b/conf.py @@ -62,12 +62,8 @@ '_build', 'archive/*', 'book/connectors/__*', - 'book/replication/*_1.rst', - 'book/replication/*_2.rst', - 'getting_started/using_package_manager.rst', - 'getting_started/using_docker.rst', - 'dev_guide/box_protocol.rst', - 'dev_guide/internals.rst', + 'how-to/using_package_manager.rst', + 'how-to/using_docker.rst', 'reference/configuration/cfg_*', 'images', 'book/cartridge/cartridge_overview.rst', diff --git a/doc/book/box/authentication.rst b/doc/book/admin/access_control.rst similarity index 98% rename from doc/book/box/authentication.rst rename to doc/book/admin/access_control.rst index f66ee03cfe..55a8cdc57b 100644 --- a/doc/book/box/authentication.rst +++ b/doc/book/admin/access_control.rst @@ -4,10 +4,8 @@ Access control ================================================================================ -Understanding security details is primarily an issue for administrators. -However, ordinary users should at least skim this section to get an idea -of how Tarantool makes it possible for administrators to prevent unauthorized -access to the database and to certain functions. +This section explains how Tarantool makes it possible for administrators +to prevent unauthorized access to the database and to certain functions. Briefly: diff --git a/doc/book/admin/index.rst b/doc/book/admin/index.rst index 7e38eb72da..c8bdf71af8 100644 --- a/doc/book/admin/index.rst +++ b/doc/book/admin/index.rst @@ -29,8 +29,12 @@ This chapter includes the following sections: instance_config start_stop_instance + modules logs security + access_control + vshard_admin + replication/index server_introspection daemon_supervision disaster_recovery diff --git a/doc/book/admin/modules.rst b/doc/book/admin/modules.rst new file mode 100644 index 0000000000..33ec77b713 --- /dev/null +++ b/doc/book/admin/modules.rst @@ -0,0 +1,213 @@ +.. _admin-managing_tarantool_modules: + +Managing modules +================ + +This section covers the installation and reloading of Tarantool modules. +To learn about writing your own module and contributing it, +check the :ref:`Contributing a module ` section. + +.. _app_server-installing_module: + +Installing a module +------------------- + +Modules in Lua and C that come from Tarantool developers and community +contributors are available in the following locations: + +* Tarantool modules repository (see :ref:`below `) +* Tarantool deb/rpm repositories (see :ref:`below `) + +.. _app_server-installing_module_luarocks: + +Installing a module from a repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See +`README in tarantool/rocks repository `_ +for detailed instructions. + +.. _app_server-installing_module_debrpm: + +Installing a module from deb/rpm +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Follow these steps: + +1. Install Tarantool as recommended on the + `download page `_. + +2. Install the module you need. Look up the module's name on + `Tarantool rocks page `_ and put the prefix + "tarantool-" before the module name to avoid ambiguity: + + .. code-block:: console + + $ # for Ubuntu/Debian: + $ sudo apt-get install tarantool- + + $ # for RHEL/CentOS/Amazon: + $ sudo yum install tarantool- + + For example, to install the module + `shard `_ on Ubuntu, say: + + .. code-block:: console + + $ sudo apt-get install tarantool-shard + +Once these steps are complete, you can: + +* load any module with + + .. code-block:: tarantoolsession + + tarantool> name = require('module-name') + + for example: + + .. code-block:: tarantoolsession + + tarantool> shard = require('shard') + +* search locally for installed modules using ``package.path`` (Lua) or + ``package.cpath`` (C): + + .. code-block:: tarantoolsession + + tarantool> package.path + --- + - ./?.lua;./?/init.lua; /usr/local/share/tarantool/?.lua;/usr/local/share/ + tarantool/?/init.lua;/usr/share/tarantool/?.lua;/usr/share/tarantool/?/ini + t.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/ + usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua; + ... + + tarantool> package.cpath + --- + - ./?.so;/usr/local/lib/x86_64-linux-gnu/tarantool/?.so;/usr/lib/x86_64-li + nux-gnu/tarantool/?.so;/usr/local/lib/tarantool/?.so;/usr/local/lib/x86_64 + -linux-gnu/lua/5.1/?.so;/usr/lib/x86_64-linux-gnu/lua/5.1/?.so;/usr/local/ + lib/lua/5.1/?.so; + ... + + .. NOTE:: + + Question-marks stand for the module name that was specified earlier when + saying ``require('module-name')``. + +.. _app_server-reloading_module: + +Reloading a module +------------------ + +You can reload any Tarantool application or module with zero downtime. + +.. _app_server-reloading_lua_module: + +Reloading a module in Lua +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here's an example that illustrates the most typical case -- "update and reload". + +.. NOTE:: + + In this example, we use recommended :ref:`administration practices ` + based on :ref:`instance files ` and + :ref:`tarantoolctl ` utility. + +1. Update the application file. + + For example, a module in ``/usr/share/tarantool/app.lua``: + + .. code-block:: lua + + local function start() + -- initial version + box.once("myapp:v1.0", function() + box.schema.space.create("somedata") + box.space.somedata:create_index("primary") + ... + end) + + -- migration code from 1.0 to 1.1 + box.once("myapp:v1.1", function() + box.space.somedata.index.primary:alter(...) + ... + end) + + -- migration code from 1.1 to 1.2 + box.once("myapp:v1.2", function() + box.space.somedata.index.primary:alter(...) + box.space.somedata:insert(...) + ... + end) + end + + -- start some background fibers if you need + + local function stop() + -- stop all background fibers and clean up resources + end + + local function api_for_call(xxx) + -- do some business + end + + return { + start = start, + stop = stop, + api_for_call = api_for_call + } + +2. Update the :ref:`instance file `. + + For example, ``/etc/tarantool/instances.enabled/my_app.lua``: + + .. code-block:: lua + + #!/usr/bin/env tarantool + -- + -- hot code reload example + -- + + box.cfg({listen = 3302}) + + -- ATTENTION: unload it all properly! + local app = package.loaded['app'] + if app ~= nil then + -- stop the old application version + app.stop() + -- unload the application + package.loaded['app'] = nil + -- unload all dependencies + package.loaded['somedep'] = nil + end + + -- load the application + log.info('require app') + app = require('app') + + -- start the application + app.start({some app options controlled by sysadmins}) + + The important thing here is to properly unload the application and its + dependencies. + +3. Manually reload the application file. + + For example, using ``tarantoolctl``: + + .. code-block:: console + + $ tarantoolctl eval my_app /etc/tarantool/instances.enabled/my_app.lua + +.. _app_server-reloading_c_module: + +Reloading a module in C +~~~~~~~~~~~~~~~~~~~~~~~ + +After you compiled a new version of a C module (``*.so`` shared library), call +:doc:`box.schema.func.reload('module-name') ` +from your Lua script to reload the module. + diff --git a/doc/book/admin/replication/index.rst b/doc/book/admin/replication/index.rst new file mode 100644 index 0000000000..f8a8a409fc --- /dev/null +++ b/doc/book/admin/replication/index.rst @@ -0,0 +1,10 @@ +Replication administration +========================== + +.. toctree:: + :maxdepth: 2 + + repl_monitoring + repl_recover + repl_reseed + repl_problem_solving diff --git a/doc/book/replication/mr-degraded.svg b/doc/book/admin/replication/mr-degraded.svg similarity index 100% rename from doc/book/replication/mr-degraded.svg rename to doc/book/admin/replication/mr-degraded.svg diff --git a/doc/book/replication/repl_monitoring.rst b/doc/book/admin/replication/repl_monitoring.rst similarity index 96% rename from doc/book/replication/repl_monitoring.rst rename to doc/book/admin/replication/repl_monitoring.rst index a5c37ce197..9170e3142a 100644 --- a/doc/book/replication/repl_monitoring.rst +++ b/doc/book/admin/replication/repl_monitoring.rst @@ -42,7 +42,7 @@ these instances, issue a :doc:`/reference/reference_lua/box_info/replication` re This report is for a master-master replica set of three instances, each having its own instance id, UUID and log sequence number. -.. image:: mm-3m-mesh.svg +.. image:: /concepts/replication/images/mm-3m-mesh.svg :align: center The request was issued at master #1, and the reply includes statistics for the @@ -78,6 +78,5 @@ The primary indicators of replication health are: For better understanding, see the following diagram illustrating the ``upstream`` and ``downstream`` connections within the replica set of three instances: -.. image:: replication.svg +.. image:: /concepts/replication/images/replication.svg :align: left - diff --git a/doc/book/replication/repl_problem_solving.rst b/doc/book/admin/replication/repl_problem_solving.rst similarity index 100% rename from doc/book/replication/repl_problem_solving.rst rename to doc/book/admin/replication/repl_problem_solving.rst diff --git a/doc/book/replication/repl_recover.rst b/doc/book/admin/replication/repl_recover.rst similarity index 100% rename from doc/book/replication/repl_recover.rst rename to doc/book/admin/replication/repl_recover.rst diff --git a/doc/book/replication/repl_reseed.rst b/doc/book/admin/replication/repl_reseed.rst similarity index 100% rename from doc/book/replication/repl_reseed.rst rename to doc/book/admin/replication/repl_reseed.rst diff --git a/doc/reference/reference_rock/vshard/vshard_admin.rst b/doc/book/admin/vshard_admin.rst similarity index 71% rename from doc/reference/reference_rock/vshard/vshard_admin.rst rename to doc/book/admin/vshard_admin.rst index debbb06065..da1e6cfc83 100644 --- a/doc/reference/reference_rock/vshard/vshard_admin.rst +++ b/doc/book/admin/vshard_admin.rst @@ -1,14 +1,15 @@ -.. _vshard-admin: +.. _vshard-admin: -=============================================================================== -Administration -=============================================================================== +Sharding with vshard +==================== -.. _vshard-install: +Sharding in Tarantool is implemented in the ``vshard`` module. +For a quick start with ``vshard``, refer to the :ref:`guide `. + +.. _vshard-install: -------------------------------------------------------------------------------- Installation -------------------------------------------------------------------------------- +------------ The ``vshard`` module is distributed separately from the main Tarantool package. To install the module, execute the following command: @@ -17,23 +18,22 @@ To install the module, execute the following command: $ tarantoolctl rocks install vshard -.. NOTE:: +.. note:: The ``vshard`` module requires Tarantool of the version 1.10.1 or higher, :ref:`Tarantool development package `, ``git``, ``cmake`` and ``gcc`` packages installed. -.. _vshard-config-cluster: +.. _vshard-config-cluster: -------------------------------------------------------------------------------- Configuration -------------------------------------------------------------------------------- +------------- Any viable sharded cluster consists of: -* one or more replica sets, each containing two or more - :ref:`storage ` instances, -* one or more :ref:`router ` instances. +* one or more replica sets, each containing two or more + :ref:`storage ` instances, +* one or more :ref:`router ` instances. The number of ``storage`` instances in a replica set defines the redundancy factor of the data. The recommended value is 3 or more. The number of ``router`` instances @@ -54,7 +54,7 @@ files. Self-identification is currently performed using ``tarantoolctl``: -.. code-block:: console +.. code-block:: console $ tarantoolctl instance_name @@ -72,11 +72,10 @@ a system and passing the sharding parameters. The configuration example of a simple sharded cluster is available :ref:`here `. -.. _vshard-replica-weights: +.. _vshard-replica-weights: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Replica weights -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~ The ``router`` sends all read-write requests to the master instance only. Setting replica weights allows sending read-only requests not only to the master instance, but to any @@ -96,7 +95,7 @@ weights in different zones for the same replica set. To set weights, use the zone attribute for each replica during configuration: -.. code-block:: kconfig +.. code-block:: kconfig local cfg = { sharding = { @@ -114,7 +113,7 @@ To set weights, use the zone attribute for each replica during configuration: Then, specify relative weights for each zone pair in the ``weights`` parameter of ``vshard.router.cfg``. For example: -.. code-block:: kconfig +.. code-block:: kconfig weights = { [1] = { @@ -139,11 +138,10 @@ Then, specify relative weights for each zone pair in the ``weights`` parameter o local cfg = vshard.router.cfg({weights = weights, sharding = ...}) -.. _vshard-replica-set-weights: +.. _vshard-replica-set-weights: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Replica set weights -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~ A replica set weight is not the same as the replica weight. The weight of a replica set defines the capacity of the replica set: the larger the weight, the more @@ -158,11 +156,10 @@ all weights of all replica sets are equal. You can use weights, for example, to store the prevailing amount of data on a replica set with more memory space. -.. _vshard-rebalancing: +.. _vshard-rebalancing: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Rebalancing process -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~ There is an **etalon number** of buckets for a replica set. (Etalon in this context means "ideal".) @@ -192,27 +189,26 @@ migration of its buckets to the remaining cluster nodes. It also allows adding a new zero-load replica set, which initiates migration of the buckets from the loaded replica sets to the zero-load replica set. -.. NOTE:: +.. note:: A new zero-load replica set should be assigned a weight for rebalancing to start. When a new shard is added, the configuration can be updated dynamically: -1. The configuration should be updated on all the ``routers`` first, and then on all - the ``storages``. -2. The new shard becomes available for rebalancing in the ``storage`` layer. -3. As a result of rebalancing, buckets are migrated to the new shard. -4. If a migrated bucket is requested, ``router`` receives an error code containing - information about the new location of the bucket. +1. The configuration should be updated on all the ``routers`` first, and then on all + the ``storages``. +2. The new shard becomes available for rebalancing in the ``storage`` layer. +3. As a result of rebalancing, buckets are migrated to the new shard. +4. If a migrated bucket is requested, ``router`` receives an error code containing + information about the new location of the bucket. At this time, the new shard is already present in the ``router``'s pool of connections, so redirection is transparent for the application. -.. _vshard-parallel-rebalancing: +.. _vshard-parallel-rebalancing: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Parallel rebalancing -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~ Originally, ``vshard`` had quite a simple ``rebalancer`` – one process on one node that calculated *routes* which should send buckets, how @@ -231,14 +227,14 @@ To set the degree of parallelism, a new option was added -- :ref:`rebalancer_max_sending `. You can specify it in a storage configuration in the root table: -.. code-block:: lua +.. code-block:: lua cfg.rebalancer_max_sending = 5 vshard.storage.cfg(cfg, box.info.uuid) In routers, this option is ignored. -.. NOTE:: +.. note:: Specifying ``cfg.rebalancer_max_sending = N`` probably won't give N times speed up. It depends on network, disk, number of other fibers in the system. @@ -279,11 +275,10 @@ then some buckets will try to get relocated – and will fail with that. This problem will consume network resources and time. It is important to configure these parameters to not conflict with each other. -.. _vshard-lock-pin: +.. _vshard-lock-pin: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Replica set lock and bucket pin -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A replica set lock makes a replica set invisible to the ``rebalancer``: a locked replica set can neither receive new buckets nor migrate its own buckets. @@ -312,14 +307,14 @@ cluster (assume all replica set weights are equal to 1). The initial configuration: -.. code-block:: none +.. code-block:: none rs1: bucket_count = 150 rs2: bucket_count = 150, pinned_count = 120 Adding a new replica set: -.. code-block:: none +.. code-block:: none rs1: bucket_count = 150 rs2: bucket_count = 150, pinned_count = 120 @@ -329,7 +324,7 @@ The perfect balance would be ``100 - 100 - 100``, which is impossible since the ``rs2`` replica set has 120 pinned buckets. The best possible balance here is the following: -.. code-block:: none +.. code-block:: none rs1: bucket_count = 90 rs2: bucket_count = 120, pinned_count 120 @@ -341,11 +336,10 @@ disbalance. At the same time it respected equal weights of ``rs1`` and ``rs3``. The algorithms for implementing locks and pins are completely different, although they look similar in terms of functionality. -.. _vshard-lock-and-rebalancing: +.. _vshard-lock-and-rebalancing: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Replica set lock and rebalancing -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Locked replica sets simply do not participate in rebalancing. This means that even if the actual total number of buckets is not equal to the etalon number, @@ -354,37 +348,36 @@ one of the replica sets is locked, it recalculates the etalon number of buckets of the non-locked replica sets as if the locked replica set and its buckets did not exist at all. -.. _vshard-pin-and-rebalancing: +.. _vshard-pin-and-rebalancing: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Bucket pin and rebalancing -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +^^^^^^^^^^^^^^^^^^^^^^^^^^ Rebalancing replica sets with pinned buckets requires a more complex algorithm. Here ``pinned_count[o]`` is the number of pinned buckets, and ``etalon_count`` is the etalon number of buckets for a replica set: -1. The ``rebalancer`` calculates the etalon number of buckets as if all buckets - were not pinned. Then the rebalancer checks each replica set and compares the - etalon number of buckets with the number of pinned buckets in a replica set. - If ``pinned_count < etalon_count``, non-locked replica sets (at this point all - locked replica sets already are filtered out) with pinned buckets can receive - new buckets. -2. If ``pinned_count > etalon_count``, the disbalance cannot be fixed, as the - ``rebalancer`` cannot move pinned buckets out of this replica set. In such a case - the etalon number is updated and set equal to the number of pinned buckets. - The replica sets with ``pinned_count > etalon_count`` are not processed by - the ``rebalancer``, and the number of pinned buckets is subtracted from the - total number of buckets. The rebalancer tries to move out as many buckets as - possible from such replica sets. -3. This procedure is restarted from step 1 for replica sets with - ``pinned_count >= etalon_count`` until ``pinned_count <= etalon_count`` on - all replica sets. The procedure is also restarted when the total number of - buckets is changed. +1. The ``rebalancer`` calculates the etalon number of buckets as if all buckets + were not pinned. Then the rebalancer checks each replica set and compares the + etalon number of buckets with the number of pinned buckets in a replica set. + If ``pinned_count < etalon_count``, non-locked replica sets (at this point all + locked replica sets already are filtered out) with pinned buckets can receive + new buckets. +2. If ``pinned_count > etalon_count``, the disbalance cannot be fixed, as the + ``rebalancer`` cannot move pinned buckets out of this replica set. In such a case + the etalon number is updated and set equal to the number of pinned buckets. + The replica sets with ``pinned_count > etalon_count`` are not processed by + the ``rebalancer``, and the number of pinned buckets is subtracted from the + total number of buckets. The rebalancer tries to move out as many buckets as + possible from such replica sets. +3. This procedure is restarted from step 1 for replica sets with + ``pinned_count >= etalon_count`` until ``pinned_count <= etalon_count`` on + all replica sets. The procedure is also restarted when the total number of + buckets is changed. Here is the pseudocode for the algorithm: -.. code-block:: lua +.. code-block:: lua function cluster_calculate_perfect_balance(replicasets, bucket_count) -- rebalance the buckets using weights of the still viable replica sets -- @@ -413,31 +406,30 @@ On each step, the algorithm either finishes the calculation, or ignores at least one new replica set overloaded with the pinned buckets, and updates the etalon number of buckets on other replica sets. -.. _vshard-ref: +.. _vshard-ref: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Bucket ref -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~ Bucket ref is an in-memory counter that is similar to the :ref:`bucket pin `, but has the following differences: -#. Bucket ref is not persistent. Refs are intended for forbidding bucket transfer - during request execution, but on restart all requests are dropped. +#. Bucket ref is not persistent. Refs are intended for forbidding bucket transfer + during request execution, but on restart all requests are dropped. -#. There are two types of bucket refs: read-only (RO) and read-write (RW). +#. There are two types of bucket refs: read-only (RO) and read-write (RW). - If a bucket has RW refs, it cannot be moved. However, when the rebalancer - needs it to be sent, it locks the bucket for new write requests, waits - until all current requests are finished, and then sends the bucket. + If a bucket has RW refs, it cannot be moved. However, when the rebalancer + needs it to be sent, it locks the bucket for new write requests, waits + until all current requests are finished, and then sends the bucket. - If a bucket has RO refs, it can be sent, but cannot be dropped. Such a - bucket can even enter GARBAGE or SENT state, but its data is kept until - the last reader is gone. + If a bucket has RO refs, it can be sent, but cannot be dropped. Such a + bucket can even enter GARBAGE or SENT state, but its data is kept until + the last reader is gone. - A single bucket can have both RO and RW refs. + A single bucket can have both RO and RW refs. -#. Bucket ref is countable. +#. Bucket ref is countable. The :ref:`vshard.storage.bucket_ref/unref()` methods are called automatically when :ref:`vshard.router.call() ` @@ -453,7 +445,7 @@ To see how many refs there are for a bucket, use For example: -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession vshard.storage.buckets_info(1) --- @@ -465,11 +457,10 @@ For example: rw_lock: true id: 1 -.. _vshard-define-spaces: +.. _vshard-define-spaces: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Defining spaces -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~ Database Schema is stored on ``storages``, while ``routers`` know nothing about spaces and tuples. @@ -477,7 +468,7 @@ spaces and tuples. Spaces should be defined within a storage application using ``box.once()``. For example: -.. code-block:: lua +.. code-block:: lua box.once("testapp:schema:1", function() local customer = box.schema.space.create('customer') @@ -507,22 +498,21 @@ For example: box.schema.func.create('customer_add') end) -.. NOTE:: +.. note:: Every space you plan to shard must have a field with :ref:`bucket id ` numbers, indexed by the :ref:`shard index `. -.. _vshard-adding-data: +.. _vshard-adding-data: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Adding data -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~ All DML operations with data should be performed via ``router``. The only operation supported by ``router`` is `CALL` via ``bucket_id``: -.. code-block:: lua +.. code-block:: lua result = vshard.router.call(bucket_id, mode, func, args) @@ -538,44 +528,42 @@ same replica set. .. _vshard-bootstrap: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Bootstrapping and restarting a storage -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If a replica set master fails, it is recommended to: -#. Switch one of the replicas into the master mode. This allows the new master - to process all the incoming requests. -#. Update the configuration of all the cluster members. This forwards all the - requests to the new master. +#. Switch one of the replicas into the master mode. This allows the new master + to process all the incoming requests. +#. Update the configuration of all the cluster members. This forwards all the + requests to the new master. Monitoring the master and switching the instance modes can be handled by any external utility. To perform a scheduled downtime of a replica set master, it is recommended to: -#. Update the configuration of the master and wait for the replicas to get into - sync. All the requests then are forwarded to a new master. -#. Switch another instance into the master mode. -#. Update the configuration of all the nodes. -#. Shut down the old master. +#. Update the configuration of the master and wait for the replicas to get into + sync. All the requests then are forwarded to a new master. +#. Switch another instance into the master mode. +#. Update the configuration of all the nodes. +#. Shut down the old master. To perform a scheduled downtime of a replica set, it is recommended to: -#. Migrate all the buckets to the other cluster storages. -#. Update the configuration of all the nodes. -#. Shut down the replica set. +#. Migrate all the buckets to the other cluster storages. +#. Update the configuration of all the nodes. +#. Shut down the replica set. In case a whole replica set fails, some part of the dataset becomes inaccessible. Meanwhile, the ``router`` tries to reconnect to the master of the failed replica set. This way, once the replica set is up and running again, the cluster is automatically restored. -.. _vshard-fibers: +.. _vshard-fibers: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Fibers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~ Searches for buckets, buckets recovery, and buckets rebalancing are performed automatically and do not require manual intervention. @@ -583,53 +571,50 @@ automatically and do not require manual intervention. Technically, there are multiple fibers responsible for different types of operations: -* a **discovery** fiber on the ``router`` searches for buckets in the background -* a **failover** fiber on the ``router`` maintains replica connections -* a **garbage collector** fiber on each master ``storage`` removes the contents - of buckets that were moved -* a **bucket recovery** fiber on each master ``storage`` recovers buckets in the - SENDING and RECEIVING states in case of reboot -* a **rebalancer** on a single master ``storage`` among all replica sets executes - the rebalancing process. +* a **discovery** fiber on the ``router`` searches for buckets in the background +* a **failover** fiber on the ``router`` maintains replica connections +* a **garbage collector** fiber on each master ``storage`` removes the contents + of buckets that were moved +* a **bucket recovery** fiber on each master ``storage`` recovers buckets in the + SENDING and RECEIVING states in case of reboot +* a **rebalancer** on a single master ``storage`` among all replica sets executes + the rebalancing process. See the :ref:`Rebalancing process ` and :ref:`Migration of buckets ` sections for details. -.. _vshard-gc: +.. _vshard-gc: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Garbage collector -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +^^^^^^^^^^^^^^^^^ A **garbage collector** fiber runs in the background on the master storages of each replica set. It starts deleting the contents of the bucket in the GARBAGE state part by part. Once the bucket is empty, its record is deleted from the ``_bucket`` system space. -.. _vshard-bucket-recovery: +.. _vshard-bucket-recovery: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Bucket recovery -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +^^^^^^^^^^^^^^^ A **bucket recovery** fiber runs on the master storages. It helps to recover buckets in the SENDING and RECEIVING states in case of reboot. Buckets in the SENDING state are recovered as follows: -1. The system first searches for buckets in the SENDING state. -2. If such a bucket is found, the system sends a request to the destination - replica set. -3. If the bucket on the destination replica set is ACTIVE, the original bucket - is deleted from the source node. +1. The system first searches for buckets in the SENDING state. +2. If such a bucket is found, the system sends a request to the destination + replica set. +3. If the bucket on the destination replica set is ACTIVE, the original bucket + is deleted from the source node. Buckets in the RECEIVING state are deleted without extra checks. -.. _vshard-failover: +.. _vshard-failover: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Failover -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +^^^^^^^^ A **failover** fiber runs on every ``router``. If a master of a replica set becomes unavailable, the failover fiber redirects read requests to the replicas. diff --git a/doc/book/app_server/index.rst b/doc/book/app_server/index.rst deleted file mode 100644 index b390f30e96..0000000000 --- a/doc/book/app_server/index.rst +++ /dev/null @@ -1,27 +0,0 @@ -:noindex: -:fullwidth: - -.. _app_server: - -******************************************************************************** -Application server -******************************************************************************** - -Here we introduce the basics of working with Tarantool as a Lua -application server. - -This chapter contains the following sections: - -.. toctree:: - :maxdepth: 2 - :numbered: 0 - - launching_app - creating_app - installing_module - contributing_module - reloading_module - luajit_memprof - luajit_getmetrics - using_ide - cookbook diff --git a/doc/book/app_server/installing_module.rst b/doc/book/app_server/installing_module.rst deleted file mode 100644 index d78a3d9dd4..0000000000 --- a/doc/book/app_server/installing_module.rst +++ /dev/null @@ -1,91 +0,0 @@ -.. _app_server-installing_module: - -================================================================================ -Installing a module -================================================================================ - -Modules in Lua and C that come from Tarantool developers and community -contributors are available in the following locations: - -* Tarantool modules repository (see :ref:`below `) -* Tarantool deb/rpm repositories (see :ref:`below `) - -.. _app_server-installing_module_luarocks: - --------------------------------------------------------------------------------- -Installing a module from a repository --------------------------------------------------------------------------------- - -See -`README in tarantool/rocks repository `_ -for detailed instructions. - -.. _app_server-installing_module_debrpm: - --------------------------------------------------------------------------------- -Installing a module from deb/rpm --------------------------------------------------------------------------------- - -Follow these steps: - -1. Install Tarantool as recommended on the - `download page `_. - -2. Install the module you need. Look up the module's name on - `Tarantool rocks page `_ and put the prefix - "tarantool-" before the module name to avoid ambiguity: - - .. code-block:: console - - $ # for Ubuntu/Debian: - $ sudo apt-get install tarantool- - - $ # for RHEL/CentOS/Amazon: - $ sudo yum install tarantool- - - For example, to install the module - `shard `_ on Ubuntu, say: - - .. code-block:: console - - $ sudo apt-get install tarantool-shard - -Once these steps are complete, you can: - -* load any module with - - .. code-block:: tarantoolsession - - tarantool> name = require('module-name') - - for example: - - .. code-block:: tarantoolsession - - tarantool> shard = require('shard') - -* search locally for installed modules using ``package.path`` (Lua) or - ``package.cpath`` (C): - - .. code-block:: tarantoolsession - - tarantool> package.path - --- - - ./?.lua;./?/init.lua; /usr/local/share/tarantool/?.lua;/usr/local/share/ - tarantool/?/init.lua;/usr/share/tarantool/?.lua;/usr/share/tarantool/?/ini - t.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/ - usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua; - ... - - tarantool> package.cpath - --- - - ./?.so;/usr/local/lib/x86_64-linux-gnu/tarantool/?.so;/usr/lib/x86_64-li - nux-gnu/tarantool/?.so;/usr/local/lib/tarantool/?.so;/usr/local/lib/x86_64 - -linux-gnu/lua/5.1/?.so;/usr/lib/x86_64-linux-gnu/lua/5.1/?.so;/usr/local/ - lib/lua/5.1/?.so; - ... - - .. NOTE:: - - Question-marks stand for the module name that was specified earlier when - saying ``require('module-name')``. diff --git a/doc/book/app_server/reloading_module.rst b/doc/book/app_server/reloading_module.rst deleted file mode 100644 index 794e9108b3..0000000000 --- a/doc/book/app_server/reloading_module.rst +++ /dev/null @@ -1,117 +0,0 @@ -.. _app_server-reloading_module: - -================================================================================ -Reloading a module -================================================================================ - -You can reload any Tarantool application or module with zero downtime. - -.. _app_server-reloading_lua_module: - --------------------------------------------------------------------------------- -Reloading a module in Lua --------------------------------------------------------------------------------- - -Here's an example that illustrates the most typical case -- "update and reload". - -.. NOTE:: - - In this example, we use recommended :ref:`administration practices ` - based on :ref:`instance files ` and - :ref:`tarantoolctl ` utility. - -1. Update the application file. - - For example, a module in ``/usr/share/tarantool/app.lua``: - - .. code-block:: lua - - local function start() - -- initial version - box.once("myapp:v1.0", function() - box.schema.space.create("somedata") - box.space.somedata:create_index("primary") - ... - end) - - -- migration code from 1.0 to 1.1 - box.once("myapp:v1.1", function() - box.space.somedata.index.primary:alter(...) - ... - end) - - -- migration code from 1.1 to 1.2 - box.once("myapp:v1.2", function() - box.space.somedata.index.primary:alter(...) - box.space.somedata:insert(...) - ... - end) - end - - -- start some background fibers if you need - - local function stop() - -- stop all background fibers and clean up resources - end - - local function api_for_call(xxx) - -- do some business - end - - return { - start = start, - stop = stop, - api_for_call = api_for_call - } - -2. Update the :ref:`instance file `. - - For example, ``/etc/tarantool/instances.enabled/my_app.lua``: - - .. code-block:: lua - - #!/usr/bin/env tarantool - -- - -- hot code reload example - -- - - box.cfg({listen = 3302}) - - -- ATTENTION: unload it all properly! - local app = package.loaded['app'] - if app ~= nil then - -- stop the old application version - app.stop() - -- unload the application - package.loaded['app'] = nil - -- unload all dependencies - package.loaded['somedep'] = nil - end - - -- load the application - log.info('require app') - app = require('app') - - -- start the application - app.start({some app options controlled by sysadmins}) - - The important thing here is to properly unload the application and its - dependencies. - -3. Manually reload the application file. - - For example, using ``tarantoolctl``: - - .. code-block:: console - - $ tarantoolctl eval my_app /etc/tarantool/instances.enabled/my_app.lua - -.. _app_server-reloading_c_module: - --------------------------------------------------------------------------------- -Reloading a module in C --------------------------------------------------------------------------------- - -After you compiled a new version of a C module (``*.so`` shared library), call -:doc:`box.schema.func.reload('module-name') ` -from your Lua script to reload the module. diff --git a/doc/book/box/data_model.rst b/doc/book/box/data_model.rst deleted file mode 100644 index a26fc95486..0000000000 --- a/doc/book/box/data_model.rst +++ /dev/null @@ -1,1416 +0,0 @@ -.. _box_data_model: - -Data model -========== - -This section describes how Tarantool stores values and what operations with data -it supports. - -If you tried to create a database as suggested in our -:ref:`"Getting started" exercises `, -then your test database now looks like this: - -.. image:: data_model.png - -.. _index-box_tuple: - - -Tuples ------- - -Tarantool operates data in the form of tuples. - -.. glossary:: - - tuple - A tuple is a group of data values in Tarantool's memory. - Think of it as a "database record" or a "row". - The data values in the tuple are called :term:`fields `. - - When Tarantool returns a tuple value in the console, - by default, it uses :ref:`YAML ` format, - for example: ``[3, 'Ace of Base', 1993]``. - - Internally, Tarantool stores tuples as - `MsgPack `_ arrays. - - field - Fields are distinct data values, contained in a tuple. - They play the same role as "row columns" or "record fields" in relational databases, - with a few improvements: - - * fields can be composite structures, such as arrays or maps, - * fields don't need to have names. - - A given tuple may have any number of fields, and the fields may be of - different :ref:`types `. - - The field's number is the identifier of the field. - Numbers are counted from base 1 in Lua and other 1-based languages, - or from base 0 in languages like PHP or C/C++. - So, ``1`` or ``0`` can be used in some contexts to refer to the first - field of a tuple. - -.. _index-box_space: - -Spaces ------- - -Tarantool stores tuples in containers called spaces. -In the example above, there's a space called ``tester``. - -.. glossary:: - - space - In Tarantool, a space is a primary container that stores data. - It is analogous to tables in relational databases. - Spaces contain :term:`tuples ` -- the Tarantool name for - database records. - The number of tuples in a space is unlimited. - - At least one space is required to store data with Tarantool. - Each space has the following attributes: - - * a unique **name** specified by the user, - * a unique **numeric identifier** which can be specified by - the user, but usually is assigned automatically by Tarantool, - * an **engine**: *memtx* (default) --- in-memory engine, - fast but limited in size, or *vinyl* --- on-disk engine for huge data sets. - - To be functional, a space also needs to have a :ref:`primary index `. - It can also have secondary indexes. - -.. _index-box_index: - -Indexes -------- - -Read the full information about indexes on page :doc:`Indexes `. - -An **index** is a group of key values and pointers. - -As with spaces, you should specify the index **name** and let Tarantool -come up with a unique **numeric identifier** ("index id"). - -An index always has a **type**. The default index type is :ref:`TREE `. -TREE indexes are provided by all Tarantool engines, can index unique and -non-unique values, support partial key searches, comparisons, and ordered results. -Additionally, the memtx engine supports :ref:`HASH `, -:ref:`RTREE ` and :ref:`BITSET ` indexes. - -An index may be **multi-part**, that is, you can declare that an index key value -is composed of two or more fields in the tuple, in any order. -For example, for an ordinary TREE index, the maximum number of parts is 255. - -An index may be **unique**, that is, you can declare that it would be illegal -to have the same key value twice. - -The first index defined on a space is called the **primary key index**, -and it must be unique. All other indexes are called **secondary indexes**, -and they may be non-unique. - -.. _index-box_data-types: - -Data types ----------- - -Tarantool is both a database manager and an application server. -Therefore a developer often deals with two type sets: -the types of the programming language (such as Lua) and -the types of the Tarantool storage format (MsgPack). - -.. _index-box_lua-vs-msgpack: - -Lua versus MsgPack -~~~~~~~~~~~~~~~~~~ - -.. container:: table - - .. list-table:: - :widths: 15 30 15 40 - :header-rows: 1 - - * - Scalar / compound - - MsgPack type - - Lua type - - Example value - * - scalar - - nil - - `cdata`_ - - :ref:`box.NULL ` - * - scalar - - boolean - - `boolean`_ - - ``true`` - * - scalar - - string - - `string`_ - - ``'A B C'`` - * - scalar - - integer - - `number`_ - - ``12345`` - * - scalar - - integer - - `cdata`_ - - ``12345`` - * - scalar - - float64 (double) - - `number`_ - - ``1.2345`` - * - scalar - - float64 (double) - - `cdata`_ - - ``1.2345`` - * - scalar - - binary - - `cdata`_ - - ``[!!binary 3t7e]`` - * - scalar - - ext (for Tarantool ``decimal``) - - `cdata`_ - - ``1.2`` - * - scalar - - ext (for Tarantool ``datetime``) - - `cdata`_ - - ``'2021-08-20T16:21:25.122999906 Europe/Berlin'`` - * - scalar - - ext (for Tarantool ``interval``) - - `cdata`_ - - ``+1 months, 1 days`` - * - scalar - - ext (for Tarantool ``uuid``) - - `cdata`_ - - ``12a34b5c-de67-8f90-123g-h4567ab8901`` - * - compound - - map - - `table`_ (with string keys) - - ``{'a': 5, 'b': 6}`` - * - compound - - array - - `table`_ (with integer keys) - - ``[1, 2, 3, 4, 5]`` - * - compound - - array - - tuple (`cdata`_) - - ``[12345, 'A B C']`` - -.. _boolean: http://www.lua.org/pil/2.2.html -.. _string: http://www.lua.org/pil/2.4.html -.. _number: http://www.lua.org/pil/2.3.html -.. _table: http://www.lua.org/pil/2.5.html -.. _cdata: http://luajit.org/ext_ffi.html#call - -.. note:: - - MsgPack values have variable lengths. - So, for example, the smallest number requires only one byte, but the largest number - requires nine bytes. - -.. note:: - - The Lua `nil `_ type is encoded as MsgPack ``nil`` but - decoded as :ref:`msgpack.NULL `. - -.. _index_box_field_type_details: - -Field type details -~~~~~~~~~~~~~~~~~~ - -.. _index-box_nil: - -**nil**. In Lua, the nil type has only one possible value, also called ``nil``. -Tarantool displays it as ``null`` when using the default -:ref:`YAML ` format. -Nil may be compared to values of any types with == (is-equal) -or ~= (is-not-equal), but other comparison operations will not work. -Nil may not be used in Lua tables; the workaround is to use -:ref:`box.NULL ` because ``nil == box.NULL`` is true. -Example: ``nil``. - -.. _index-box_boolean: - -**boolean**. A boolean is either ``true`` or ``false``. -Example: ``true``. - -.. _index-box_integer: - -**integer**. The Tarantool integer type is for integers between --9223372036854775808 and 18446744073709551615, which is about 18 quintillion. -This type corresponds to the number type in Lua and to the integer type in MsgPack. -Example: ``-2^63``. - -.. _index-box_unsigned: - -**unsigned**. The Tarantool unsigned type is for integers between -0 and 18446744073709551615. So it is a subset of integer. -Example: ``123456``. - -.. _index-box_double: - -**double**. The double field type exists -mainly to be equivalent to Tarantool/SQL's -:ref:`DOUBLE data type `. -In `msgpuck.h `_ (Tarantool's interface to MsgPack), -the storage type is ``MP_DOUBLE`` and the size of the encoded value is always 9 bytes. -In Lua, fields of the double type can only contain non-integer numeric values and -cdata values with double floating-point numbers. -Examples: ``1.234``, ``-44``, ``1.447e+44``. - -To avoid using the wrong kind of values inadvertently, use -``ffi.cast()`` when searching or changing ``double`` fields. -For example, instead of -:samp:`{space_object}:insert`:code:`{`:samp:`{value}`:code:`}` -use -``ffi = require('ffi') ...`` -:samp:`{space_object}:insert`:code:`({ffi.cast('double',`:samp:`{value}`:code:`)})`. -Example: - -.. code-block:: tarantoolsession - - s = box.schema.space.create('s', {format = {{'d', 'double'}}}) - s:create_index('ii') - s:insert({1.1}) - ffi = require('ffi') - s:insert({ffi.cast('double', 1)}) - s:insert({ffi.cast('double', tonumber('123'))}) - s:select(1.1) - s:select({ffi.cast('double', 1)}) - -Arithmetic with cdata ``double`` will not work reliably, so -for Lua, it is better to use the ``number`` type. -This warning does not apply for Tarantool/SQL because -Tarantool/SQL does -:ref:`implicit casting `. - -.. _index-box_number: - -**number**. The Tarantool number field may have both -integer and floating-point values, although in Lua a ``number`` -is a double-precision floating-point. - -Tarantool will try to store a Lua number as -floating-point if the value contains a decimal point or is very large -(greater than 100 trillion = 1e14), otherwise Tarantool will store it as an integer. -To ensure that even very large numbers are stored as integers, use the -:ref:`tonumber64 ` function, or the LL (Long Long) suffix, -or the ULL (Unsigned Long Long) suffix. -Here are examples of numbers using regular notation, exponential notation, -the ULL suffix and the ``tonumber64`` function: -``-55``, ``-2.7e+20``, ``100000000000000ULL``, ``tonumber64('18446744073709551615')``. - -You can also use the ``ffi`` module to specify a C type to cast the number to. -In this case, the number will be stored as `cdata`_. - -.. _index-box_decimal: - -**decimal**. The Tarantool decimal type is stored as a :ref:`MsgPack ext ` (Extension). -Values with the decimal type are not floating-point values although -they may contain decimal points. -They are exact with up to 38 digits of precision. -Example: a value returned by a function in the :ref:`decimal ` module. - -.. _index-box_datetime: - -**datetime**. Introduced in :tarantool-release:`2.10.0`. -The Tarantool ``datetime`` type facilitates operations with date and time, -accounting for leap years or the varying number of days in a month. -It is stored as a :ref:`MsgPack ext ` (Extension). -Operations with this data type use code from `c-dt `_, a third-party library. - -For more information, see :doc:`Module datetime `. - -.. _index-box_interval: - -**interval**. Introduced in :tarantool-release:`2.10.0`. -The Tarantool ``interval`` type represents periods of time. -They can be added to or subtracted from ``datetime`` values or each other. -Operations with this data type use code from `c-dt `_, a third-party library. -The type is stored as a :ref:`MsgPack ext ` (Extension). -For more information, see :doc:`Module datetime `. - -.. _index-box_string: - -**string**. A string is a variable-length sequence of bytes, usually represented with -alphanumeric characters inside single quotes. In both Lua and MsgPack, strings -are treated as binary data, with no attempts to determine a string's -character set or to perform any string conversion -- unless there is an optional -:ref:`collation `. -So, usually, string sorting and comparison are done byte-by-byte, without any special -collation rules applied. -For example, numbers are ordered by their point on the number line, so 2345 is -greater than 500; meanwhile, strings are ordered by the encoding of the first -byte, then the encoding of the second byte, and so on, so ``'2345'`` is less than ``'500'``. -Example: ``'A, B, C'``. - -.. _index-box_bin: - -**bin**. A bin (binary) value is not directly supported by Lua but there is -a Tarantool type ``varbinary`` which is encoded as MsgPack binary. -For an (advanced) example showing how to insert varbinary into a database, -see the Cookbook Recipe for :ref:`ffi_varbinary_insert `. -Example: ``"\65 \66 \67"``. - -.. _index-box_uuid: - -**uuid**. The Tarantool uuid type is used for -:ref:`Universally Unique Identifiers `. -Since version :doc:`2.4.1 ` Tarantool stores -``uuid`` values as a :ref:`MsgPack ext ` (Extension). - -Example: ``64d22e4d-ac92-4a23-899a-e5934af5479``. - -.. _index-box_array: - -**array**. An array is represented in Lua with ``{...}`` (`braces `_). -Examples: lists of numbers representing points in geometric figures: -``{10, 11}``, ``{3, 5, 9, 10}``. - -**table**. Lua tables with string keys are stored as MsgPack maps; -Lua tables with integer keys starting with 1 are stored as MsgPack arrays. -Nils may not be used in Lua tables; the workaround is to use -:ref:`box.NULL `. -Example: a ``box.space.tester:select()`` request will return a Lua table. - -**tuple**. A tuple is a light reference to a MsgPack array stored in the database. -It is a special type (cdata) to avoid conversion to a Lua table on retrieval. -A few functions may return tables with multiple tuples. For tuple examples, -see :ref:`box.tuple `. - -.. _index-box_scalar: - -**scalar**. Values in a scalar field can be boolean, integer, unsigned, double, -number, decimal, string, uuid, or varbinary; but not array, map, or tuple. -Examples: ``true``, ``1``, ``'xxx'``. - -.. _index-box_any: - -**any**. Values in a field of this type can be boolean, integer, unsigned, double, -number, decimal, string, uuid, varbinary, array, map, or tuple. -Examples: ``true``, ``1``, ``'xxx'``, ``{box.NULL, 0}``. - -Examples of insert requests with different field types: - -.. code-block:: tarantoolsession - - tarantool> box.space.K:insert{1,nil,true,'A B C',12345,1.2345} - --- - - [1, null, true, 'A B C', 12345, 1.2345] - ... - tarantool> box.space.K:insert{2,{['a']=5,['b']=6}} - --- - - [2, {'a': 5, 'b': 6}] - ... - tarantool> box.space.K:insert{3,{1,2,3,4,5}} - --- - - [3, [1, 2, 3, 4, 5]] - ... - -.. _index-box_indexed-field-types: - -Indexed field types -~~~~~~~~~~~~~~~~~~~ - -Indexes restrict values that Tarantool can store with MsgPack. -This is why, for example, ``'unsigned'`` and ``'integer'`` are different field types, -although in MsgPack they are both stored as integer values. -An ``'unsigned'`` index contains only *non-negative* integer values, -while an ``‘integer’`` index contains *any* integer values. - -Here again are the field types described in -:ref:`Field type details `, and the index types they can fit in. -The default field type is ``'unsigned'`` and the default index type is TREE. -Although ``'nil'`` is not a legal indexed field type, indexes may contain `nil` -:ref:`as a non-default option `. -Full information is in section -:ref:`Details about index field types `. - -.. container:: table - - .. list-table:: - :header-rows: 1 - :widths: 34 33 33 - - * - Field type name string - - Field type - - Index type - * - ``'boolean'`` - - :ref:`boolean ` - - :ref:`boolean ` - * - ``'integer'`` (may also be called ``'int'``) - - :ref:`integer `, which may include unsigned values - - TREE or HASH - * - ``'unsigned'`` (may also be called ``'uint'`` or ``'num'``, but ``'num'`` is deprecated) - - :ref:`unsigned ` - - TREE, BITSET, or HASH - * - ``'double'`` - - :ref:`double ` - - TREE or HASH - * - ``'number'`` - - :ref:`number `, which may include - :ref:`integer `, :ref:`double `, - or :ref:`decimal ` values - - TREE or HASH - * - ``'decimal'`` - - :ref:`decimal ` - - TREE or HASH - * - ``'string'`` (may also be called ``'str'``) - - :ref:`string ` - - TREE, BITSET, or HASH - * - ``'varbinary'`` - - :ref:`varbinary ` - - TREE, HASH, or BITSET (since version 2.7) - * - ``'uuid'`` - - :ref:`uuid ` - - TREE or HASH - * - ``datetime`` - - :ref:`datetime ` - - TREE - * - ``'array'`` - - :ref:`array ` - - :ref:`RTREE ` - * - ``'scalar'`` - - may include :ref:`nil `, - :ref:`boolean `, - :ref:`integer `, - :ref:`unsigned `, - :ref:`number `, - :ref:`decimal `, - :ref:`string `, - :ref:`varbinary `, - or :ref:`uuid ` values | - |br| - When a scalar field contains values of - different underlying types, the key order - is: nils, then booleans, then numbers, - then strings, then varbinaries, then - uuids. - - TREE or HASH - -.. _index-collation: - -Collations ----------- - -By default, when Tarantool compares strings, it uses the so-called -**binary collation**. -It only considers the numeric value of each byte in a string. -For example, the encoding of ``'A'`` (what used to be called the "ASCII value") is 65, -the encoding of ``'B'`` is 66, and the encoding of ``'a'`` is 98. -Therefore, if the string is encoded with ASCII or UTF-8, then ``'A' < 'B' < 'a'``. - -Binary collation is the best choice for fast deterministic simple maintenance and searching -with Tarantool indexes. - -But if you want the ordering that you see in phone books and dictionaries, -then you need Tarantool's optional collations, such as ``unicode`` and -``unicode_ci``, which allow for ``'a' < 'A' < 'B'`` and ``'a' == 'A' < 'B'`` -respectively. - -**The unicode and unicode_ci optional collations** use the ordering according to the -`Default Unicode Collation Element Table (DUCET) `_ -and the rules described in -`Unicode® Technical Standard #10 Unicode Collation Algorithm (UTS #10 UCA) `_. -The only difference between the two collations is about -`weights `_: - -* ``unicode`` collation observes L1, L2, and L3 weights (strength = 'tertiary'); -* ``unicode_ci`` collation observes only L1 weights (strength = 'primary'), so for example ``'a' == 'A' == 'á' == 'Á'``. - -As an example, take some Russian words: - -.. code-block:: text - - 'ЕЛЕ' - 'елейный' - 'ёлка' - 'еловый' - 'елозить' - 'Ёлочка' - 'ёлочный' - 'ЕЛь' - 'ель' - -...and show the difference in ordering and selecting by index: - -* with ``unicode`` collation: - - .. code-block:: tarantoolsession - - tarantool> box.space.T:create_index('I', {parts = {{field = 1, type = 'str', collation='unicode'}}}) - ... - tarantool> box.space.T.index.I:select() - --- - - - ['ЕЛЕ'] - - ['елейный'] - - ['ёлка'] - - ['еловый'] - - ['елозить'] - - ['Ёлочка'] - - ['ёлочный'] - - ['ель'] - - ['ЕЛь'] - ... - tarantool> box.space.T.index.I:select{'ЁлКа'} - --- - - [] - ... - -* with ``unicode_ci`` collation: - - .. code-block:: tarantoolsession - - tarantool> box.space.T:create_index('I', {parts = {{field = 1, type ='str', collation='unicode_ci'}}}) - ... - tarantool> box.space.T.index.I:select() - --- - - - ['ЕЛЕ'] - - ['елейный'] - - ['ёлка'] - - ['еловый'] - - ['елозить'] - - ['Ёлочка'] - - ['ёлочный'] - - ['ЕЛь'] - ... - tarantool> box.space.T.index.I:select{'ЁлКа'} - --- - - - ['ёлка'] - ... - - -In all, collation involves much more than these simple examples of -upper case / lower case and accented / unaccented equivalence in alphabets. -We also consider variations of the same character, non-alphabetic writing systems, -and special rules that apply for combinations of characters. - -For English, Russian, and most other languages and use cases, use the "unicode" and "unicode_ci" collations. -If you need Cyrillic letters 'Е' and 'Ё' to have the same level-1 weights, -try the Kyrgyz collation. - -**The tailored optional collations**: for other languages, Tarantool supplies tailored collations for every -modern language that has more than a million native speakers, and -for specialized situations such as the difference between dictionary -order and telephone book order. -Run ``box.space._collation:select()`` to see the complete list. - -The tailored collation names have the form -``unicode_[language code]_[strength]``, where language code is a standard -2-character or 3-character language abbreviation, and strength is ``s1`` -for "primary strength" (level-1 weights), ``s2`` for "secondary", ``s3`` for "tertiary". -Tarantool uses the same language codes as the ones in the "list of tailorable locales" on man pages of -`Ubuntu `_ and -`Fedora `_. -Charts explaining the precise differences from DUCET order are -in the -`Common Language Data Repository `_. - -.. _index-constraints: - -Constraints ------------ - -For better control over stored data, Tarantool supports **constraints** – user-defined -limitations on the values of certain fields or entire tuples. Together with data types, -constraints allow limiting the ranges of available field values both syntactically and semantically. - -For example, the field ``age`` typically has the ``number`` type, so it cannot store -strings or boolean values. However, it can still have values that don't make sense, -such as negative numbers. This is where constraints come to help. - -.. _index-constraint_types: - -Constraint types -~~~~~~~~~~~~~~~~ - -There are two types of constraints in Tarantool: - -* *Field constraints* check that the value being assigned to a field - satisfies a given condition. For example, ``age`` must be non-negative. - -* *Tuple constraints* check complex conditions that can involve all fields of - a tuple. For example, a tuple contains a date in three fields: - ``year``, ``month``, and ``day``. You can validate ``day`` values based on - the ``month`` value (and even ``year`` if you consider leap years). - -Field constraints work faster, while tuple constraints allow implementing -a wider range of limitations. - -.. _index-constraint_functions: - -Constraint functions -~~~~~~~~~~~~~~~~~~~~ - -Constraints use stored Lua functions, which must return ``true`` when the constraint -is satisfied. Other return values (including ``nil``) and exceptions make the -check fail and prevent tuple insertion or modification. - -To create a constraint function, use :ref:`func.create with function body `. - -Constraint functions take two parameters: - -* The field value and the constraint name for field constraints. - - .. code-block:: tarantoolsession - - tarantool> box.schema.func.create('check_age', - > {language = 'LUA', is_deterministic = true, body = 'function(f, c) return (f >= 0 and f < 150) end'}) - --- - ... - -* The tuple and the constraint name for tuple constraints. - - .. code-block:: tarantoolsession - - tarantool> box.schema.func.create('check_person', - > {language = 'LUA', is_deterministic = true, body = 'function(t, c) return (t.age >= 0 and #(t.name) > 3) end'}) - --- - ... - -.. warning:: - - Tarantool doesn't check field names used in tuple constraint functions. - If a field referenced in a tuple constraint gets renamed, this constraint will break - and prevent further insertions and modifications in the space. - -.. _index-constraint_apply: - -Creating constraints -~~~~~~~~~~~~~~~~~~~~ - -To create a constraint in a space, specify the corresponding function's name -in the ``constraint`` parameter: - -* Field constraints: when setting up the space format: - - .. code-block:: tarantoolsession - - tarantool> box.space.person:format({ - > {name = 'id', type = 'number'}, - > {name = 'name', type = 'string'}, - > {name = 'age', type = 'number', constraint = 'check_age'}, - > }) - -* Tuple constraints: when creating or altering a space: - - .. code-block:: tarantoolsession - - tarantool> box.schema.space.create('person', { engine = 'memtx', constraint = 'check_tuple'}) - -In both cases, ``constraint`` can contain multiple function names passed as a tuple. -Each constraint can have an optional name: - -.. code-block:: lua - - constraint = {'age_constraint' = 'check_age', 'name_constraint' = 'check_name'} - -.. note:: - - When adding a constraint to an existing space with data, Tarantool checks it - against the stored data. If there are fields or tuples that don't satisfy - the constraint, it won't be applied to the space. - - -.. _index-box_foreign_keys: - -Foreign keys ------------- - -**Foreign keys** provide links between related spaces, therefore maintaining the -`referential integrity `_ -of the database. - -Some fields can only contain values present in other spaces. For example, -shop orders always belong to existing customers. Hence, all values of the ``customer`` -field of the ``orders`` space must exist in the ``customers`` space. In this case, -``customers`` is a **parent space** for ``orders`` (its **child space**). When two -spaces are linked with a foreign key, each time a tuple is inserted or modified -in the child space, Tarantool checks that a corresponding value is present in -the parent space. - - -.. image:: foreign_key.svg - :align: center - -Foreign key types -~~~~~~~~~~~~~~~~~ - -There are two types of foreign keys in Tarantool: - -* *Field foreign keys* check that the value being assigned to a field - is present in a particular field of another space. For example, the ``customer`` - value in a tuple from the ``orders`` space must match an ``id`` stored in the ``customers`` space. - -* *Tuple foreign keys* check that multiple fields of a tuple have a match in - another space. For example, if the ``orders`` space has fields ``customer_id`` - and ``customer_name``, a tuple foreign key can check that the ``customers`` space - contains a tuple with both these values in the corresponding fields. - -Field foreign keys work faster while tuple foreign keys allow implementing -more strict references. - -Creating foreign keys -~~~~~~~~~~~~~~~~~~~~~ - -.. important:: - - For each foreign key, there must exist an index that includes all its fields. - -To create a foreign key in a space, specify the parent space and linked fields in the ``foreign_key`` parameter. -Fields can be referenced by name or by number: - -* Field foreign keys: when setting up the space format. - - .. code-block:: tarantoolsession - - tarantool> box.space.orders:format({ - > {name = 'id', type = 'number'}, - > {name = 'customer_id', foreign_key = {space = 'customers', field = 'id'}}, -- or field = 1 - > {name = 'price_total', type = 'number'}, - > }) - -* Tuple foreign keys: when creating or altering a space. Note that for foreign - keys with multiple fields there must exist an index that includes all these fields. - - .. code-block:: tarantoolsession - - tarantool> box.schema.space.create("orders", {foreign_key={space='customers', field={customer_id='id', customer_name='name'}}}) - --- - ... - tarantool> box.space.orders:format({ - > {name = "id", type = "number"}, - > {name = "customer_id" }, - > {name = "customer_name"}, - > {name = "price_total", type = "number"}, - > }) - -.. note:: - - Type can be omitted for foreign key fields because it's - defined in the parent space. - -Foreign keys can have an optional name. - -.. code-block:: lua - - foreign_key = {customer = {space = '...', field = {...}}} - -A space can have multiple tuple foreign keys. In this case, they all must have names. - -.. code-block:: lua - - foreign_key = {customer = {space = '...', field = {...} }, item = { space = '...', field = {...}}} - -Tarantool performs integrity checks upon data modifications in parent spaces. -If you try to remove a tuple referenced by a foreign key or an entire parent space, -you will get an error. - -.. important:: - - Renaming parent spaces or referenced fields may break the corresponding foreign - keys and prevent further insertions or modifications in the child spaces. - - -.. _index-box_sequence: - -Sequences ---------- - -A **sequence** is a generator of ordered integer values. - -As with spaces and indexes, you should specify the sequence **name** and let -Tarantool generate a unique numeric identifier (sequence ID). - -As well, you can specify several options when creating a new sequence. -The options determine what value will be generated whenever the sequence is used. - -.. _index-box_sequence-options: - -Options for box.schema.sequence.create() -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. container:: table - - .. list-table:: - :widths: 20 40 15 25 - :header-rows: 1 - - * - Option name - - Type and meaning - - Default - - Examples - * - ``start`` - - Integer. The value to generate the first time a sequence is used - - 1 - - ``start=0`` - * - ``min`` - - Integer. Values smaller than this cannot be generated - - 1 - - ``min=-1000`` - * - ``max`` - - Integer. Values larger than this cannot be generated - - 9223372036854775807 - - ``max=0`` - * - ``cycle`` - - Boolean. Whether to start again when values cannot be generated - - false - - ``cycle=true`` - * - ``cache`` - - Integer. The number of values to store in a cache - - 0 - - ``cache=0`` - * - ``step`` - - Integer. What to add to the previous generated value, when generating a new value - - 1 - - ``step=-1`` - * - ``if_not_exists`` - - Boolean. If this is true and a sequence with this name exists already, - ignore other options and use the existing values - - ``false`` - - ``if_not_exists=true`` - - -Once a sequence exists, it can be altered, dropped, reset, forced to generate -the next value, or associated with an index. - -For an initial example, we generate a sequence named 'S'. - -.. code-block:: tarantoolsession - - tarantool> box.schema.sequence.create('S',{min=5, start=5}) - --- - - step: 1 - id: 5 - min: 5 - cache: 0 - uid: 1 - max: 9223372036854775807 - cycle: false - name: S - start: 5 - ... - -The result shows that the new sequence has all default values, -except for the two that were specified, ``min`` and ``start``. - -Then we get the next value, with the ``next()`` function. - -.. code-block:: tarantoolsession - - tarantool> box.sequence.S:next() - --- - - 5 - ... - -The result is the same as the start value. If we called ``next()`` -again, we would get 6 (because the previous value plus the -step value is 6), and so on. - -Then we create a new table and specify that its primary key should be -generated from the sequence. - -.. code-block:: tarantoolsession - - tarantool> s=box.schema.space.create('T') - --- - ... - tarantool> s:create_index('I',{sequence='S'}) - --- - - parts: - - type: unsigned - is_nullable: false - fieldno: 1 - sequence_id: 1 - id: 0 - space_id: 520 - unique: true - type: TREE - sequence_fieldno: 1 - name: I - ... - --- - ... - -Then we insert a tuple without specifying a value for the primary key. - -.. code-block:: tarantoolsession - - tarantool> box.space.T:insert{nil,'other stuff'} - --- - - [6, 'other stuff'] - ... - -The result is a new tuple where the first field has a value of 6. -This arrangement, where the system automatically generates the -values for a primary key, is sometimes called "auto-incrementing" -or "identity". - -For syntax and implementation details, see the reference for -:doc:`box.schema.sequence `. - -.. _index-box_persistence: - -Persistence ------------ - -To ensure data persistence, Tarantool records updates to the database in the so-called -:ref:`write-ahead log (WAL) ` files. -When a power outage occurs or the Tarantool instance is killed incidentally, -the in-memory database is lost. -In such case, Tarantool restores the data from WAL files -by reading them and redoing the requests. -This is called the "recovery process". -You can change the timing of the WAL writer or turn it off by setting -the :ref:`wal_mode `. - -Tarantool also maintains a set of :ref:`snapshot files `. -These files contain an on-disk copy of the entire data set for a given moment. -Instead of reading every WAL file since the databases were created, the recovery -process can load the latest snapshot file and then read the WAL files, -produced after the snapshot file was made. -After creating a new snapshot, the earlier WAL files can be removed to free up space. - -To force immediate creation of a snapshot file, use the -:doc:`box.snapshot() ` function. -To enable the automatic creation of snapshot files, use Tarantool's -:ref:`checkpoint daemon `. -The checkpoint daemon sets intervals for forced checkpoints. It makes sure that the states -of both memtx and vinyl storage engines are synchronized and saved to disk, -and automatically removes earlier WAL files. - -Snapshot files can be created even if there is no WAL file. - -.. NOTE:: - - The memtx engine makes only regular checkpoints with the interval set in - :ref:`checkpoint daemon ` configuration. - - The vinyl engine runs checkpointing in the background at all times. - -See the :ref:`Internals ` section for more details -about the WAL writer and the recovery process. - -.. _index-box_operations: - -Operations ----------- - -.. _index-box_data-operations: - -Data operations -~~~~~~~~~~~~~~~ - -The basic data operations supported in Tarantool are: - -* five data-manipulation operations (INSERT, UPDATE, UPSERT, DELETE, REPLACE), and -* one data-retrieval operation (SELECT). - -All of them are implemented as functions in :ref:`box.space ` submodule. - -**Examples:** - -* :ref:`INSERT `: Add a new tuple to space 'tester'. - - The first field, field[1], will be 999 (MsgPack type is `integer`). - - The second field, field[2], will be 'Taranto' (MsgPack type is `string`). - - .. code-block:: tarantoolsession - - tarantool> box.space.tester:insert{999, 'Taranto'} - -* :ref:`UPDATE `: Update the tuple, changing field field[2]. - - The clause "{999}", which has the value to look up in the index of the tuple's - primary-key field, is mandatory, because ``update()`` requests must always have - a clause that specifies a unique key, which in this case is field[1]. - - The clause "{{'=', 2, 'Tarantino'}}" specifies that assignment will happen to - field[2] with the new value. - - .. code-block:: tarantoolsession - - tarantool> box.space.tester:update({999}, {{'=', 2, 'Tarantino'}}) - -* :ref:`UPSERT `: Upsert the tuple, changing field field[2] - again. - - The syntax of ``upsert()`` is similar to the syntax of ``update()``. However, - the execution logic of these two requests is different. - UPSERT is either UPDATE or INSERT, depending on the database's state. - Also, UPSERT execution is postponed until after transaction commit, so, unlike - ``update()``, ``upsert()`` doesn't return data back. - - .. code-block:: tarantoolsession - - tarantool> box.space.tester:upsert({999, 'Taranted'}, {{'=', 2, 'Tarantism'}}) - -* :ref:`REPLACE `: Replace the tuple, adding a new field. - - This is also possible with the ``update()`` request, but the ``update()`` - request is usually more complicated. - - .. code-block:: tarantoolsession - - tarantool> box.space.tester:replace{999, 'Tarantella', 'Tarantula'} - -* :ref:`SELECT `: Retrieve the tuple. - - The clause "{999}" is still mandatory, although it does not have to mention - the primary key. - - .. code-block:: tarantoolsession - - tarantool> box.space.tester:select{999} - -* :ref:`DELETE `: Delete the tuple. - - In this example, we identify the primary-key field. - - .. code-block:: tarantoolsession - - tarantool> box.space.tester:delete{999} - -Summarizing the examples: - -* Functions ``insert`` and ``replace`` accept a tuple - (where a primary key comes as part of the tuple). -* Function ``upsert`` accepts a tuple - (where a primary key comes as part of the tuple), - and also the update operations to execute. -* Function ``delete`` accepts a full key of any unique index - (primary or secondary). -* Function ``update`` accepts a full key of any unique index - (primary or secondary), - and also the operations to execute. -* Function ``select`` accepts any key: primary/secondary, unique/non-unique, - full/partial. - -See reference on ``box.space`` for more -:ref:`details on using data operations `. - -.. NOTE:: - - Besides Lua, you can use - :ref:`Perl, PHP, Python or other programming language connectors `. - The client server protocol is open and documented. - See this :ref:`annotated BNF `. - -.. _index-box_complexity-factors: - -Complexity factors -~~~~~~~~~~~~~~~~~~ - -In reference for :ref:`box.space ` and -:doc:`/reference/reference_lua/box_index` -submodules, there are notes about which complexity factors might affect the -resource usage of each function. - -.. container:: table - - .. list-table:: - :widths: 20 80 - :header-rows: 1 - - * - Complexity factor - - Effect - * - Index size - - The number of index keys is the same as the number - of tuples in the data set. For a TREE index, if - there are more keys, then the lookup time will be - greater, although, of course, the effect is not - linear. For a HASH index, if there are more keys, - then there is more RAM used, but the number of - low-level steps tends to remain constant. - * - Index type - - Typically, a HASH index is faster than a TREE index - if the number of tuples in the space is greater - than one. - * - Number of indexes accessed - - Ordinarily, only one index is accessed to retrieve - one tuple. But to update the tuple, there must be N - accesses if the space has N different indexes. - |br| - Note regarding storage engine: Vinyl optimizes away such - accesses if secondary index fields are unchanged by - the update. So, this complexity factor applies only to - memtx, since it always makes a full-tuple copy on every - update. - * - Number of tuples accessed - - A few requests, for example, SELECT, can retrieve - multiple tuples. This factor is usually less - important than the others. - * - WAL settings - - The important setting for the write-ahead log is - :ref:`wal_mode `. - If the setting causes no writing or - delayed writing, this factor is unimportant. If the - setting causes every data-change request to wait - for writing to finish on a slow device, this factor - is more important than all the others. - - -Data schema description ------------------------ - -In Tarantool, the use of a data schema is optional. - -When creating a :term:`space `, you do not have to define a data schema. In this case, -the tuples store random data. This rule does not apply to indexed fields. -Such fields must contain data of the same type. - -You can define a data schema when creating a space. Read more in the description of the -:doc:`/reference/reference_lua/box_schema/space_create` function. -If you have already created a space without specifying a data schema, you can do it later using -:doc:`/reference/reference_lua/box_space/format`. - -After the data schema is defined, all the data is validated by type. Before any insert or update, -you will get an error if the data types do not match. - -We recommend using a data schema because it helps avoid mistakes. - -In Tarantool, you can define a data schema in two different ways. - -Data schema description in a code file -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The code file is usually called ``init.lua`` and contains the following schema description: - -.. code:: lua - - box.cfg() - - users = box.schema.create_space('users', { if_not_exists = true }) - users:format({{ name = 'user_id', type = 'number'}, { name = 'fullname', type = 'string'}}) - - users:create_index('pk', { parts = { { field = 'user_id', type = 'number'}}}) - -This is quite simple: when you run tarantool, it executes this code and creates -a data schema. To run this file, use: - -.. code:: bash - - tarantool init.lua - -However, it may seem complicated if you do not plan to dive deep into the Lua language and its syntax. - -Possible difficulty: the snippet above has a function call with a colon: ``users:format``. -It is used to pass the ``users`` variable as the first argument -of the ``format`` function. -This is similar to ``self`` in object-based languages. - -So it might be more convenient for you to describe the data schema with YAML. - -.. _data-schema-ddl: - -Data schema description using the DDL module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The `DDL module `_ allows you to describe a data schema -in the YAML format in a declarative way. - -The schema would look something like this: - -.. code-block:: yaml - - spaces: - users: - engine: memtx - is_local: false - temporary: false - format: - - {name: user_id, type: uuid, is_nullable: false} - - {name: fullname, type: string, is_nullable: false} - - {name: bucket_id, type: unsigned, is_nullable: false} - indexes: - - name: user_id - unique: true - parts: [{path: user_id, type: uuid, is_nullable: false}] - type: HASH - - name: bucket_id - unique: false - parts: [{path: bucket_id, type: unsigned, is_nullable: false}] - type: TREE - sharding_key: [user_id] - sharding_func: test_module.sharding_func - -This alternative is simpler to use, and you do not have to dive deep into Lua. - -``DDL`` is a built-in -:doc:`Cartridge ` module. -Cartridge is a cluster solution for Tarantool. In its WebUI, there is a separate tab -called "Code". On this tab, in the ``schema.yml`` file, you can define the schema, check its correctness, -and apply it to the whole cluster. - -If you do not use Cartridge, you can still use the DDL module: -put the following Lua code into the file that you use to run Tarantool. -This file is usually called ``init.lua``. - -.. code:: lua - - local yaml = require('yaml') - local ddl = require('ddl') - - box.cfg{} - - local fh = io.open('ddl.yml', 'r') - local schema = yaml.decode(fh:read('*all')) - fh:close() - local ok, err = ddl.check_schema(schema) - if not ok then - print(err) - end - local ok, err = ddl.set_schema(schema) - if not ok then - print(err) - end - -.. WARNING:: - - It is forbidden to modify the data schema in DDL after it has been applied. - For migration, there are different scenarios described below. - - -.. _migrations: - -Migrations ----------- - -**Migration** refers to any change in a data schema: adding/removing a field, -creating/dropping an index, changing a field format, etc. - -In Tarantool, there are two types of schema migration -that do not require data migration: - -- adding a field to the end of a space - -- creating an index - -.. note:: - - Check the `Upgrading space schema `__ - section in the Enterprise version. With the help of ``space:upgrade()`` feature, - you can enable compression and migrate, including already created tuples. - - -Adding a field to the end of a space -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can add a field as follows: - -.. code:: lua - - local users = box.space.users - local fmt = users:format() - - table.insert(fmt, { name = 'age', type = 'number', is_nullable = true }) - users:format(fmt) - -Note that the field must have the ``is_nullable`` parameter. Otherwise, -an error will occur. - -After creating a new field, you probably want to fill it with data. -The `tarantool/moonwalker `_ -module is useful for this task. -The README file describes how to work with this module. - -Creating an index -~~~~~~~~~~~~~~~~~ - -Index creation is described in the -:doc:`/reference/reference_lua/box_space/create_index` method. - -.. _other-migrations: - -Other types of migrations -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Other types of migrations are also allowed, but it would be more difficult to -maintain data consistency. - -Migrations are possible in two cases: - -- When Tarantool starts, and no client uses the database yet - -- During request processing, when active clients are already using the database - -For the first case, it is enough to write and test the migration code. -The most difficult task is to migrate data when there are active clients. -You should keep it in mind when you initially design the data schema. - -We identify the following problems if there are active clients: - -- Associated data can change atomically. - -- The system should be able to transfer data using both the new schema and the old one. - -- When data is being transferred to a new space, data access should consider - that the data might be in one space or another. - -- Write requests must not interfere with the migration. - A common approach is to write according to the new data schema. - -These issues may or may not be relevant depending on your application and -its availability requirements. - -What you need to know when writing complex migrations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Tarantool has a transaction mechanism. It is useful when writing a migration, -because it allows you to work with the data atomically. But before using -the transaction mechanism, you should explore its limitations. - -For details, see the section about :doc:`transactions `. - -How you can apply migration -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The migration code is executed on a running Tarantool instance. -Important: no method guarantees you transactional application of migrations -on the whole cluster. - -**Method 1**: include migrations in the application code - -This is quite simple: when you reload the code, the data is migrated at the right moment, -and the database schema is updated. -However, this method may not work for everyone. -You may not be able to restart Tarantool or update the code using the hot-reload mechanism. - -**Method 2**: tarantool/migrations (only for a Tarantool Cartridge cluster) - -This method is described in the README file of the -`tarantool/migrations `_ module. - -.. note:: - - There are also two other methods that we **do not recommend**, - but you may find them useful for one reason or another. - - **Method 3**: the ``tarantoolctl`` utility - - The ``tarantoolctl`` utility ships with Tarantool. - Connect to the necessary instance using ``tarantoolctl connect``. - - .. code:: console - - $ tarantoolctl connect admin:password@localhost:3301 - - - If your migration is written in a Lua file, you can execute it - using ``dofile()``. Call this function and specify the path to the - migration file as the first argument. It looks like this: - - .. code-block:: tarantoolsession - - tarantool> dofile('0001-delete-space.lua') - --- - ... - - - (or) Copy the migration script code, - paste it into the console, and run it. - - **Method 4**: applying migration with Ansible - - If you use the `Ansible role `_ - to deploy a Tarantool cluster, you can use ``eval``. - You can find more information about it - `in the Ansible role documentation `_. diff --git a/doc/book/box/index.rst b/doc/book/box/index.rst index 063ff1a785..ec5d6cde48 100644 --- a/doc/book/box/index.rst +++ b/doc/book/box/index.rst @@ -13,9 +13,9 @@ This chapter contains the following sections: :maxdepth: 2 :numbered: 0 - data_model - atomic - authentication - triggers + ../../concepts/data_model/index + ../../concepts/atomic + ../admin/access_control + ../../concepts/triggers limitations - engines/index + ../../concepts/engines/index diff --git a/doc/book/index.rst b/doc/book/index.rst index 7ec69b17e9..0ad7da7169 100644 --- a/doc/book/index.rst +++ b/doc/book/index.rst @@ -12,11 +12,11 @@ User's Guide intro ../getting_started/index + ../how-to/index + ../concepts/index box/index cartridge/index - app_server/index admin/index - replication/index monitoring/index connectors ../reference/reference_sql/index diff --git a/doc/book/replication/1_1.rst b/doc/book/replication/1_1.rst deleted file mode 100644 index cab684ac08..0000000000 --- a/doc/book/replication/1_1.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. code-block:: tarantoolsession - - $ # Terminal 1 - $ mkdir -p ~/tarantool_test_node_1 - $ cd ~/tarantool_test_node_1 - $ rm -R ./* - $ ~/tarantool/src/tarantool - $ ~/tarantool/src/tarantool: version 1.7.0-1724-g033ed69 - type 'help' for interactive help - tarantool> box.cfg{listen = 3301} - <... ...> - tarantool> box.schema.user.create('replicator', {password = 'password'}) - <...> I> creating ./00000000000000000000.xlog.inprogress' - --- - ... - tarantool> box.schema.user.grant('replicator','execute','role','replication') - --- - ... - tarantool> box.space._cluster:select({0}, {iterator = 'GE'}) - --- - - - [1, '6190d919-1133-4452-b123-beca0b178b32'] - ... diff --git a/doc/book/replication/1_2.rst b/doc/book/replication/1_2.rst deleted file mode 100644 index ae9fe8ed66..0000000000 --- a/doc/book/replication/1_2.rst +++ /dev/null @@ -1,3 +0,0 @@ -.. code-block:: console - - $ diff --git a/doc/book/replication/2_1.rst b/doc/book/replication/2_1.rst deleted file mode 100644 index 8a56ebfd19..0000000000 --- a/doc/book/replication/2_1.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. code-block:: tarantoolsession - - $ # Terminal 1 - $ mkdir -p ~/tarantool_test_node_1 - <... ...> - tarantool> box.space._cluster:select({0}, {iterator = 'GE'}) - --- - - - [1, '6190d919-1133-4452-b123-beca0b178b32'] - ... - tarantool> - <...> [11031] relay/127.0.0.1:58734/101/main I> recovery start - <...> [11031] relay/127.0.0.1:58734/101/main I> recovering from `./00000000000000000000.snap' - <...> [11031] relay/127.0.0.1:58734/101/main I> snapshot sent - <...> [11031] relay/127.0.0.1:58734/101/main I> recover from `./00000000000000000000.xlog' - <...> [11031] relay/127.0.0.1:58734/101/main recovery.cc:211 W> file - `./00000000000000000000.xlog` wasn't correctly closed - <...> [11031] relay/127.0.0.1:58734/102/main I> recover from `./00000000000000000000.xlog' diff --git a/doc/book/replication/2_2.rst b/doc/book/replication/2_2.rst deleted file mode 100644 index 11401c7fa3..0000000000 --- a/doc/book/replication/2_2.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. code-block:: tarantoolsession - - $ # Terminal 2 - $ mkdir -p ~/tarantool_test_node_2 - $ cd ~/tarantool_test_node_2 - $ rm -R ./* - $ ~/tarantool/src/tarantool - /home/username/tarantool/src/tarantool: version 1.7.0-1724-g033ed69 - type 'help' for interactive help - tarantool> box.cfg{ - > listen = 3302, - > replication = 'replicator:password@localhost:3301' - > } - <...> - <...> [11243] main/101/interactive I> mapping 1073741824 bytes for tuple arena... - <...> [11243] main/101/interactive C> starting replication from localhost:3301 - <...> [11243] main/102/applier/localhost:3301 I> connected to 1.7.0 at 127.0.0.1:3301 - <...> [11243] main/102/applier/localhost:3301 I> authenticated - <...> [11243] main/102/applier/localhost:3301 I> downloading a snapshot from 127.0.0.1:3301 - <...> [11243] main/102/applier/localhost:3301 I> done - <...> [11243] snapshot/101/main I> creating `./00000000000000000000.snap.inprogress' - <...> [11243] snapshot/101/main I> saving snapshot `./00000000000000000000.snap.inprogress' - <...> [11243] snapshot/101/main I> done - <...> [11243] iproto I> binary: started - <...> [11243] iproto I> binary: bound to 0.0.0.0:3302 - <...> [11243] wal/101/main I> creating `./00000000000000000000.xlog.inprogress' - <...> [11243] main/101/interactive I> ready to accept requests - tarantool> box.space._cluster:select({0}, {iterator = 'GE'}) - - - [1, '6190d919-1133-4452-b123-beca0b178b32'] - - [2, '236230b8-af3e-406b-b709-15a60b44c20c'] - ... diff --git a/doc/book/replication/3_1.rst b/doc/book/replication/3_1.rst deleted file mode 100644 index 29136132c5..0000000000 --- a/doc/book/replication/3_1.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - tarantool> - tarantool> - <...> [11031] relay/127.0.0.1:58734/101/main I> recovery start - <...> [11031] relay/127.0.0.1:58734/101/main I> recovering from `./00000000000000000000.snap' - <...> [11031] relay/127.0.0.1:58734/101/main I> snapshot sent - <...> [11031] relay/127.0.0.1:58734/101/main I> recover from `./00000000000000000000.xlog' - <...> [11031] relay/127.0.0.1:58734/101/main recovery.cc:211 W> file - `./00000000000000000000.xlog` wasn't correctly closed - <...> [11031] relay/127.0.0.1:58734/102/main I> recover from `./00000000000000000000.xlog' - tarantool> s = box.schema.space.create('tester') - --- - ... - tarantool> i = s:create_index('primary', {}) - --- - ... - tarantool> s:insert{1, 'Tuple inserted on Terminal #1'} - --- - - [1, 'Tuple inserted on Terminal #1'] - ... diff --git a/doc/book/replication/3_2.rst b/doc/book/replication/3_2.rst deleted file mode 100644 index 11401c7fa3..0000000000 --- a/doc/book/replication/3_2.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. code-block:: tarantoolsession - - $ # Terminal 2 - $ mkdir -p ~/tarantool_test_node_2 - $ cd ~/tarantool_test_node_2 - $ rm -R ./* - $ ~/tarantool/src/tarantool - /home/username/tarantool/src/tarantool: version 1.7.0-1724-g033ed69 - type 'help' for interactive help - tarantool> box.cfg{ - > listen = 3302, - > replication = 'replicator:password@localhost:3301' - > } - <...> - <...> [11243] main/101/interactive I> mapping 1073741824 bytes for tuple arena... - <...> [11243] main/101/interactive C> starting replication from localhost:3301 - <...> [11243] main/102/applier/localhost:3301 I> connected to 1.7.0 at 127.0.0.1:3301 - <...> [11243] main/102/applier/localhost:3301 I> authenticated - <...> [11243] main/102/applier/localhost:3301 I> downloading a snapshot from 127.0.0.1:3301 - <...> [11243] main/102/applier/localhost:3301 I> done - <...> [11243] snapshot/101/main I> creating `./00000000000000000000.snap.inprogress' - <...> [11243] snapshot/101/main I> saving snapshot `./00000000000000000000.snap.inprogress' - <...> [11243] snapshot/101/main I> done - <...> [11243] iproto I> binary: started - <...> [11243] iproto I> binary: bound to 0.0.0.0:3302 - <...> [11243] wal/101/main I> creating `./00000000000000000000.xlog.inprogress' - <...> [11243] main/101/interactive I> ready to accept requests - tarantool> box.space._cluster:select({0}, {iterator = 'GE'}) - - - [1, '6190d919-1133-4452-b123-beca0b178b32'] - - [2, '236230b8-af3e-406b-b709-15a60b44c20c'] - ... diff --git a/doc/book/replication/4_1.rst b/doc/book/replication/4_1.rst deleted file mode 100644 index 29136132c5..0000000000 --- a/doc/book/replication/4_1.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - tarantool> - tarantool> - <...> [11031] relay/127.0.0.1:58734/101/main I> recovery start - <...> [11031] relay/127.0.0.1:58734/101/main I> recovering from `./00000000000000000000.snap' - <...> [11031] relay/127.0.0.1:58734/101/main I> snapshot sent - <...> [11031] relay/127.0.0.1:58734/101/main I> recover from `./00000000000000000000.xlog' - <...> [11031] relay/127.0.0.1:58734/101/main recovery.cc:211 W> file - `./00000000000000000000.xlog` wasn't correctly closed - <...> [11031] relay/127.0.0.1:58734/102/main I> recover from `./00000000000000000000.xlog' - tarantool> s = box.schema.space.create('tester') - --- - ... - tarantool> i = s:create_index('primary', {}) - --- - ... - tarantool> s:insert{1, 'Tuple inserted on Terminal #1'} - --- - - [1, 'Tuple inserted on Terminal #1'] - ... diff --git a/doc/book/replication/4_2.rst b/doc/book/replication/4_2.rst deleted file mode 100644 index 8e39e6fb1c..0000000000 --- a/doc/book/replication/4_2.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - tarantool> box.space._cluster:select({0}, {iterator = 'GE'}) - - - [1, '6190d919-1133-4452-b123-beca0b178b32'] - - [2, '236230b8-af3e-406b-b709-15a60b44c20c'] - ... - tarantool> s = box.space.tester - --- - ... - tarantool> s:select({1}, {iterator = 'GE'}) - --- - - - [1, 'Tuple inserted on Terminal #1'] - ... - tarantool> s:insert{2, 'Tuple inserted on Terminal #2'} - --- - - [2, 'Tuple inserted on Terminal #2'] - ... diff --git a/doc/book/replication/5_1.rst b/doc/book/replication/5_1.rst deleted file mode 100644 index b9bd04117f..0000000000 --- a/doc/book/replication/5_1.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - tarantool> s:insert{1, 'Tuple inserted on Terminal #1'} - --- - - [1, 'Tuple inserted on Terminal #1'] - ... - tarantool> os.exit() - $ ls -l ~/tarantool_test_node_1 - total 8 - -rw-rw-r-- 1 4925 May 5 11:12 00000000000000000000.snap - -rw-rw-r-- 1 634 May 5 11:45 00000000000000000000.xlog - $ ls -l ~/tarantool_test_node_2/ - total 8 - -rw-rw-r-- 1 4925 May 5 11:20 00000000000000000000.snap - -rw-rw-r-- 1 704 May 5 11:38 00000000000000000000.xlog - $ diff --git a/doc/book/replication/5_2.rst b/doc/book/replication/5_2.rst deleted file mode 100644 index 104deefbc1..0000000000 --- a/doc/book/replication/5_2.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - tarantool> s:select({1}, {iterator = 'GE'}) - --- - - - [1, 'Tuple inserted on Terminal #1'] - ... - tarantool> s:insert{2, 'Tuple inserted on Terminal #2'} - --- - - [2, 'Tuple inserted on Terminal #2'] - ... - tarantool> - <...> [25579] main/103/replica/localhost:3301 I> can't read row - <...> [25579] main/103/replica/localhost:3301 !> SystemError - unexpected EOF when reading from socket, - called on fd 10, aka 127.0.0.1:50884, peer of 127.0.0.1:3301: Broken pipe - <...> [25579] main/103/replica/localhost:3301 I> will retry every 1 second diff --git a/doc/book/replication/6_1.rst b/doc/book/replication/6_1.rst deleted file mode 100644 index b9bd04117f..0000000000 --- a/doc/book/replication/6_1.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - tarantool> s:insert{1, 'Tuple inserted on Terminal #1'} - --- - - [1, 'Tuple inserted on Terminal #1'] - ... - tarantool> os.exit() - $ ls -l ~/tarantool_test_node_1 - total 8 - -rw-rw-r-- 1 4925 May 5 11:12 00000000000000000000.snap - -rw-rw-r-- 1 634 May 5 11:45 00000000000000000000.xlog - $ ls -l ~/tarantool_test_node_2/ - total 8 - -rw-rw-r-- 1 4925 May 5 11:20 00000000000000000000.snap - -rw-rw-r-- 1 704 May 5 11:38 00000000000000000000.xlog - $ diff --git a/doc/book/replication/6_2.rst b/doc/book/replication/6_2.rst deleted file mode 100644 index e1941b7798..0000000000 --- a/doc/book/replication/6_2.rst +++ /dev/null @@ -1,23 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - tarantool> s:insert{2, 'Tuple inserted on Terminal #2'} - --- - - [2, 'Tuple inserted on Terminal #2'] - ... - tarantool> - <...> [11243] main/105/applier/localhost:3301 I> can't read row - <...> [11243] main/105/applier/localhost:3301 coio.cc:352 !> SystemError - unexpected EOF when reading from socket, - called on fd 6, aka 127.0.0.1:58734, peer of 127.0.0.1:3301: Broken pipe - <...> [11243] main/105/applier/localhost:3301 I> will retry every 1 second - tarantool> box.space.tester:select({0}, {iterator = 'GE'}) - --- - - - [1, 'Tuple inserted on Terminal #1'] - - [2, 'Tuple inserted on Terminal #2'] - ... - tarantool> box.space.tester:insert{3, 'Another'} - --- - - [3, 'Another'] - ... - diff --git a/doc/book/replication/7_1.rst b/doc/book/replication/7_1.rst deleted file mode 100644 index ebdcf99f93..0000000000 --- a/doc/book/replication/7_1.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - tarantool> s:insert{1, 'Tuple inserted on Terminal #1'} - --- - - [1, 'Tuple inserted on Terminal #1'] - ... - tarantool> os.exit() - $ ls -l ~/tarantool_test_node_1 - total 8 - -rw-rw-r-- 1 4925 May 5 11:12 00000000000000000000.snap - -rw-rw-r-- 1 634 May 5 11:45 00000000000000000000.xlog - $ ls -l ~/tarantool_test_node_2/ - total 8 - -rw-rw-r-- 1 4925 May 5 11:20 00000000000000000000.snap - -rw-rw-r-- 1 704 May 5 11:38 00000000000000000000.xlog - $ ~/tarantool/src/tarantool - <...> - tarantool> box.cfg{listen = 3301} - <...> [22612] main/101/interactive I> ready to accept requests - <... ...> - tarantool> box.space.tester:select({0}, {iterator = 'GE'}) - - - [1, 'Tuple inserted on Terminal #1'] - ... diff --git a/doc/book/replication/7_2.rst b/doc/book/replication/7_2.rst deleted file mode 100644 index 5c69991e5b..0000000000 --- a/doc/book/replication/7_2.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - tarantool> s:insert{2, 'Tuple inserted on Terminal #2'} - --- - - [2, 'Tuple inserted on Terminal #2'] - ... - tarantool> - <...> [25579] main/103/replica/localhost:3301 I> can't read row - <...> [25579] main/103/replica/localhost:3301 !> SystemError - unexpected EOF when reading from socket, - called on fd 10, aka 127.0.0.1:50884, peer of 127.0.0.1:3301: Broken pipe - <...> [25579] main/103/replica/localhost:3301 I> will retry every 1 second - tarantool> box.space.tester:select({0}, {iterator = 'GE'}) - --- - - - [1, 'Tuple inserted on Terminal #1'] - - [2, 'Tuple inserted on Terminal #2'] - ... - tarantool> box.space.tester:insert{3, 'Another'} - --- - - [3, 'Another'] - ... - <...> [11243] main/105/applier/localhost:3301 I> connected to 1.7.0 at 127.0.0.1:3301 - <...> [11243] main/105/applier/localhost:3301 I> authenticated - diff --git a/doc/book/replication/8_1.rst b/doc/book/replication/8_1.rst deleted file mode 100644 index 0875b5861c..0000000000 --- a/doc/book/replication/8_1.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - $ ~/tarantool/src/tarantool - <...> - tarantool> box.cfg{listen = 3301} - <...> [22612] main/101/interactive I> ready to accept requests - <... ...> - tarantool> box.space.tester:select({0}, {iterator = 'GE'}) - --- - - - [1, 'Tuple inserted on Terminal #1'] - ... - tarantool> box.cfg{ - > replication = 'replicator:password@localhost:3302' - > } - [28987] main/101/interactive C> starting replication from localhost:3302 - --- - ... - [22612] main/101/interactive C> starting replication from localhost:3302 - [22612] main/101/interactive I> set 'replication' configuration - option to "replicator:password@localhost:3302" - [22612] main/104/applier/localhost:3302 I> connected to 1.7.0 at 127.0.0.1:3302 - [22612] main/104/applier/localhost:3302 I> authenticated - [22612] wal/101/main I> creating `./00000000000000000008.xlog.inprogress' - [22612] relay/127.0.0.1:33510/102/main I> done `./00000000000000000000.xlog' - [22612] relay/127.0.0.1:33510/102/main I> recover from `./00000000000000000008.xlog' - tarantool> box.space.tester:select({0}, {iterator = 'GE'}) - --- - - - [1, 'Tuple inserted on Terminal #1'] - - [2, 'Tuple inserted on Terminal #2'] - - [3, 'Another'] - ... - diff --git a/doc/book/replication/8_2.rst b/doc/book/replication/8_2.rst deleted file mode 100644 index 328d423bdd..0000000000 --- a/doc/book/replication/8_2.rst +++ /dev/null @@ -1,29 +0,0 @@ -.. code-block:: tarantoolsession - - <... ...> - tarantool> s:insert{2, 'Tuple inserted on Terminal #2'} - --- - - [2, 'Tuple inserted on Terminal #2'] - ... - tarantool> - <...> [25579] main/103/replica/localhost:3301 I> can't read row - <...> [25579] main/103/replica/localhost:3301 !> SystemError - unexpected EOF when reading from socket, - called on fd 10, aka 127.0.0.1:50884, peer of 127.0.0.1:3301: Broken pipe - <...> [25579] main/103/replica/localhost:3301 I> will retry every 1 second - tarantool> box.space.tester:select({0}, {iterator = 'GE'}) - --- - - - [1, 'Tuple inserted on Terminal #1'] - - [2, 'Tuple inserted on Terminal #2'] - ... - tarantool> box.space.tester:insert{3, 'Another'} - --- - - [3, 'Another'] - ... - <...> [11243] main/105/applier/localhost:3301 I> connected to 1.7.0 at 127.0.0.1:3301 - <...> [11243] main/105/applier/localhost:3301 I> authenticated - tarantool> - <...> [11243] relay/127.0.0.1:36150/101/main I> recover from `./00000000000000000000.xlog' - <...> [11243] relay/127.0.0.1:36150/101/main recovery.cc:211 W> file - `./00000000000000000000.xlog` wasn't correctly closed - <...> [11243] relay/127.0.0.1:36150/102/main I> recover from `./00000000000000000000.xlog' diff --git a/doc/book/replication/index.rst b/doc/book/replication/index.rst deleted file mode 100644 index dbc0e082a3..0000000000 --- a/doc/book/replication/index.rst +++ /dev/null @@ -1,29 +0,0 @@ -:noindex: -:fullwidth: - -.. _replication: - -******************************************************************************** -Replication -******************************************************************************** - -Replication allows multiple Tarantool instances to work on copies of the same -databases. The databases are kept in sync because each instance can communicate -its changes to all the other instances. - -This chapter includes the following sections: - -.. toctree:: - :maxdepth: 2 - :numbered: 0 - - repl_architecture - repl_bootstrap - repl_add_instances - repl_remove_instances - repl_monitoring - repl_recover - repl_reseed - repl_problem_solving - repl_sync - repl_leader_elect diff --git a/doc/book/replication/repl_add_instances.rst b/doc/book/replication/repl_add_instances.rst deleted file mode 100644 index 237dc39e62..0000000000 --- a/doc/book/replication/repl_add_instances.rst +++ /dev/null @@ -1,419 +0,0 @@ -.. _replication-add_instances: - -================================================================================ -Adding instances -================================================================================ - -.. _replication-add_replica: - --------------------------------------------------------------------------------- -Adding a replica --------------------------------------------------------------------------------- - -.. image:: mr-1m-2r-mesh-add.png - :align: center - -To add a second **replica** instance to the **master-replica** set from our -:ref:`bootstrapping example `, we need an -analog of the instance file that we created for the first replica in that set: - -.. code-block:: lua - - -- instance file for replica #2 - box.cfg{ - listen = 3301, - replication = {'replicator:password@192.168.0.101:3301', -- master URI - 'replicator:password@192.168.0.102:3301', -- replica #1 URI - 'replicator:password@192.168.0.103:3301'}, -- replica #2 URI - read_only = true - } - box.once("schema", function() - box.schema.user.create('replicator', {password = 'password'}) - box.schema.user.grant('replicator', 'replication') -- grant replication role - box.schema.space.create("test") - box.space.test:create_index("primary") - print('box.once executed on replica #2') - end) - -Here we add the URI of replica #2 to the :ref:`replication ` -parameter, so now it contains three URIs. - -After we launch the new replica instance, it gets connected to the master -instance and retrieves the master's write-ahead-log and snapshot files: - -.. code-block:: console - - $ # launching replica #2 - $ tarantool replica2.lua - 2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> version 1.7.4-52-g980d30092 - 2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> log level 5 - 2017-06-14 14:54:33.928 [46945] main/101/replica2.lua I> mapping 268435456 bytes for tuple arena... - 2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301 - 2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> authenticated - 2017-06-14 14:54:33.930 [46945] main/101/replica2.lua I> bootstrapping replica from 192.168.0.101:3301 - 2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> initial data received - 2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> final data received - 2017-06-14 14:54:33.934 [46945] snapshot/101/main I> saving snapshot `/var/lib/tarantool/replica2/00000000000000000010.snap.inprogress' - 2017-06-14 14:54:33.934 [46945] snapshot/101/main I> done - 2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> vinyl checkpoint done - 2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> ready to accept requests - 2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> set 'read_only' configuration option to true - 2017-06-14 14:54:33.936 [46945] main C> entering the event loop - -Since we are adding a read-only instance, there is no need to dynamically -update the ``replication`` parameter on the other running instances. This update -would be required if we :ref:`added a master instance `. - -However, we recommend specifying the URI of replica #3 in all instance files of the -replica set. This will keep all the files consistent with each other and with -the current replication topology, and so will help to avoid configuration errors -in case of further configuration updates and replica set restart. - -.. _replication-add_master: - --------------------------------------------------------------------------------- -Adding a master --------------------------------------------------------------------------------- - -.. image:: mm-3m-mesh-add.png - :align: center - -To add a third master instance to the **master-master** set from our -:ref:`bootstrapping example `, we need an -analog of the instance files that we created to bootstrap the other master -instances in that set: - -.. code-block:: lua - - -- instance file for master #3 - box.cfg{ - listen = 3301, - replication = {'replicator:password@192.168.0.101:3301', -- master#1 URI - 'replicator:password@192.168.0.102:3301', -- master#2 URI - 'replicator:password@192.168.0.103:3301'}, -- master#3 URI - read_only = true, -- temporarily read-only - } - box.once("schema", function() - box.schema.user.create('replicator', {password = 'password'}) - box.schema.user.grant('replicator', 'replication') -- grant replication role - box.schema.space.create("test") - box.space.test:create_index("primary") - end) - -Here we make the following changes: - -* Add the URI of master #3 to the :ref:`replication ` - parameter. -* Temporarily specify :ref:`read_only=true ` to disable - data-change operations on the instance. After launch, master #3 will act as a - replica until it retrieves all data from the other masters in the replica set. - -After we launch master #3, it gets connected to the other master -instances and retrieves their write-ahead-log and snapshot files: - -.. code-block:: console - - $ # launching master #3 - $ tarantool master3.lua - 2017-06-14 17:10:00.556 [47121] main/101/master3.lua C> version 1.7.4-52-g980d30092 - 2017-06-14 17:10:00.557 [47121] main/101/master3.lua C> log level 5 - 2017-06-14 17:10:00.557 [47121] main/101/master3.lua I> mapping 268435456 bytes for tuple arena... - 2017-06-14 17:10:00.559 [47121] iproto/101/main I> binary: bound to [::]:3301 - 2017-06-14 17:10:00.559 [47121] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301 - 2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.102:3301 - 2017-06-14 17:10:00.559 [47121] main/106/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.103:3301 - 2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> authenticated - 2017-06-14 17:10:00.559 [47121] main/101/master3.lua I> bootstrapping replica from 192.168.0.102:3301 - 2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> initial data received - 2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> final data received - 2017-06-14 17:10:00.562 [47121] snapshot/101/main I> saving snapshot `/Users/e.shebunyaeva/work/tarantool-test-repl/master3_dir/00000000000000000009.snap.inprogress' - 2017-06-14 17:10:00.562 [47121] snapshot/101/main I> done - 2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> vinyl checkpoint done - 2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> ready to accept requests - 2017-06-14 17:10:00.565 [47121] main/101/master3.lua I> set 'read_only' configuration option to true - 2017-06-14 17:10:00.565 [47121] main C> entering the event loop - 2017-06-14 17:10:00.565 [47121] main/104/applier/replicator@192.168.0.10 I> authenticated - -Next, we add the URI of master #3 to the ``replication`` parameter on the existing two -masters. Replication-related parameters are dynamic, so we only need to make a -``box.cfg{}`` request on each of the running instances: - -.. code-block:: tarantoolsession - - # adding master #3 URI to replication sources - tarantool> box.cfg{replication = - > {'replicator:password@192.168.0.101:3301', - > 'replicator:password@192.168.0.102:3301', - > 'replicator:password@192.168.0.103:3301'}} - --- - ... - -When master #3 catches up with the other masters' state, we can disable -read-only mode for this instance: - -.. code-block:: tarantoolsession - - # making master #3 a real master - tarantool> box.cfg{read_only=false} - --- - ... - -We also recommend to specify master #3 URI in all instance files in order to -keep all the files consistent with each other and with the current replication -topology. - -.. _replication-orphan_status: - --------------------------------------------------------------------------------- -Orphan status --------------------------------------------------------------------------------- - -Starting with Tarantool version 1.9, there is a change to the -procedure when an instance joins a replica set. -During ``box.cfg()`` the instance will try to join all masters listed -in :ref:`box.cfg.replication `. -If the instance does not succeed with at least -the number of masters specified in -:ref:`replication_connect_quorum `, -then it will switch to **orphan status**. -While an instance is in orphan status, it is read-only. - -To "join" a master, a replica instance must "connect" to the -master node and then "sync". - -"Connect" means contact the master over the physical network -and receive acknowledgment. If there is no acknowledgment after -:ref:`box.replication_connect_timeout ` -seconds (usually 4 seconds), and retries fail, then the connect step fails. - -"Sync" means receive updates -from the master in order to make a local database copy. -Syncing is complete when the replica has received all the -updates, or at least has received enough updates that the replica's lag -(see -:ref:`replication.upstream.lag ` -in ``box.info()``) -is less than or equal to the number of seconds specified in -:ref:`box.cfg.replication_sync_lag `. -If ``replication_sync_lag`` is unset (nil) or set to TIMEOUT_INFINITY, then -the replica skips the "sync" state and switches to "follow" immediately. - -In order to leave orphan mode you need to sync with a sufficient number -(:ref:`replication_connect_quorum `) of -instances. To do so, you may either: - -* Set :ref:`replication_connect_quorum ` - to a lower value. -* Reset ``box.cfg.replication`` to exclude instances that cannot be reached - or synced with. -* Set ``box.cfg.replication`` to ``""`` (empty string). - -The following situations are possible. - -.. _replication-leader: - -**Situation 1: bootstrap** - -Here ``box.cfg{}`` is being called for the first time. -A replica is joining but no replica set exists yet. - - 1. Set status to 'orphan'. - 2. Try to connect to all nodes from ``box.cfg.replication``, - or to the number of nodes required by - :ref:`replication_connect_quorum `. - Retrying up to 3 times in 30 seconds is possible because this is bootstrap, - :ref:`replication_connect_timeout ` - is overridden. - - 3. Abort and throw an error if not connected to all nodes in ``box.cfg.replication`` or - :ref:`replication_connect_quorum `. - - 4. This instance might be elected as the replica set 'leader'. - Criteria for electing a leader include vclock value (largest is best), - and whether it is read-only or read-write (read-write is best unless there is no other choice). - The leader is the master that other instances must join. - The leader is the master that executes - :doc:`box.once() ` functions. - - 5. If this instance is elected as the replica set leader, - then - perform an "automatic bootstrap": - - a. Set status to 'running'. - b. Return from ``box.cfg{}``. - - Otherwise this instance will be a replica joining an existing replica set, - so: - - a. Bootstrap from the leader. - See examples in section :ref:`Bootstrapping a replica set `. - b. In background, sync with all the other nodes in the replication set. - -**Situation 2: recovery** - -Here ``box.cfg{}`` is not being called for the first time. -It is being called again in order to perform recovery. - - 1. Perform :ref:`recovery ` from the last local - snapshot and the WAL files. - - 2. Connect to at least - :ref:`replication_connect_quorum ` - nodes. If failed -- set status to 'orphan'. - (Attempts to sync will continue in the background and when/if they succeed - then 'orphan' will be changed to 'connected'.) - - 3. If connected - sync with all connected nodes, until the difference is not more than - :ref:`replication_sync_lag ` seconds. - -.. _replication-configuration_update: - -**Situation 3: configuration update** - -Here ``box.cfg{}`` is not being called for the first time. -It is being called again because some replication parameter -or something in the replica set has changed. - - 1. Try to connect to all nodes from ``box.cfg.replication``, - or to the number of nodes required by - :ref:`replication_connect_quorum `, - within the time period specified in - :ref:`replication_connect_timeout `. - - 2. Try to sync with the connected nodes, - within the time period specified in - :ref:`replication_sync_timeout `. - - 3. If earlier steps fail, change status to 'orphan'. - (Attempts to sync will continue in the background and when/if they succeed - then 'orphan' status will end.) - - 4. If earlier steps succeed, set status to 'running' (master) or 'follow' (replica). - -.. _replication-configuration_rebootstrap: - -**Situation 4: rebootstrap** - -Here ``box.cfg{}`` is not being called. The replica connected successfully -at some point in the past, and is now ready for an update from the master. -But the master cannot provide an update. -This can happen by accident, or more likely can happen because the replica -is slow (its :ref:`lag ` is large), -and the WAL (.xlog) files containing the -updates have been deleted. This is not crippling. The replica can discard -what it received earlier, and then ask for the master's latest snapshot -(.snap) file contents. Since it is effectively going through the bootstrap -process a second time, this is called "rebootstrapping". However, there has -to be one difference from an ordinary bootstrap -- the replica's -:ref:`replica id ` will remain the same. -If it changed, then the master would think that the replica is a -new addition to the cluster, and would maintain a record of an -instance ID of a replica that has ceased to exist. Rebootstrapping was -introduced in Tarantool version 1.10.2 and is completely automatic. - -.. _replication-server_startup: - --------------------------------------------------------------------------------- -Server startup with replication --------------------------------------------------------------------------------- - -In addition to the recovery process described in the -section :ref:`Recovery process `, the server must take -additional steps and precautions if :ref:`replication ` is enabled. - -Once again the startup procedure is initiated by the ``box.cfg{}`` request. -One of the ``box.cfg`` parameters may be -:ref:`replication ` which specifies replication -source(-s). We will refer to this replica, which is starting up due to ``box.cfg``, -as the "local" replica to distinguish it from the other replicas in a replica set, -which we will refer to as "distant" replicas. - -*If there is no snapshot .snap file and the* ``replication`` *parameter is empty and* -``cfg.read_only=false``: |br| -then the local replica assumes it is an unreplicated "standalone" instance, or is -the first replica of a new replica set. It will generate new UUIDs for -itself and for the replica set. The replica UUID is stored in the ``_cluster`` space; the -replica set UUID is stored in the ``_schema`` space. Since a snapshot contains all the -data in all the spaces, that means the local replica's snapshot will contain the -replica UUID and the replica set UUID. Therefore, when the local replica restarts on -later occasions, it will be able to recover these UUIDs when it reads the .snap -file. - -*If there is no snapshot .snap file and the* ``replication`` *parameter is empty -and* ``cfg.read_only=true``: |br| -it cannot be the first replica of a new replica set because the first replica -must be a master. Therefore an error message will occur: ER_BOOTSTRAP_READONLY. -To avoid this, change the setting for this (local) instance to ``read_only = false``, -or ensure that another (distant) instance starts first and has the local instance's -UUID in its ``_cluster`` space. In the latter case, if ER_BOOTSTRAP_READONLY still -occurs, set the local instance's -:ref:`box.replication_connect_timeout ` -to a larger value. - -*If there is no snapshot .snap file and the* ``replication`` *parameter is not empty -and the* ``_cluster`` *space contains no other replica UUIDs*: |br| -then the local replica assumes it is not a standalone instance, but is not yet part -of a replica set. It must now join the replica set. It will send its replica UUID to the -first distant replica which is listed in ``replication`` and which will act as a -master. This is called the "join request". When a distant replica receives a join -request, it will send back: - -(1) the distant replica's replica set UUID, -(2) the contents of the distant replica's .snap file. |br| - When the local replica receives this information, it puts the replica set UUID in - its ``_schema`` space, puts the distant replica's UUID and connection information - in its ``_cluster`` space, and makes a snapshot containing all the data sent by - the distant replica. Then, if the local replica has data in its WAL .xlog - files, it sends that data to the distant replica. The distant replica will - receive this and update its own copy of the data, and add the local replica's - UUID to its ``_cluster`` space. - -*If there is no snapshot .snap file and the* ``replication`` *parameter is not empty -and the* ``_cluster`` *space contains other replica UUIDs*: |br| -then the local replica assumes it is not a standalone instance, and is already part -of a replica set. It will send its replica UUID and replica set UUID to all the distant -replicas which are listed in ``replication``. This is called the "on-connect -handshake". When a distant replica receives an on-connect handshake: |br| - -(1) the distant replica compares its own copy of the replica set UUID to the one in - the on-connect handshake. If there is no match, then the handshake fails and - the local replica will display an error. -(2) the distant replica looks for a record of the connecting instance in its - ``_cluster`` space. If there is none, then the handshake fails. |br| - Otherwise the handshake is successful. The distant replica will read any new - information from its own .snap and .xlog files, and send the new requests to - the local replica. - -In the end, the local replica knows what replica set it belongs to, the distant -replica knows that the local replica is a member of the replica set, and both -replicas have the same database contents. - -.. _replication-vector: - -*If there is a snapshot file and replication source is not empty*: |br| -first the local replica goes through the recovery process described in the -previous section, using its own .snap and .xlog files. Then it sends a -"subscribe" request to all the other replicas of the replica set. The subscribe -request contains the server vector clock. The vector clock has a collection of -pairs 'server id, lsn' for every replica in the ``_cluster`` system space. Each -distant replica, upon receiving a subscribe request, will read its .xlog files' -requests and send them to the local replica if (lsn of .xlog file request) is -greater than (lsn of the vector clock in the subscribe request). After all the -other replicas of the replica set have responded to the local replica's subscribe -request, the replica startup is complete. - -The following temporary limitations applied for Tarantool versions earlier than -1.7.7: - -* The URIs in the ``replication`` parameter should all be in the same order on all replicas. - This is not mandatory but is an aid to consistency. -* The replicas of a replica set should be started up at slightly different times. - This is not mandatory but prevents a situation where each replica is waiting - for the other replica to be ready. - -The following limitation still applies for the current Tarantool version: - -* The maximum number of entries in the ``_cluster`` space is - :ref:`32 `. Tuples for - out-of-date replicas are not automatically re-used, so if this 32-replica - limit is reached, users may have to reorganize the ``_cluster`` space manually. diff --git a/doc/book/replication/repl_bootstrap.rst b/doc/book/replication/repl_bootstrap.rst deleted file mode 100644 index a452739762..0000000000 --- a/doc/book/replication/repl_bootstrap.rst +++ /dev/null @@ -1,374 +0,0 @@ -.. _replication-bootstrap: - -================================================================================ -Bootstrapping a replica set -================================================================================ - -.. _replication-master_replica_bootstrap: - --------------------------------------------------------------------------------- -Master-replica bootstrap --------------------------------------------------------------------------------- - -Let us first bootstrap a simple **master-replica** set containing two instances, -each located on its own machine. For easier administration, we make the -:ref:`instance files ` almost identical. - -.. image:: mr-1m-1r-twoway.png - :align: center - -Here is an example of the master's instance file: - -.. code-block:: lua - - -- instance file for the master - box.cfg{ - listen = 3301, - replication = {'replicator:password@192.168.0.101:3301', -- master URI - 'replicator:password@192.168.0.102:3301'}, -- replica URI - read_only = false - } - box.once("schema", function() - box.schema.user.create('replicator', {password = 'password'}) - box.schema.user.grant('replicator', 'replication') -- grant replication role - box.schema.space.create("test") - box.space.test:create_index("primary") - print('box.once executed on master') - end) - -where: - -* the ``box.cfg()`` :ref:`listen ` parameter defines a URI - (port 3301 in our example), on which the master can accept connections from - replicas. -* the ``box.cfg()`` :ref:`replication ` parameter - defines the URIs at which all instances in the replica set can accept connections. - It includes the replica's URI as well, although the replica is not a replication - source right now. This parameter is mandatory only for master-master or full-mesh - cluster setups. - - .. NOTE:: - - For security reasons, we recommend that administrators prevent unauthorized - replication sources by associating a password with every user that has a - replication :ref:`role `. That way, the :ref:`URI - ` for ``replication`` parameter must have the long form - ``username:password@host:port``. - -* the :ref:`read_only = false ` parameter setting enables - data-change operations on the instance and makes the instance act as a master, - not as a replica. *That is the only parameter setting in our instance files - that will differ.* -* the :doc:`box.once() ` function contains database initialization logic - that should be executed only once during the replica set lifetime. - -In this example, we create a space with a primary index, and a user for -replication purposes. We also say ``print('box.once executed on master')`` -so that it will later be visible on a console whether ``box.once()`` was executed. - -.. NOTE:: - - Replication requires privileges. We can grant privileges for accessing spaces - directly to the user who will start the instance. However, it is more usual - to grant privileges for accessing spaces to a - :ref:`role `, and then grant the role to the user who - will start the replica. - -Here we use Tarantool's predefined role named "replication" which by default -grants "read" privileges for all database objects ("universe"), and we can -change privileges for this role as required. - -In the replica's instance file, we set the ``read_only`` parameter to "true", and -say ``print('box.once executed on replica')`` so that later it will be visible -that ``box.once()`` was not executed more than once. -Otherwise the replica's instance file is identical to the master's instance file. - -.. code-block:: lua - - -- instance file for the replica - box.cfg{ - listen = 3301, - replication = {'replicator:password@192.168.0.101:3301', -- master URI - 'replicator:password@192.168.0.102:3301'}, -- replica URI - read_only = true - } - box.once("schema", function() - box.schema.user.create('replicator', {password = 'password'}) - box.schema.user.grant('replicator', 'replication') -- grant replication role - box.schema.space.create("test") - box.space.test:create_index("primary") - print('box.once executed on replica') - end) - -.. NOTE:: - - The replica does not inherit the master’s configuration parameters, such as - those making the :ref:`checkpoint daemon ` run on - the master. To get the same behavior, set the relevant parameters - explicitly so that they are the same on both master and replica. - -Now we can launch the two instances. The master... - -.. code-block:: console - - $ # launching the master - $ tarantool master.lua - 2017-06-14 14:12:03.847 [18933] main/101/master.lua C> version 1.7.4-52-g980d30092 - 2017-06-14 14:12:03.848 [18933] main/101/master.lua C> log level 5 - 2017-06-14 14:12:03.849 [18933] main/101/master.lua I> mapping 268435456 bytes for tuple arena... - 2017-06-14 14:12:03.859 [18933] iproto/101/main I> binary: bound to [::]:3301 - 2017-06-14 14:12:03.861 [18933] main/105/applier/replicator@192.168.0. I> can't connect to master - 2017-06-14 14:12:03.861 [18933] main/105/applier/replicator@192.168.0. coio.cc:105 !> SystemError connect, called on fd 14, aka 192.168.0.102:56736: Connection refused - 2017-06-14 14:12:03.861 [18933] main/105/applier/replicator@192.168.0. I> will retry every 1 second - 2017-06-14 14:12:03.861 [18933] main/104/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.101:3301 - 2017-06-14 14:12:19.878 [18933] main/105/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.102:3301 - 2017-06-14 14:12:19.879 [18933] main/101/master.lua I> initializing an empty data directory - 2017-06-14 14:12:19.908 [18933] snapshot/101/main I> saving snapshot `/var/lib/tarantool/master/00000000000000000000.snap.inprogress' - 2017-06-14 14:12:19.914 [18933] snapshot/101/main I> done - 2017-06-14 14:12:19.914 [18933] main/101/master.lua I> vinyl checkpoint done - 2017-06-14 14:12:19.917 [18933] main/101/master.lua I> ready to accept requests - 2017-06-14 14:12:19.918 [18933] main/105/applier/replicator@192.168.0. I> failed to authenticate - 2017-06-14 14:12:19.918 [18933] main/105/applier/replicator@192.168.0. xrow.cc:431 E> ER_LOADING: Instance bootstrap hasn't finished yet - box.once executed on master - 2017-06-14 14:12:19.920 [18933] main C> entering the event loop - -... (the display confirms that ``box.once()`` was executed on the master) -- and the replica: - -.. code-block:: console - - $ # launching the replica - $ tarantool replica.lua - 2017-06-14 14:12:19.486 [18934] main/101/replica.lua C> version 1.7.4-52-g980d30092 - 2017-06-14 14:12:19.486 [18934] main/101/replica.lua C> log level 5 - 2017-06-14 14:12:19.487 [18934] main/101/replica.lua I> mapping 268435456 bytes for tuple arena... - 2017-06-14 14:12:19.494 [18934] iproto/101/main I> binary: bound to [::]:3311 - 2017-06-14 14:12:19.495 [18934] main/104/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.101:3301 - 2017-06-14 14:12:19.495 [18934] main/105/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.102:3302 - 2017-06-14 14:12:19.496 [18934] main/104/applier/replicator@192.168.0. I> failed to authenticate - 2017-06-14 14:12:19.496 [18934] main/104/applier/replicator@192.168.0. xrow.cc:431 E> ER_LOADING: Instance bootstrap hasn't finished yet - -In both logs, there are messages saying that the replica was bootstrapped from the master: - -.. code-block:: console - - $ # bootstrapping the replica (from the master's log) - <...> - 2017-06-14 14:12:20.503 [18933] main/106/main I> initial data sent. - 2017-06-14 14:12:20.505 [18933] relay/[::ffff:192.168.0.101]:/101/main I> recover from `/var/lib/tarantool/master/00000000000000000000.xlog' - 2017-06-14 14:12:20.505 [18933] main/106/main I> final data sent. - 2017-06-14 14:12:20.522 [18933] relay/[::ffff:192.168.0.101]:/101/main I> recover from `/Users/e.shebunyaeva/work/tarantool-test-repl/master_dir/00000000000000000000.xlog' - 2017-06-14 14:12:20.922 [18933] main/105/applier/replicator@192.168.0. I> authenticated - -.. code-block:: console - - $ # bootstrapping the replica (from the replica's log) - <...> - 2017-06-14 14:12:20.498 [18934] main/104/applier/replicator@192.168.0. I> authenticated - 2017-06-14 14:12:20.498 [18934] main/101/replica.lua I> bootstrapping replica from 192.168.0.101:3301 - 2017-06-14 14:12:20.512 [18934] main/104/applier/replicator@192.168.0. I> initial data received - 2017-06-14 14:12:20.512 [18934] main/104/applier/replicator@192.168.0. I> final data received - 2017-06-14 14:12:20.517 [18934] snapshot/101/main I> saving snapshot `/var/lib/tarantool/replica/00000000000000000005.snap.inprogress' - 2017-06-14 14:12:20.518 [18934] snapshot/101/main I> done - 2017-06-14 14:12:20.519 [18934] main/101/replica.lua I> vinyl checkpoint done - 2017-06-14 14:12:20.520 [18934] main/101/replica.lua I> ready to accept requests - 2017-06-14 14:12:20.520 [18934] main/101/replica.lua I> set 'read_only' configuration option to true - 2017-06-14 14:12:20.520 [18934] main C> entering the event loop - -Notice that ``box.once()`` was executed only at the master, although we added -``box.once()`` to both instance files. - -We could as well launch the replica first: - -.. code-block:: console - - $ # launching the replica - $ tarantool replica.lua - 2017-06-14 14:35:36.763 [18952] main/101/replica.lua C> version 1.7.4-52-g980d30092 - 2017-06-14 14:35:36.765 [18952] main/101/replica.lua C> log level 5 - 2017-06-14 14:35:36.765 [18952] main/101/replica.lua I> mapping 268435456 bytes for tuple arena... - 2017-06-14 14:35:36.772 [18952] iproto/101/main I> binary: bound to [::]:3301 - 2017-06-14 14:35:36.772 [18952] main/104/applier/replicator@192.168.0. I> can't connect to master - 2017-06-14 14:35:36.772 [18952] main/104/applier/replicator@192.168.0. coio.cc:105 !> SystemError connect, called on fd 13, aka 192.168.0.101:56820: Connection refused - 2017-06-14 14:35:36.772 [18952] main/104/applier/replicator@192.168.0. I> will retry every 1 second - 2017-06-14 14:35:36.772 [18952] main/105/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.102:3301 - -... and the master later: - -.. code-block:: console - - $ # launching the master - $ tarantool master.lua - 2017-06-14 14:35:43.701 [18953] main/101/master.lua C> version 1.7.4-52-g980d30092 - 2017-06-14 14:35:43.702 [18953] main/101/master.lua C> log level 5 - 2017-06-14 14:35:43.702 [18953] main/101/master.lua I> mapping 268435456 bytes for tuple arena... - 2017-06-14 14:35:43.709 [18953] iproto/101/main I> binary: bound to [::]:3301 - 2017-06-14 14:35:43.709 [18953] main/105/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.102:3301 - 2017-06-14 14:35:43.709 [18953] main/104/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.101:3301 - 2017-06-14 14:35:43.709 [18953] main/101/master.lua I> initializing an empty data directory - 2017-06-14 14:35:43.721 [18953] snapshot/101/main I> saving snapshot `/var/lib/tarantool/master/00000000000000000000.snap.inprogress' - 2017-06-14 14:35:43.722 [18953] snapshot/101/main I> done - 2017-06-14 14:35:43.723 [18953] main/101/master.lua I> vinyl checkpoint done - 2017-06-14 14:35:43.723 [18953] main/101/master.lua I> ready to accept requests - 2017-06-14 14:35:43.724 [18953] main/105/applier/replicator@192.168.0. I> failed to authenticate - 2017-06-14 14:35:43.724 [18953] main/105/applier/replicator@192.168.0. xrow.cc:431 E> ER_LOADING: Instance bootstrap hasn't finished yet - box.once executed on master - 2017-06-14 14:35:43.726 [18953] main C> entering the event loop - 2017-06-14 14:35:43.779 [18953] main/103/main I> initial data sent. - 2017-06-14 14:35:43.780 [18953] relay/[::ffff:192.168.0.101]:/101/main I> recover from `/var/lib/tarantool/master/00000000000000000000.xlog' - 2017-06-14 14:35:43.780 [18953] main/103/main I> final data sent. - 2017-06-14 14:35:43.796 [18953] relay/[::ffff:192.168.0.102]:/101/main I> recover from `/var/lib/tarantool/master/00000000000000000000.xlog' - 2017-06-14 14:35:44.726 [18953] main/105/applier/replicator@192.168.0. I> authenticated - -In this case, the replica would wait for the master to become available, so the -launch order doesn't matter. Our ``box.once()`` logic would also be executed -only once, at the master. - -.. code-block:: console - - $ # the replica has eventually connected to the master - $ # and got bootstrapped (from the replica's log) - 2017-06-14 14:35:43.777 [18952] main/104/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.101:3301 - 2017-06-14 14:35:43.777 [18952] main/104/applier/replicator@192.168.0. I> authenticated - 2017-06-14 14:35:43.777 [18952] main/101/replica.lua I> bootstrapping replica from 192.168.0.199:3310 - 2017-06-14 14:35:43.788 [18952] main/104/applier/replicator@192.168.0. I> initial data received - 2017-06-14 14:35:43.789 [18952] main/104/applier/replicator@192.168.0. I> final data received - 2017-06-14 14:35:43.793 [18952] snapshot/101/main I> saving snapshot `/var/lib/tarantool/replica/00000000000000000005.snap.inprogress' - 2017-06-14 14:35:43.793 [18952] snapshot/101/main I> done - 2017-06-14 14:35:43.795 [18952] main/101/replica.lua I> vinyl checkpoint done - 2017-06-14 14:35:43.795 [18952] main/101/replica.lua I> ready to accept requests - 2017-06-14 14:35:43.795 [18952] main/101/replica.lua I> set 'read_only' configuration option to true - 2017-06-14 14:35:43.795 [18952] main C> entering the event loop - -.. _replication-controlled_failover: - --------------------------------------------------------------------------------- -Controlled failover --------------------------------------------------------------------------------- - -To perform a **controlled failover**, that is, swap the roles of the master and -replica, all we need to do is to set ``read_only=true`` at the master, and -``read_only=false`` at the replica. The order of actions is important here. -If a system is running in production, we do not want concurrent writes happening -both at the replica and the master. Nor do we want the new replica to accept -any writes until it has finished fetching all replication data from the old -master. To compare replica and master state, we can use -:ref:`box.info.signature `. - -1. Set ``read_only=true`` at the master. - - .. code-block:: tarantoolsession - - # at the master - tarantool> box.cfg{read_only=true} - -2. Record the master’s current position with ``box.info.signature``, containing - the sum of all LSNs in the master’s vector clock. - - .. code-block:: tarantoolsession - - # at the master - tarantool> box.info.signature - -3. Wait until the replica’s signature is the same as the master’s. - - .. code-block:: tarantoolsession - - # at the replica - tarantool> box.info.signature - -4. Set ``read_only=false`` at the replica to enable write operations. - - .. code-block:: tarantoolsession - - # at the replica - tarantool> box.cfg{read_only=false} - -These four steps ensure that the replica doesn’t accept new writes until it’s done -fetching writes from the master. - -.. _replication-master_master_bootstrap: - --------------------------------------------------------------------------------- -Master-master bootstrap --------------------------------------------------------------------------------- - -Now let us bootstrap a two-instance **master-master** set. For easier -administration, we make master#1 and master#2 instance files fully identical. - -.. image:: mm-2m-mesh.png - :align: center - -We re-use the master's instance file from the -:ref:`master-replica example ` above. - -.. code-block:: lua - - -- instance file for any of the two masters - box.cfg{ - listen = 3301, - replication = {'replicator:password@192.168.0.101:3301', -- master1 URI - 'replicator:password@192.168.0.102:3301'}, -- master2 URI - read_only = false - } - box.once("schema", function() - box.schema.user.create('replicator', {password = 'password'}) - box.schema.user.grant('replicator', 'replication') -- grant replication role - box.schema.space.create("test") - box.space.test:create_index("primary") - print('box.once executed on master #1') - end) - -In the :ref:`replication ` parameter, we define the -URIs of both masters in the replica set and say -``print('box.once executed on master #1')`` so it will be clear when and where the -``box.once()`` logic is executed. - -Now we can launch the two masters. Again, the launch order doesn't matter. -The ``box.once()`` logic will also be executed only once, at the master which -is elected as the replica set :ref:`leader ` at bootstrap. - -.. code-block:: console - - $ # launching master #1 - $ tarantool master1.lua - 2017-06-14 15:39:03.062 [47021] main/101/master1.lua C> version 1.7.4-52-g980d30092 - 2017-06-14 15:39:03.062 [47021] main/101/master1.lua C> log level 5 - 2017-06-14 15:39:03.063 [47021] main/101/master1.lua I> mapping 268435456 bytes for tuple arena... - 2017-06-14 15:39:03.065 [47021] iproto/101/main I> binary: bound to [::]:3301 - 2017-06-14 15:39:03.065 [47021] main/105/applier/replicator@192.168.0.10 I> can't connect to master - 2017-06-14 15:39:03.065 [47021] main/105/applier/replicator@192.168.0.10 coio.cc:107 !> SystemError connect, called on fd 14, aka 192.168.0.102:57110: Connection refused - 2017-06-14 15:39:03.065 [47021] main/105/applier/replicator@192.168.0.10 I> will retry every 1 second - 2017-06-14 15:39:03.065 [47021] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301 - 2017-06-14 15:39:08.070 [47021] main/105/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.102:3301 - 2017-06-14 15:39:08.071 [47021] main/105/applier/replicator@192.168.0.10 I> authenticated - 2017-06-14 15:39:08.071 [47021] main/101/master1.lua I> bootstrapping replica from 192.168.0.102:3301 - 2017-06-14 15:39:08.073 [47021] main/105/applier/replicator@192.168.0.10 I> initial data received - 2017-06-14 15:39:08.074 [47021] main/105/applier/replicator@192.168.0.10 I> final data received - 2017-06-14 15:39:08.074 [47021] snapshot/101/main I> saving snapshot `/Users/e.shebunyaeva/work/tarantool-test-repl/master1_dir/00000000000000000008.snap.inprogress' - 2017-06-14 15:39:08.074 [47021] snapshot/101/main I> done - 2017-06-14 15:39:08.076 [47021] main/101/master1.lua I> vinyl checkpoint done - 2017-06-14 15:39:08.076 [47021] main/101/master1.lua I> ready to accept requests - box.once executed on master #1 - 2017-06-14 15:39:08.077 [47021] main C> entering the event loop - -.. code-block:: console - - $ # launching master #2 - $ tarantool master2.lua - 2017-06-14 15:39:07.452 [47022] main/101/master2.lua C> version 1.7.4-52-g980d30092 - 2017-06-14 15:39:07.453 [47022] main/101/master2.lua C> log level 5 - 2017-06-14 15:39:07.453 [47022] main/101/master2.lua I> mapping 268435456 bytes for tuple arena... - 2017-06-14 15:39:07.455 [47022] iproto/101/main I> binary: bound to [::]:3301 - 2017-06-14 15:39:07.455 [47022] main/104/applier/replicator@192.168.0.19 I> remote master is 1.7.4 at 192.168.0.101:3301 - 2017-06-14 15:39:07.455 [47022] main/105/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.102:3301 - 2017-06-14 15:39:07.455 [47022] main/101/master2.lua I> initializing an empty data directory - 2017-06-14 15:39:07.457 [47022] snapshot/101/main I> saving snapshot `/Users/e.shebunyaeva/work/tarantool-test-repl/master2_dir/00000000000000000000.snap.inprogress' - 2017-06-14 15:39:07.457 [47022] snapshot/101/main I> done - 2017-06-14 15:39:07.458 [47022] main/101/master2.lua I> vinyl checkpoint done - 2017-06-14 15:39:07.459 [47022] main/101/master2.lua I> ready to accept requests - 2017-06-14 15:39:07.460 [47022] main C> entering the event loop - 2017-06-14 15:39:08.072 [47022] main/103/main I> initial data sent. - 2017-06-14 15:39:08.073 [47022] relay/[::ffff:192.168.0.102]:/101/main I> recover from `/Users/e.shebunyaeva/work/tarantool-test-repl/master2_dir/00000000000000000000.xlog' - 2017-06-14 15:39:08.073 [47022] main/103/main I> final data sent. - 2017-06-14 15:39:08.077 [47022] relay/[::ffff:192.168.0.102]:/101/main I> recover from `/Users/e.shebunyaeva/work/tarantool-test-repl/master2_dir/00000000000000000000.xlog' - 2017-06-14 15:39:08.461 [47022] main/104/applier/replicator@192.168.0.10 I> authenticated diff --git a/doc/book/replication/repl_remove_instances.rst b/doc/book/replication/repl_remove_instances.rst deleted file mode 100644 index 9c6eeef2e6..0000000000 --- a/doc/book/replication/repl_remove_instances.rst +++ /dev/null @@ -1,226 +0,0 @@ -.. _replication-remove_instances: - -================================================================================ -Removing instances -================================================================================ - -Let's assume that we have the following configured replica set with 3 instances -(*instance1*, *instance2* and *intance3*) and we want to remove *instance2*. - -.. image:: replication.svg - :align: left - -To remove it politely, follow these steps: - -1. Disconnect *instance2* from the cluster. -2. Disconnect the cluster from *instance2*. -3. Remove *instance2* from the ``_cluster`` space. - -.. image:: replicationX.svg - :align: left - -**Step 1: disconnecting an instance from the cluster** - -On the disconnecting instance *instance2*, run ``box.cfg{}`` -with a blank replication source: - -.. code-block:: tarantoolsession - - tarantool> box.cfg{replication=''} - -Then check that it was disconnected. Take a look at ``box.info.replication`` -on *instance2* (notice that ``replication.{1,3}.upstream`` is absent): - -.. code-block:: tarantoolsession - - tarantool> box.info.replication - --- - - 1: - id: 1 - uuid: db89978f-7115-4537-8417-9982bb5a256f - lsn: 9 - -- upstream is absent - downstream: - status: follow - idle: 0.93983899999876 - vclock: {1: 9} - 2: - id: 2 - uuid: 0a756d14-e437-4296-85b0-d27a0621613e - lsn: 0 - 3: - id: 3 - uuid: bb362584-c265-4e53-aeb6-450ae818bf59 - lsn: 0 - -- upstream is absent - downstream: - status: follow - idle: 0.26624799999991 - vclock: {1: 9} - ... - -Check *instance1* and *instance3* as well -(notice that the status of ``replication.2.downstream`` is ``stopped``): - -.. code-block:: tarantoolsession - - -- instance1 - tarantool> box.info.replication - --- - - 1: - id: 1 - uuid: db89978f-7115-4537-8417-9982bb5a256f - lsn: 9 - 2: - id: 2 - uuid: 0a756d14-e437-4296-85b0-d27a0621613e - lsn: 0 - upstream: - status: follow - idle: 0.3533439999992 - peer: replicator@localhost:3302 - lag: 0.0001220703125 - downstream: - status: stopped -- status has changed: - message: unexpected EOF when reading from socket, called on fd 13, aka [::1]:3301, - peer of [::1]:53776 - system_message: Broken pipe - 3: - id: 3 - uuid: bb362584-c265-4e53-aeb6-450ae818bf59 - lsn: 0 - upstream: - status: follow - idle: 0.35327999999936 - peer: replicator@localhost:3303 - lag: 0.00018095970153809 - downstream: - status: follow - idle: 0.68685100000221 - vclock: {1: 9} - ... - -**Step 2: disconnecting the cluster from the decommissioned instance** - -On every other instance in the cluster remove *instance2* from -the ``box.cfg{ replication }`` list and call an appropriate -``box.cfg{ replication = {instance1, instance3} }``: - -.. code-block:: tarantoolsession - - tarantool> box.cfg{ replication = { 'instance1-uri', 'instance3-uri' } } - -Take a look at ``box.info.replication`` on *instance2* to check that *instance1* and *instance3* were -disconnected -(notice that the status of ``replication.{1,3}.downstream`` is ``stopped``): - -.. code-block:: tarantoolsession - - tarantool> box.info.replication - --- - - 1: - id: 1 - uuid: db89978f-7115-4537-8417-9982bb5a256f - lsn: 9 - downstream: - status: stopped -- status has changed - message: unexpected EOF when reading from socket, called on fd 16, aka [::1]:3302, - peer of [::1]:53832 - system_message: Broken pipe - 2: - id: 2 - uuid: 0a756d14-e437-4296-85b0-d27a0621613e - lsn: 0 - 3: - id: 3 - uuid: bb362584-c265-4e53-aeb6-450ae818bf59 - lsn: 0 - downstream: - status: stopped -- status has changed - message: unexpected EOF when reading from socket, called on fd 18, aka [::1]:3302, - peer of [::1]:53825 - system_message: Broken pipe - ... - -Check *instance1* and *instance3* as well -(notice that the status of ``replication.2.upstream`` is ``stopped``): - -.. code-block:: tarantoolsession - - -- instance1 - tarantool> box.info.replication - --- - - 1: - id: 1 - uuid: db89978f-7115-4537-8417-9982bb5a256f - lsn: 9 - 2: - id: 2 - uuid: 0a756d14-e437-4296-85b0-d27a0621613e - lsn: 0 - downstream: - status: stopped -- status has changed - message: unexpected EOF when reading from socket, called on fd 13, aka [::1]:3301, - peer of [::1]:53776 - system_message: Broken pipe - 3: - id: 3 - uuid: bb362584-c265-4e53-aeb6-450ae818bf59 - lsn: 0 - upstream: - status: follow - idle: 0.50240100000156 - peer: replicator@localhost:3303 - lag: 0.00015711784362793 - downstream: - status: follow - idle: 0.14237199999843 - vclock: {1: 9} - ... - -**Step 3: persistent removal** - -If a removed instance rejoins later, it will receive all the updates made -by the other instances while it was disconnected. - -If an instance is decommissioned forever, we should clean up the ``_cluster`` space. -First, discover the ``id`` and ``uuid`` of the instance. -On *instance2*, call ``return box.info.id, box.info.uuid``: - -.. code-block:: tarantoolsession - - tarantool> return box.info.id, box.info.uuid - --- - - 2 - - '0a756d14-e437-4296-85b0-d27a0621613e' - ... - -Take a note of ``id`` and ``uuid``. - -Now choose any master from the remaining cluster and perform the following actions on it -(let's assume that we chose *instance1*): - -1. Select all records from the ``_cluster`` space: - -.. code-block:: tarantoolsession - - tarantool> box.space._cluster:select{} - --- - - - [1, 'db89978f-7115-4537-8417-9982bb5a256f'] - - [2, '0a756d14-e437-4296-85b0-d27a0621613e'] - - [3, 'bb362584-c265-4e53-aeb6-450ae818bf59'] - ... - -2. Check if the ``id`` and ``uuid`` of *instance2* are correct and remove them -from the cluster: - -.. code-block:: tarantoolsession - - tarantool> box.space._cluster:delete(2) - --- - - [2, '0a756d14-e437-4296-85b0-d27a0621613e'] - ... - -**Final checks** - -After all modifications, say ``box.info.replication`` to check the health status. diff --git a/doc/book/box/atomic.rst b/doc/concepts/atomic.rst similarity index 100% rename from doc/book/box/atomic.rst rename to doc/concepts/atomic.rst diff --git a/doc/book/box/atomic/thread_model.rst b/doc/concepts/atomic/thread_model.rst similarity index 100% rename from doc/book/box/atomic/thread_model.rst rename to doc/concepts/atomic/thread_model.rst diff --git a/doc/book/box/atomic/transaction_model.rst b/doc/concepts/atomic/transaction_model.rst similarity index 100% rename from doc/book/box/atomic/transaction_model.rst rename to doc/concepts/atomic/transaction_model.rst diff --git a/doc/book/box/atomic/txn_mode_default.rst b/doc/concepts/atomic/txn_mode_default.rst similarity index 96% rename from doc/book/box/atomic/txn_mode_default.rst rename to doc/concepts/atomic/txn_mode_default.rst index a26dc70ccc..1005e949d4 100644 --- a/doc/book/box/atomic/txn_mode_default.rst +++ b/doc/concepts/atomic/txn_mode_default.rst @@ -19,7 +19,7 @@ To allow yielding inside a :ref:`memtx ` transaction, see :ref: To switch back to the default mode, disable the transaction manager: -.. code-block:: enabling +.. code-block:: tarantoolsession box.cfg{memtx_use_mvcc_engine = false} diff --git a/doc/book/box/atomic/txn_mode_mvcc.rst b/doc/concepts/atomic/txn_mode_mvcc.rst similarity index 100% rename from doc/book/box/atomic/txn_mode_mvcc.rst rename to doc/concepts/atomic/txn_mode_mvcc.rst diff --git a/doc/book/app_server/creating_app/fibers.rst b/doc/concepts/coop_multitasking.rst similarity index 72% rename from doc/book/app_server/creating_app/fibers.rst rename to doc/concepts/coop_multitasking.rst index ef4bec2b5a..d0f3fe5deb 100644 --- a/doc/book/app_server/creating_app/fibers.rst +++ b/doc/concepts/coop_multitasking.rst @@ -1,31 +1,29 @@ -.. _application_server_fibers: +.. _concepts-coop_multitasking: -Fibers, yields and cooperative multitasking -=========================================== +Fibers, yields, and cooperative multitasking +============================================ -But wait! If we launch it as shown above -- ``self.respawn()`` -- the function -will be executed only once, just like all the other methods. But we need to -execute ``respawn()`` every 60 seconds. Creating a :ref:`fiber ` -is the Tarantool way of making application logic work in the background at all -times. +Creating a fiber is the Tarantool way of making application logic work in the background at all times. +A **fiber** is a set of instructions that are executed with :ref:`cooperative multitasking `: +the instructions contain :ref:`yield ` signals, upon which control is passed to another fiber. -.. _app-temp_fibers: +.. _app-fibers: Fibers ------ -A **fiber** exists for executing instruction sequences but it is not a thread. +Fibers are similar to threads of execution in computing. The key difference is that threads use -preemptive multitasking, while fibers use :ref:`cooperative multitasking `. This gives -fibers the following two advantages over threads: +preemptive multitasking, while fibers use cooperative multitasking (see :ref:`below `). +This gives fibers the following two advantages over threads: -* Better controllability. Threads often depend on the kernel's thread scheduler - to preempt a busy thread and resume another thread, so preemption may occur - unpredictably. Fibers :ref:`yield ` themselves to run another fiber while executing, - so yields are controlled by application logic. -* Higher performance. Threads require more resources to preempt as they need to - address the system kernel. Fibers are lighter and faster as they don't need to - address the kernel to yield. +* Better controllability. Threads often depend on the kernel's thread scheduler + to preempt a busy thread and resume another thread, so preemption may occur + unpredictably. Fibers :ref:`yield ` themselves to run another fiber while executing, + so yields are controlled by application logic. +* Higher performance. Threads require more resources to preempt as they need to + address the system kernel. Fibers are lighter and faster as they don't need to + address the kernel to yield. Yet fibers have some limitations as compared with threads, the main limitation being no multi-core mode. All fibers in an application belong to a single thread, @@ -37,84 +35,45 @@ A fiber has all the features of a Lua `coroutine `_ and all programming concepts that apply for Lua coroutines will apply for fibers as well. However, Tarantool has made some enhancements for fibers and has used fibers internally. -So, although use of coroutines is possible and supported, use of fibers is +So, although the use of coroutines is possible and supported, the use of fibers is recommended. -Well, performance or controllability are of little importance in our case. We'll -launch ``respawn()`` in a fiber to make it work in the background all the time. -To do so, we'll need to amend ``respawn()``: - -.. code-block:: lua - - respawn = function(self) - -- let's give our fiber a name; - -- this will produce neat output in fiber.info() - fiber.name('Respawn fiber') - while true do - for _, tuple in box.space.pokemons.index.status:pairs( - self.state.CAUGHT) do - box.space.pokemons:update( - tuple[self.ID], - {{'=', self.STATUS, self.state.ACTIVE}} - ) - end - fiber.sleep(self.respawn_time) - end - end - -and call it as a fiber in ``start()``: - -.. code-block:: lua - - start = function(self) - -- create spaces and indexes - <...> - -- create models - <...> - -- compile models - <...> - -- start the game - self.pokemon_model = compiled_pokemon - self.player_model = compiled_player - fiber.create(self.respawn, self) - log.info('Started') - -- errors if schema creation or compilation fails - <...> - end - +Any live fiber can be in one of three states: ``running``, ``suspended``, and +``ready``. After a fiber dies, the ``dead`` status returns. + +To learn more about fibers, go to the :ref:`fiber ` module documentation. + .. _app-yields: Yields ------ +Yield is an action that occurs in a :ref:`cooperative ` environment that +transfers control of the thread from the current fiber to another fiber that is ready to execute. + Any live fiber can be in one of three states: ``running``, ``suspended``, and -``ready``. After a fiber dies, the ``dead`` status returns. By observing +``ready``. After a fiber dies, the ``dead`` status is returned. By observing fibers from the outside, you can only see ``running`` (for the current fiber) and ``suspended`` for any other fiber waiting for an event from eventloop (``ev``) for execution. - -.. image:: yields.svg +.. image:: yields.svg :align: center -Yield is an action that occurs in a :ref:`cooperative ` environment that -transfers control of the thread from the current fiber to another fiber that is ready to execute. - - -After yield has occurred, the next ``ready`` fiber is taken from the queue and executed. +After a yield has occurred, the next ``ready`` fiber is taken from the queue and executed. When there are no more ``ready`` fibers, execution is transferred to the event loop. After a fiber has yielded and regained control, it immediately issues :ref:`testcancel `. -There are :ref:`explicit ` and :ref:`implicit ` yields. +Yields can be :ref:`explicit ` or :ref:`implicit `. .. _app-explicit-yields: Explicit yields ~~~~~~~~~~~~~~~ -**Explicit yield** is clearly visible from the invoking code. There are only two +**Explicit yields** are clearly visible from the invoking code. There are only two explicit yields: :ref:`fiber.yield() ` and :ref:`fiber.sleep(t) ` :ref:`fiber.yield() ` yields execution to another ``ready`` fiber while putting itself in the ``ready`` state, @@ -162,10 +121,10 @@ Here is the list of implicitly yielding operations: .. note:: - Please note that all operations of ``os`` mosule are non-cooperative and + Please note that all operations of the ``os`` mosule are non-cooperative and exclusively block the whole tx thread. -For :ref:`memtx `, since all data is in memory, there is no yielding for a read requests +For :ref:`memtx `, since all data is in memory, there is no yielding for a read request (like ``:select``, ``:pairs``, ``:get``). For :ref:`vinyl `, since some data may not be in memory, there may be disk I/O for a @@ -216,12 +175,12 @@ That is why executing separate commands like ``select()``, ``insert()``, ``updat transaction without MVCC will cause it to an abort. This is due to implicit yield after each chunk of code is executed in the console. - -**Example #1** +Example #1 +~~~~~~~~~~ * Engine = memtx. -.. code-block:: memtx +.. code-block:: lua space:get() space:insert() @@ -232,7 +191,7 @@ The sequence has one yield, at the end of the insert, caused by implicit commit; * Engine = memtx. -.. code-block:: memtx +.. code-block:: lua box.begin() space1:get() @@ -246,7 +205,7 @@ The sequence has one yield, at the end of the ``box.commit``, none of the insert * Engine = vinyl. -.. code-block:: vinyl +.. code-block:: lua space:get() space:insert() @@ -258,7 +217,7 @@ at commit. * Engine = vinyl. -.. code-block:: vinyl +.. code-block:: lua box.begin() space1:get() @@ -271,7 +230,8 @@ at commit. The sequence may yield from 1 to 5 times. -**Example #2** +Example #2 +~~~~~~~~~~ Assume that there are tuples in the :ref:`memtx ` space ``tester`` where the third field represents a positive dollar amount. @@ -321,9 +281,9 @@ three times sequentially when sending requests to the network and awaiting the r Cooperative multitasking ------------------------ -Cooperative multitasking means that unless a running :ref:`fiber ` deliberately :ref:`yields ` +Cooperative multitasking means that unless a running fiber deliberately :ref:`yields ` control, it is not preempted by some other fiber. But a running fiber will -deliberately yield when it encounters a “yield point”: a transaction commit, +deliberately yield when it encounters a "yield point": a transaction commit, an operating system call, or an explicit "yield" request. Any system call which can block will be performed asynchronously, and any running fiber which must wait for a system call will be preempted, so that another @@ -343,4 +303,4 @@ However, a function may perform complex calculations or be written in such a way that yields take a long time to occur. This can lead to unfair scheduling when a single client throttles the rest of the system, or to apparent stalls in processing requests. It is the responsibility of the function -author to avoid this situation. \ No newline at end of file +author to avoid this situation. diff --git a/doc/book/box/data_model.png b/doc/concepts/data_model/data_model.png similarity index 100% rename from doc/book/box/data_model.png rename to doc/concepts/data_model/data_model.png diff --git a/doc/book/box/data_model.svg b/doc/concepts/data_model/data_model.svg similarity index 100% rename from doc/book/box/data_model.svg rename to doc/concepts/data_model/data_model.svg diff --git a/doc/book/box/foreign_key.svg b/doc/concepts/data_model/foreign_key.svg similarity index 100% rename from doc/book/box/foreign_key.svg rename to doc/concepts/data_model/foreign_key.svg diff --git a/doc/concepts/data_model/index.rst b/doc/concepts/data_model/index.rst new file mode 100644 index 0000000000..470bdfe35d --- /dev/null +++ b/doc/concepts/data_model/index.rst @@ -0,0 +1,41 @@ +.. _box_data_model: + +Data model +========== + +If you tried to create a database as suggested in our +:ref:`basic tutorial `, +then your test database now looks like this: + +.. image:: data_model.png + +Tarantool stores data in :ref:`spaces `, which can be thought of as tables in a relational database. +Every record or row in a space is called a :ref:`tuple `. +A tuple may have any number of fields, and the fields may be of different :ref:`types `. + +String data in fields are compared based on the specified :ref:`collation ` rules. +The user can provide hard limits for data values through :ref:`constraints ` +and link related spaces with :ref:`foreign keys `. + +Tarantool supports highly customizable :ref:`indexes ` of various types. +In particular, indexes can be defined with generators like :ref:`sequences `. + +There are six basic :ref:`data operations ` in Tarantool: +SELECT, INSERT, UPDATE, UPSERT, REPLACE, and DELETE. A number of :ref:`complexity factors ` +affects the resource usage of each function. + +Tarantool allows :ref:`describing the data schema ` but does not require it. +The user can :ref:`migrate a schema ` without migrating the data. + +To ensure :ref:`data persistence ` and recover quickly in case of failure, +Tarantool uses mechanisms like the write-ahead log (WAL) and snapshots. + +.. toctree:: + :maxdepth: 2 + + value_store + indexes + operations + schema_desc + persistence + migrations diff --git a/doc/book/box/indexes.rst b/doc/concepts/data_model/indexes.rst similarity index 58% rename from doc/book/box/indexes.rst rename to doc/concepts/data_model/indexes.rst index a885f21485..62c89b1f40 100644 --- a/doc/book/box/indexes.rst +++ b/doc/concepts/data_model/indexes.rst @@ -1,14 +1,24 @@ +.. _concepts-data_model_indexes: +.. _index-box_index: -================================================================================ Indexes -================================================================================ +======= + +Basics +------ An **index** is a special data structure that stores a group of key values and pointers. It is used for efficient manipulations with data. -As with spaces, you should specify the index **name**, and let Tarantool +As with spaces, you should specify the index **name** and let Tarantool come up with a unique **numeric identifier** ("index id"). +An index always has a **type**. The default index type is :ref:`TREE `. +TREE indexes are provided by all Tarantool engines, can index unique and +non-unique values, support partial key searches, comparisons, and ordered results. +Additionally, the memtx engine supports :ref:`HASH `, +:ref:`RTREE ` and :ref:`BITSET ` indexes. + An index may be **multi-part**, that is, you can declare that an index key value is composed of two or more fields in the tuple, in any order. For example, for an ordinary TREE index, the maximum number of parts is 255. @@ -23,239 +33,97 @@ and they may be non-unique. Indexes have certain limitations. See details on page :doc:`Limitations `. --------------------------------------------------------------------------------- -Creating an index --------------------------------------------------------------------------------- - -It is mandatory to create an index for a space before trying to insert -tuples into the space, or select tuples from the space. - -The simple :doc:`index-creation ` -operation is: - -.. cssclass:: highlight -.. parsed-literal:: - - :extsamp:`box.space.{**{space-name}**}:create_index('{*{index-name}*}')` - -This creates a unique :ref:`TREE ` index on the first field -of all tuples (often called "Field#1"), which is assumed to be numeric. - -A recommended design pattern for a data model is to base primary keys on the -first fields of a tuple. This speeds up tuple comparison due to the specifics of -data storage and the way comparisons are arranged in Tarantool. - -The simple :doc:`SELECT ` request is: - -.. cssclass:: highlight -.. parsed-literal:: - - :extsamp:`box.space.{**{space-name}**}:select({*{value}*})` - -This looks for a single tuple via the first index. Since the first index -is always unique, the maximum number of returned tuples will be 1. -You can call ``select()`` without arguments, and it will return all tuples. -Be careful! Using ``select()`` for huge spaces hangs your instance. - -An index definition may also include identifiers of tuple fields -and their expected **types**. See allowed indexed field types in section -:ref:`Details about indexed field types `: - -.. cssclass:: highlight -.. parsed-literal:: - - :extsamp:`box.space.{**{space-name}**}:create_index({**{index-name}**}, {type = 'tree', parts = {{field = 1, type = 'unsigned'}}}` - -Space definitions and index definitions are stored permanently in Tarantool's -system spaces :ref:`_space ` and :ref:`_index `. - -.. admonition:: Tip - :class: fact - - See full information about creating indexes, such as - how to create a multikey index, an index using the ``path`` option, or - how to create a functional index in our reference for - :doc:`/reference/reference_lua/box_space/create_index`. - -.. _index-box_index-operations: - --------------------------------------------------------------------------------- -Index operations --------------------------------------------------------------------------------- - -Index operations are automatic: if a data manipulation request changes a tuple, -then it also changes the index keys defined for the tuple. - -#. For further demonstrations let's create a sample space named ``tester`` and - put it in a variable ``my_space``: - - .. code-block:: tarantoolsession - - tarantool> my_space = box.schema.space.create('tester') - -#. Format the created space by specifying field names and types: - - .. code-block:: tarantoolsession - - tarantool> my_space:format({ - > {name = 'id', type = 'unsigned'}, - > {name = 'band_name', type = 'string'}, - > {name = 'year', type = 'unsigned'}, - > {name = 'rate', type = 'unsigned', is_nullable = true}}) - -#. Create the **primary** index (named ``primary``): - - .. code-block:: tarantoolsession +To create a generator for indexes, you can use a sequence object. +Learn how to do it in the :ref:`tutorial `. - tarantool> my_space:create_index('primary', { - > type = 'tree', - > parts = {'id'} - > }) +.. _index-box_indexed-field-types: - This is a primary index based on the ``id`` field of each tuple. +Indexed field types +------------------- -#. Insert some :ref:`tuples ` into the space: +Not to be confused with :ref:`index types ` -- the types of the data structure that is an index. +See more about index types :ref:`below `. - .. code-block:: tarantoolsession +Indexes restrict values that Tarantool can store with MsgPack. +This is why, for example, ``'unsigned'`` and ``'integer'`` are different field types, +although in MsgPack they are both stored as integer values. +An ``'unsigned'`` index contains only *non-negative* integer values, +while an ``‘integer’`` index contains *any* integer values. - tarantool> my_space:insert{1, 'Roxette', 1986, 1} - tarantool> my_space:insert{2, 'Scorpions', 2015, 4} - tarantool> my_space:insert{3, 'Ace of Base', 1993} - tarantool> my_space:insert{4, 'Roxette', 2016, 3} +The default field type is ``'unsigned'`` and the default index type is TREE. +Although ``'nil'`` is not a legal indexed field type, indexes may contain `nil` +:ref:`as a non-default option `. -#. Create a **secondary index**: +To learn more about field types, check the +:ref:`Field type details ` section and the more elaborate +:ref:`Details about index field types ` in the reference. - .. code-block:: tarantoolsession - - tarantool> box.space.tester:create_index('secondary', {parts = {{field=3, type='unsigned'}}}) - --- - - unique: true - parts: - - type: unsigned - is_nullable: false - fieldno: 3 - id: 2 - space_id: 512 - type: TREE - name: secondary - ... - -#. Create a **multi-part index** with three parts: - - .. code-block:: tarantoolsession - - tarantool> box.space.tester:create_index('thrine', {parts = { - > {field = 2, type = 'string'}, - > {field = 3, type = 'unsigned'}, - > {field = 4, type = 'unsigned'} - > }}) - --- - - unique: true - parts: - - type: string - is_nullable: false - fieldno: 2 - - type: unsigned - is_nullable: false - fieldno: 3 - - type: unsigned - is_nullable: true - fieldno: 4 - id: 6 - space_id: 513 - type: TREE - name: thrine - ... - -**There are the following SELECT variations:** - -* The search can use **comparisons** other than equality: - - .. code-block:: tarantoolsession - - tarantool> box.space.tester:select(1, {iterator = 'GT'}) - --- - - - [2, 'Scorpions', 2015, 4] - - [3, 'Ace of Base', 1993] - - [4, 'Roxette', 2016, 3] - ... - - The :ref:`comparison operators ` are: - - * ``LT`` for "less than" - * ``LE`` for "less than or equal" - * ``GT`` for "greater" - * ``GE`` for "greater than or equal" . - * ``EQ`` for "equal", - * ``REQ`` for "reversed equal" - - Value comparisons make sense if and only if the index type is TREE. - The iterator types for other types of indexes are slightly different and work - differently. See details in section :ref:`Iterator types `. - - Note that we don't use the name of the index, which means we use primary index here. - - This type of search may return more than one tuple. The tuples will be sorted - in descending order by key if the comparison operator is LT or LE or REQ. - Otherwise they will be sorted in ascending order. - -* The search can use a **secondary index**. - - For a primary-key search, it is optional to specify an index name as - was demonstrated above. - For a secondary-key search, it is mandatory. - - .. code-block:: tarantoolsession - - tarantool> box.space.tester.index.secondary:select({1993}) - --- - - - [3, 'Ace of Base', 1993] - ... - - .. _partial_key_search: - -* **Partial key search:** The search may be for some key parts starting with - the prefix of the key. Note that partial key searches are available - only in TREE indexes. - - .. code-block:: tarantoolsession - - tarantool> box.space.tester.index.thrine:select({'Scorpions', 2015}) - --- - - - [2, 'Scorpions', 2015, 4] - ... - -* The search can be for all fields, using a table as the value: - - .. code-block:: tarantoolsession - - tarantool> box.space.tester.index.thrine:select({'Roxette', 2016, 3}) - --- - - - [4, 'Roxette', 2016, 3] - ... - - or the search can be for one field, using a table or a scalar: - - .. code-block:: tarantoolsession - - tarantool> box.space.tester.index.thrine:select({'Roxette'}) - --- - - - [1, 'Roxette', 1986, 5] - - [4, 'Roxette', 2016, 3] - ... - -.. admonition:: Tip - :class: fact +.. container:: table - You can also add, drop, or alter the definitions at runtime, with some - restrictions. Read more about index operations in reference for - :doc:`box.index submodule `. + .. list-table:: + :header-rows: 1 + :widths: 34 33 33 + + * - Field type name string + - Field type + - Index type + * - ``'boolean'`` + - :ref:`boolean ` + - :ref:`boolean ` + * - ``'integer'`` (may also be called ``'int'``) + - :ref:`integer `, which may include unsigned values + - TREE or HASH + * - ``'unsigned'`` (may also be called ``'uint'`` or ``'num'``, but ``'num'`` is deprecated) + - :ref:`unsigned ` + - TREE, BITSET, or HASH + * - ``'double'`` + - :ref:`double ` + - TREE or HASH + * - ``'number'`` + - :ref:`number `, which may include + :ref:`integer `, :ref:`double `, + or :ref:`decimal ` values + - TREE or HASH + * - ``'decimal'`` + - :ref:`decimal ` + - TREE or HASH + * - ``'string'`` (may also be called ``'str'``) + - :ref:`string ` + - TREE, BITSET, or HASH + * - ``'varbinary'`` + - :ref:`varbinary ` + - TREE, HASH, or BITSET (since version 2.7) + * - ``'uuid'`` + - :ref:`uuid ` + - TREE or HASH + * - ``datetime`` + - :ref:`datetime ` + - TREE + * - ``'array'`` + - :ref:`array ` + - :ref:`RTREE ` + * - ``'scalar'`` + - may include :ref:`nil `, + :ref:`boolean `, + :ref:`integer `, + :ref:`unsigned `, + :ref:`number `, + :ref:`decimal `, + :ref:`string `, + :ref:`varbinary `, + or :ref:`uuid ` values | + |br| + When a scalar field contains values of + different underlying types, the key order + is: nils, then booleans, then numbers, + then strings, then varbinaries, then + uuids. + - TREE or HASH .. _index-types: --------------------------------------------------------------------------------- Index types --------------------------------------------------------------------------------- +----------- An index always has a **type**. Different types are intended for different usage scenarios. @@ -329,9 +197,8 @@ We give an overview of index features in the following table: .. _indexes-tree: -******************************************************************************** TREE indexes -******************************************************************************** +~~~~~~~~~~~~ The default index type is 'TREE'. TREE indexes are provided by memtx and vinyl engines, can index unique and @@ -343,9 +210,8 @@ Additionally, memtx engine supports HASH, RTREE and BITSET indexes. .. _indexes-hash: -******************************************************************************** HASH indexes -******************************************************************************** +~~~~~~~~~~~~ HASH indexes require unique fields and loses to TREE in almost all respects. So we do not recommend to use it in the applications. @@ -369,9 +235,8 @@ Use HASH index: .. _indexes-rtree: -******************************************************************************** RTREE indexes -******************************************************************************** +~~~~~~~~~~~~~ RTREE is a multidimensional index supporting up to 20 dimensions. It is used especially for indexing spatial information, such as geographical @@ -552,9 +417,8 @@ Here's short example of using 4D tree: .. _indexes-bitset: -******************************************************************************** BITSET indexes -******************************************************************************** +~~~~~~~~~~~~~~ Bitset is a bit mask. You should use it when you need to search by bit masks. This can be, for example, storing a vector of attributes and searching by these diff --git a/doc/concepts/data_model/migrations.rst b/doc/concepts/data_model/migrations.rst new file mode 100644 index 0000000000..3d24ed8bae --- /dev/null +++ b/doc/concepts/data_model/migrations.rst @@ -0,0 +1,143 @@ +.. _migrations: + +Migrations +========== + +**Migration** refers to any change in a data schema: adding/removing a field, +creating/dropping an index, changing a field format, etc. + +In Tarantool, there are two types of schema migration +that do not require data migration: + +- adding a field to the end of a space + +- creating an index + +.. note:: + + Check the `Upgrading space schema `__ + section in the Enterprise version. With the help of ``space:upgrade()`` feature, + you can enable compression and migrate, including already created tuples. + + +Adding a field to the end of a space +------------------------------------ + +You can add a field as follows: + +.. code:: lua + + local users = box.space.users + local fmt = users:format() + + table.insert(fmt, { name = 'age', type = 'number', is_nullable = true }) + users:format(fmt) + +Note that the field must have the ``is_nullable`` parameter. Otherwise, +an error will occur. + +After creating a new field, you probably want to fill it with data. +The `tarantool/moonwalker `_ +module is useful for this task. +The README file describes how to work with this module. + +Creating an index +----------------- + +Index creation is described in the +:doc:`/reference/reference_lua/box_space/create_index` method. + +.. _other-migrations: + +Other types of migrations +------------------------- + +Other types of migrations are also allowed, but it would be more difficult to +maintain data consistency. + +Migrations are possible in two cases: + +- When Tarantool starts, and no client uses the database yet + +- During request processing, when active clients are already using the database + +For the first case, it is enough to write and test the migration code. +The most difficult task is to migrate data when there are active clients. +You should keep it in mind when you initially design the data schema. + +We identify the following problems if there are active clients: + +- Associated data can change atomically. + +- The system should be able to transfer data using both the new schema and the old one. + +- When data is being transferred to a new space, data access should consider + that the data might be in one space or another. + +- Write requests must not interfere with the migration. + A common approach is to write according to the new data schema. + +These issues may or may not be relevant depending on your application and +its availability requirements. + +What you need to know when writing complex migrations +----------------------------------------------------- + +Tarantool has a transaction mechanism. It is useful when writing a migration, +because it allows you to work with the data atomically. But before using +the transaction mechanism, you should explore its limitations. + +For details, see the section about :doc:`transactions `. + +How you can apply migration +--------------------------- + +The migration code is executed on a running Tarantool instance. +Important: no method guarantees you transactional application of migrations +on the whole cluster. + +**Method 1**: include migrations in the application code + +This is quite simple: when you reload the code, the data is migrated at the right moment, +and the database schema is updated. +However, this method may not work for everyone. +You may not be able to restart Tarantool or update the code using the hot-reload mechanism. + +**Method 2**: tarantool/migrations (only for a Tarantool Cartridge cluster) + +This method is described in the README file of the +`tarantool/migrations `_ module. + +.. note:: + + There are also two other methods that we **do not recommend**, + but you may find them useful for one reason or another. + + **Method 3**: the ``tarantoolctl`` utility + + The ``tarantoolctl`` utility ships with Tarantool. + Connect to the necessary instance using ``tarantoolctl connect``. + + .. code:: console + + $ tarantoolctl connect admin:password@localhost:3301 + + - If your migration is written in a Lua file, you can execute it + using ``dofile()``. Call this function and specify the path to the + migration file as the first argument. It looks like this: + + .. code-block:: tarantoolsession + + tarantool> dofile('0001-delete-space.lua') + --- + ... + + - (or) Copy the migration script code, + paste it into the console, and run it. + + **Method 4**: applying migration with Ansible + + If you use the `Ansible role `_ + to deploy a Tarantool cluster, you can use ``eval``. + You can find more information about it + `in the Ansible role documentation `_. diff --git a/doc/concepts/data_model/operations.rst b/doc/concepts/data_model/operations.rst new file mode 100644 index 0000000000..602c202539 --- /dev/null +++ b/doc/concepts/data_model/operations.rst @@ -0,0 +1,158 @@ +.. _index-box_operations: + +Operations +========== + +.. _index-box_data-operations: + +Data operations +--------------- + +The basic data operations supported in Tarantool are: + +* five data-manipulation operations (INSERT, UPDATE, UPSERT, DELETE, REPLACE), and +* one data-retrieval operation (SELECT). + +All of them are implemented as functions in :ref:`box.space ` submodule. + +**Examples:** + +* :ref:`INSERT `: Add a new tuple to space 'tester'. + + The first field, field[1], will be 999 (MsgPack type is `integer`). + + The second field, field[2], will be 'Taranto' (MsgPack type is `string`). + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:insert{999, 'Taranto'} + +* :ref:`UPDATE `: Update the tuple, changing field field[2]. + + The clause "{999}", which has the value to look up in the index of the tuple's + primary-key field, is mandatory, because ``update()`` requests must always have + a clause that specifies a unique key, which in this case is field[1]. + + The clause "{{'=', 2, 'Tarantino'}}" specifies that assignment will happen to + field[2] with the new value. + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:update({999}, {{'=', 2, 'Tarantino'}}) + +* :ref:`UPSERT `: Upsert the tuple, changing field field[2] + again. + + The syntax of ``upsert()`` is similar to the syntax of ``update()``. However, + the execution logic of these two requests is different. + UPSERT is either UPDATE or INSERT, depending on the database's state. + Also, UPSERT execution is postponed until after transaction commit, so, unlike + ``update()``, ``upsert()`` doesn't return data back. + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:upsert({999, 'Taranted'}, {{'=', 2, 'Tarantism'}}) + +* :ref:`REPLACE `: Replace the tuple, adding a new field. + + This is also possible with the ``update()`` request, but the ``update()`` + request is usually more complicated. + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:replace{999, 'Tarantella', 'Tarantula'} + +* :ref:`SELECT `: Retrieve the tuple. + + The clause "{999}" is still mandatory, although it does not have to mention + the primary key. + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:select{999} + +* :ref:`DELETE `: Delete the tuple. + + In this example, we identify the primary-key field. + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:delete{999} + +Summarizing the examples: + +* Functions ``insert`` and ``replace`` accept a tuple + (where a primary key comes as part of the tuple). +* Function ``upsert`` accepts a tuple + (where a primary key comes as part of the tuple), + and also the update operations to execute. +* Function ``delete`` accepts a full key of any unique index + (primary or secondary). +* Function ``update`` accepts a full key of any unique index + (primary or secondary), + and also the operations to execute. +* Function ``select`` accepts any key: primary/secondary, unique/non-unique, + full/partial. + +See reference on ``box.space`` for more +:ref:`details on using data operations `. + +.. NOTE:: + + Besides Lua, you can use + :ref:`Perl, PHP, Python or other programming language connectors `. + The client server protocol is open and documented. + See this :ref:`annotated BNF `. + +.. _index-box_complexity-factors: + +Complexity factors +------------------ + +In reference for :ref:`box.space ` and +:doc:`/reference/reference_lua/box_index` +submodules, there are notes about which complexity factors might affect the +resource usage of each function. + +.. container:: table + + .. list-table:: + :widths: 20 80 + :header-rows: 1 + + * - Complexity factor + - Effect + * - Index size + - The number of index keys is the same as the number + of tuples in the data set. For a TREE index, if + there are more keys, then the lookup time will be + greater, although, of course, the effect is not + linear. For a HASH index, if there are more keys, + then there is more RAM used, but the number of + low-level steps tends to remain constant. + * - Index type + - Typically, a HASH index is faster than a TREE index + if the number of tuples in the space is greater + than one. + * - Number of indexes accessed + - Ordinarily, only one index is accessed to retrieve + one tuple. But to update the tuple, there must be N + accesses if the space has N different indexes. + |br| + Note regarding storage engine: Vinyl optimizes away such + accesses if secondary index fields are unchanged by + the update. So, this complexity factor applies only to + memtx, since it always makes a full-tuple copy on every + update. + * - Number of tuples accessed + - A few requests, for example, SELECT, can retrieve + multiple tuples. This factor is usually less + important than the others. + * - WAL settings + - The important setting for the write-ahead log is + :ref:`wal_mode `. + If the setting causes no writing or + delayed writing, this factor is unimportant. If the + setting causes every data-change request to wait + for writing to finish on a slow device, this factor + is more important than all the others. diff --git a/doc/concepts/data_model/persistence.rst b/doc/concepts/data_model/persistence.rst new file mode 100644 index 0000000000..0545fdbfef --- /dev/null +++ b/doc/concepts/data_model/persistence.rst @@ -0,0 +1,42 @@ +.. _concepts-data_model-persistence: +.. _index-box_persistence: + +Persistence +=========== + +To ensure data persistence, Tarantool records updates to the database in the so-called +:ref:`write-ahead log (WAL) ` files. +When a power outage occurs or the Tarantool instance is killed incidentally, +the in-memory database is lost. +In such case, Tarantool restores the data from WAL files +by reading them and redoing the requests. +This is called the "recovery process". +You can change the timing of the WAL writer or turn it off by setting +the :ref:`wal_mode `. + +Tarantool also maintains a set of :ref:`snapshot files `. +These files contain an on-disk copy of the entire data set for a given moment. +Instead of reading every WAL file since the databases were created, the recovery +process can load the latest snapshot file and then read the WAL files, +produced after the snapshot file was made. +After creating a new snapshot, the earlier WAL files can be removed to free up space. + +To force immediate creation of a snapshot file, use the +:doc:`box.snapshot() ` function. +To enable the automatic creation of snapshot files, use Tarantool's +:ref:`checkpoint daemon `. +The checkpoint daemon sets intervals for forced checkpoints. It makes sure that the states +of both memtx and vinyl storage engines are synchronized and saved to disk, +and automatically removes earlier WAL files. + +Snapshot files can be created even if there is no WAL file. + +.. NOTE:: + + The memtx engine makes only regular checkpoints with the interval set in + :ref:`checkpoint daemon ` configuration. + + The vinyl engine runs checkpointing in the background at all times. + +See the :ref:`Internals ` section for more details +about the WAL writer and the recovery process. diff --git a/doc/concepts/data_model/schema_desc.rst b/doc/concepts/data_model/schema_desc.rst new file mode 100644 index 0000000000..d3c563b93a --- /dev/null +++ b/doc/concepts/data_model/schema_desc.rst @@ -0,0 +1,121 @@ +.. _index-box-data_schema_description: + +Data schema description +======================= + +In Tarantool, the use of a data schema is optional. + +When creating a :term:`space `, you do not have to define a data schema. In this case, +the tuples store random data. This rule does not apply to indexed fields. +Such fields must contain data of the same type. + +You can define a data schema when creating a space. Read more in the description of the +:doc:`/reference/reference_lua/box_schema/space_create` function. +If you have already created a space without specifying a data schema, you can do it later using +:doc:`/reference/reference_lua/box_space/format`. + +After the data schema is defined, all the data is validated by type. Before any insert or update, +you will get an error if the data types do not match. + +We recommend using a data schema because it helps avoid mistakes. + +In Tarantool, you can define a data schema in two different ways. + +Data schema description in a code file +-------------------------------------- + +The code file is usually called ``init.lua`` and contains the following schema description: + +.. code:: lua + + box.cfg() + + users = box.schema.create_space('users', { if_not_exists = true }) + users:format({{ name = 'user_id', type = 'number'}, { name = 'fullname', type = 'string'}}) + + users:create_index('pk', { parts = { { field = 'user_id', type = 'number'}}}) + +This is quite simple: when you run tarantool, it executes this code and creates +a data schema. To run this file, use: + +.. code:: bash + + tarantool init.lua + +However, it may seem complicated if you do not plan to dive deep into the Lua language and its syntax. + +Possible difficulty: the snippet above has a function call with a colon: ``users:format``. +It is used to pass the ``users`` variable as the first argument +of the ``format`` function. +This is similar to ``self`` in object-based languages. + +So it might be more convenient for you to describe the data schema with YAML. + +.. _data-schema-ddl: + +Data schema description using the DDL module +-------------------------------------------- + +The `DDL module `_ allows you to describe a data schema +in the YAML format in a declarative way. + +The schema would look something like this: + +.. code-block:: yaml + + spaces: + users: + engine: memtx + is_local: false + temporary: false + format: + - {name: user_id, type: uuid, is_nullable: false} + - {name: fullname, type: string, is_nullable: false} + - {name: bucket_id, type: unsigned, is_nullable: false} + indexes: + - name: user_id + unique: true + parts: [{path: user_id, type: uuid, is_nullable: false}] + type: HASH + - name: bucket_id + unique: false + parts: [{path: bucket_id, type: unsigned, is_nullable: false}] + type: TREE + sharding_key: [user_id] + sharding_func: test_module.sharding_func + +This alternative is simpler to use, and you do not have to dive deep into Lua. + +``DDL`` is a built-in +:doc:`Cartridge ` module. +Cartridge is a cluster solution for Tarantool. In its WebUI, there is a separate tab +called "Code". On this tab, in the ``schema.yml`` file, you can define the schema, check its correctness, +and apply it to the whole cluster. + +If you do not use Cartridge, you can still use the DDL module: +put the following Lua code into the file that you use to run Tarantool. +This file is usually called ``init.lua``. + +.. code:: lua + + local yaml = require('yaml') + local ddl = require('ddl') + + box.cfg{} + + local fh = io.open('ddl.yml', 'r') + local schema = yaml.decode(fh:read('*all')) + fh:close() + local ok, err = ddl.check_schema(schema) + if not ok then + print(err) + end + local ok, err = ddl.set_schema(schema) + if not ok then + print(err) + end + +.. WARNING:: + + It is forbidden to modify the data schema in DDL after it has been applied. + For migration, there are different scenarios described below. diff --git a/doc/concepts/data_model/value_store.rst b/doc/concepts/data_model/value_store.rst new file mode 100644 index 0000000000..3f5aca73bd --- /dev/null +++ b/doc/concepts/data_model/value_store.rst @@ -0,0 +1,695 @@ +Data storage +============ + +.. _index-box_tuple: + +Tuples +------ + +Tarantool operates data in the form of tuples. + +.. glossary:: + + tuple + A tuple is a group of data values in Tarantool's memory. + Think of it as a "database record" or a "row". + The data values in the tuple are called :term:`fields `. + + When Tarantool returns a tuple value in the console, + by default, it uses :ref:`YAML ` format, + for example: ``[3, 'Ace of Base', 1993]``. + + Internally, Tarantool stores tuples as + `MsgPack `_ arrays. + + field + Fields are distinct data values, contained in a tuple. + They play the same role as "row columns" or "record fields" in relational databases, + with a few improvements: + + * fields can be composite structures, such as arrays or maps, + * fields don't need to have names. + + A given tuple may have any number of fields, and the fields may be of + different :ref:`types `. + + The field's number is the identifier of the field. + Numbers are counted from base 1 in Lua and other 1-based languages, + or from base 0 in languages like PHP or C/C++. + So, ``1`` or ``0`` can be used in some contexts to refer to the first + field of a tuple. + +.. _index-box_space: + +Spaces +------ + +Tarantool stores tuples in containers called spaces. +In the example above, there's a space called ``tester``. + +.. glossary:: + + space + In Tarantool, a space is a primary container that stores data. + It is analogous to tables in relational databases. + Spaces contain :term:`tuples ` -- the Tarantool name for + database records. + The number of tuples in a space is unlimited. + + At least one space is required to store data with Tarantool. + Each space has the following attributes: + + * a unique **name** specified by the user, + * a unique **numeric identifier** which can be specified by + the user, but usually is assigned automatically by Tarantool, + * an **engine**: *memtx* (default) --- in-memory engine, + fast but limited in size, or *vinyl* --- on-disk engine for huge data sets. + + To be functional, a space also needs to have a :ref:`primary index `. + It can also have secondary indexes. + +.. _index-box_data-types: + +Data types +---------- + +Tarantool is both a database manager and an application server. +Therefore a developer often deals with two type sets: +the types of the programming language (such as Lua) and +the types of the Tarantool storage format (MsgPack). + +.. _index-box_lua-vs-msgpack: + +Lua versus MsgPack +~~~~~~~~~~~~~~~~~~ + +.. container:: table + + .. list-table:: + :widths: 15 30 15 40 + :header-rows: 1 + + * - Scalar / compound + - MsgPack type + - Lua type + - Example value + * - scalar + - nil + - `cdata`_ + - :ref:`box.NULL ` + * - scalar + - boolean + - `boolean`_ + - ``true`` + * - scalar + - string + - `string`_ + - ``'A B C'`` + * - scalar + - integer + - `number`_ + - ``12345`` + * - scalar + - integer + - `cdata`_ + - ``12345`` + * - scalar + - float64 (double) + - `number`_ + - ``1.2345`` + * - scalar + - float64 (double) + - `cdata`_ + - ``1.2345`` + * - scalar + - binary + - `cdata`_ + - ``[!!binary 3t7e]`` + * - scalar + - ext (for Tarantool ``decimal``) + - `cdata`_ + - ``1.2`` + * - scalar + - ext (for Tarantool ``datetime``) + - `cdata`_ + - ``'2021-08-20T16:21:25.122999906 Europe/Berlin'`` + * - scalar + - ext (for Tarantool ``interval``) + - `cdata`_ + - ``+1 months, 1 days`` + * - scalar + - ext (for Tarantool ``uuid``) + - `cdata`_ + - ``12a34b5c-de67-8f90-123g-h4567ab8901`` + * - compound + - map + - `table`_ (with string keys) + - ``{'a': 5, 'b': 6}`` + * - compound + - array + - `table`_ (with integer keys) + - ``[1, 2, 3, 4, 5]`` + * - compound + - array + - tuple (`cdata`_) + - ``[12345, 'A B C']`` + +.. _boolean: http://www.lua.org/pil/2.2.html +.. _string: http://www.lua.org/pil/2.4.html +.. _number: http://www.lua.org/pil/2.3.html +.. _table: http://www.lua.org/pil/2.5.html +.. _cdata: http://luajit.org/ext_ffi.html#call + +.. note:: + + MsgPack values have variable lengths. + So, for example, the smallest number requires only one byte, but the largest number + requires nine bytes. + +.. note:: + + The Lua `nil `_ type is encoded as MsgPack ``nil`` but + decoded as :ref:`msgpack.NULL `. + +.. _index_box_field_type_details: + +Field type details +~~~~~~~~~~~~~~~~~~ + +.. _index-box_nil: + +**nil**. In Lua, the nil type has only one possible value, also called ``nil``. +Tarantool displays it as ``null`` when using the default +:ref:`YAML ` format. +Nil may be compared to values of any types with == (is-equal) +or ~= (is-not-equal), but other comparison operations will not work. +Nil may not be used in Lua tables; the workaround is to use +:ref:`box.NULL ` because ``nil == box.NULL`` is true. +Example: ``nil``. + +.. _index-box_boolean: + +**boolean**. A boolean is either ``true`` or ``false``. +Example: ``true``. + +.. _index-box_integer: + +**integer**. The Tarantool integer type is for integers between +-9223372036854775808 and 18446744073709551615, which is about 18 quintillion. +This type corresponds to the number type in Lua and to the integer type in MsgPack. +Example: ``-2^63``. + +.. _index-box_unsigned: + +**unsigned**. The Tarantool unsigned type is for integers between +0 and 18446744073709551615. So it is a subset of integer. +Example: ``123456``. + +.. _index-box_double: + +**double**. The double field type exists +mainly to be equivalent to Tarantool/SQL's +:ref:`DOUBLE data type `. +In `msgpuck.h `_ (Tarantool's interface to MsgPack), +the storage type is ``MP_DOUBLE`` and the size of the encoded value is always 9 bytes. +In Lua, fields of the double type can only contain non-integer numeric values and +cdata values with double floating-point numbers. +Examples: ``1.234``, ``-44``, ``1.447e+44``. + +To avoid using the wrong kind of values inadvertently, use +``ffi.cast()`` when searching or changing ``double`` fields. +For example, instead of +:samp:`{space_object}:insert`:code:`{`:samp:`{value}`:code:`}` +use +``ffi = require('ffi') ...`` +:samp:`{space_object}:insert`:code:`({ffi.cast('double',`:samp:`{value}`:code:`)})`. +Example: + +.. code-block:: tarantoolsession + + s = box.schema.space.create('s', {format = {{'d', 'double'}}}) + s:create_index('ii') + s:insert({1.1}) + ffi = require('ffi') + s:insert({ffi.cast('double', 1)}) + s:insert({ffi.cast('double', tonumber('123'))}) + s:select(1.1) + s:select({ffi.cast('double', 1)}) + +Arithmetic with cdata ``double`` will not work reliably, so +for Lua, it is better to use the ``number`` type. +This warning does not apply for Tarantool/SQL because +Tarantool/SQL does +:ref:`implicit casting `. + +.. _index-box_number: + +**number**. The Tarantool number field may have both +integer and floating-point values, although in Lua a ``number`` +is a double-precision floating-point. + +Tarantool will try to store a Lua number as +floating-point if the value contains a decimal point or is very large +(greater than 100 trillion = 1e14), otherwise Tarantool will store it as an integer. +To ensure that even very large numbers are stored as integers, use the +:ref:`tonumber64 ` function, or the LL (Long Long) suffix, +or the ULL (Unsigned Long Long) suffix. +Here are examples of numbers using regular notation, exponential notation, +the ULL suffix and the ``tonumber64`` function: +``-55``, ``-2.7e+20``, ``100000000000000ULL``, ``tonumber64('18446744073709551615')``. + +You can also use the ``ffi`` module to specify a C type to cast the number to. +In this case, the number will be stored as `cdata`_. + +.. _index-box_decimal: + +**decimal**. The Tarantool decimal type is stored as a :ref:`MsgPack ext ` (Extension). +Values with the decimal type are not floating-point values although +they may contain decimal points. +They are exact with up to 38 digits of precision. +Example: a value returned by a function in the :ref:`decimal ` module. + +.. _index-box_datetime: + +**datetime**. Introduced in :tarantool-release:`2.10.0`. +The Tarantool ``datetime`` type facilitates operations with date and time, +accounting for leap years or the varying number of days in a month. +It is stored as a :ref:`MsgPack ext ` (Extension). +Operations with this data type use code from `c-dt `_, a third-party library. + +For more information, see :doc:`Module datetime `. + +.. _index-box_interval: + +**interval**. Introduced in :tarantool-release:`2.10.0`. +The Tarantool ``interval`` type represents periods of time. +They can be added to or subtracted from ``datetime`` values or each other. +Operations with this data type use code from `c-dt `_, a third-party library. +The type is stored as a :ref:`MsgPack ext ` (Extension). +For more information, see :doc:`Module datetime `. + +.. _index-box_string: + +**string**. A string is a variable-length sequence of bytes, usually represented with +alphanumeric characters inside single quotes. In both Lua and MsgPack, strings +are treated as binary data, with no attempts to determine a string's +character set or to perform any string conversion -- unless there is an optional +:ref:`collation `. +So, usually, string sorting and comparison are done byte-by-byte, without any special +collation rules applied. +For example, numbers are ordered by their point on the number line, so 2345 is +greater than 500; meanwhile, strings are ordered by the encoding of the first +byte, then the encoding of the second byte, and so on, so ``'2345'`` is less than ``'500'``. +Example: ``'A, B, C'``. + +.. _index-box_bin: + +**bin**. A bin (binary) value is not directly supported by Lua but there is +a Tarantool type ``varbinary`` which is encoded as MsgPack binary. +For an (advanced) example showing how to insert varbinary into a database, +see the Cookbook Recipe for :ref:`ffi_varbinary_insert `. +Example: ``"\65 \66 \67"``. + +.. _index-box_uuid: + +**uuid**. The Tarantool uuid type is used for +:ref:`Universally Unique Identifiers `. +Since version :doc:`2.4.1 ` Tarantool stores +``uuid`` values as a :ref:`MsgPack ext ` (Extension). + +Example: ``64d22e4d-ac92-4a23-899a-e5934af5479``. + +.. _index-box_array: + +**array**. An array is represented in Lua with ``{...}`` (`braces `_). +Examples: lists of numbers representing points in geometric figures: +``{10, 11}``, ``{3, 5, 9, 10}``. + +**table**. Lua tables with string keys are stored as MsgPack maps; +Lua tables with integer keys starting with 1 are stored as MsgPack arrays. +Nils may not be used in Lua tables; the workaround is to use +:ref:`box.NULL `. +Example: a ``box.space.tester:select()`` request will return a Lua table. + +**tuple**. A tuple is a light reference to a MsgPack array stored in the database. +It is a special type (cdata) to avoid conversion to a Lua table on retrieval. +A few functions may return tables with multiple tuples. For tuple examples, +see :ref:`box.tuple `. + +.. _index-box_scalar: + +**scalar**. Values in a scalar field can be boolean, integer, unsigned, double, +number, decimal, string, uuid, or varbinary; but not array, map, or tuple. +Examples: ``true``, ``1``, ``'xxx'``. + +.. _index-box_any: + +**any**. Values in a field of this type can be boolean, integer, unsigned, double, +number, decimal, string, uuid, varbinary, array, map, or tuple. +Examples: ``true``, ``1``, ``'xxx'``, ``{box.NULL, 0}``. + +Examples of insert requests with different field types: + +.. code-block:: tarantoolsession + + tarantool> box.space.K:insert{1,nil,true,'A B C',12345,1.2345} + --- + - [1, null, true, 'A B C', 12345, 1.2345] + ... + tarantool> box.space.K:insert{2,{['a']=5,['b']=6}} + --- + - [2, {'a': 5, 'b': 6}] + ... + tarantool> box.space.K:insert{3,{1,2,3,4,5}} + --- + - [3, [1, 2, 3, 4, 5]] + ... + +Indexed field types +~~~~~~~~~~~~~~~~~~~ + +To learn more about what values can be stored in indexed fields, read the +:ref:`Indexes ` section. + +.. _index-collation: + +Collations +---------- + +By default, when Tarantool compares strings, it uses the so-called +**binary collation**. +It only considers the numeric value of each byte in a string. +For example, the encoding of ``'A'`` (what used to be called the "ASCII value") is 65, +the encoding of ``'B'`` is 66, and the encoding of ``'a'`` is 98. +Therefore, if the string is encoded with ASCII or UTF-8, then ``'A' < 'B' < 'a'``. + +Binary collation is the best choice for fast deterministic simple maintenance and searching +with Tarantool indexes. + +But if you want the ordering that you see in phone books and dictionaries, +then you need Tarantool's optional collations, such as ``unicode`` and +``unicode_ci``, which allow for ``'a' < 'A' < 'B'`` and ``'a' == 'A' < 'B'`` +respectively. + +**The unicode and unicode_ci optional collations** use the ordering according to the +`Default Unicode Collation Element Table (DUCET) `_ +and the rules described in +`Unicode® Technical Standard #10 Unicode Collation Algorithm (UTS #10 UCA) `_. +The only difference between the two collations is about +`weights `_: + +* ``unicode`` collation observes L1, L2, and L3 weights (strength = 'tertiary'); +* ``unicode_ci`` collation observes only L1 weights (strength = 'primary'), so for example ``'a' == 'A' == 'á' == 'Á'``. + +As an example, take some Russian words: + +.. code-block:: text + + 'ЕЛЕ' + 'елейный' + 'ёлка' + 'еловый' + 'елозить' + 'Ёлочка' + 'ёлочный' + 'ЕЛь' + 'ель' + +...and show the difference in ordering and selecting by index: + +* with ``unicode`` collation: + + .. code-block:: tarantoolsession + + tarantool> box.space.T:create_index('I', {parts = {{field = 1, type = 'str', collation='unicode'}}}) + ... + tarantool> box.space.T.index.I:select() + --- + - - ['ЕЛЕ'] + - ['елейный'] + - ['ёлка'] + - ['еловый'] + - ['елозить'] + - ['Ёлочка'] + - ['ёлочный'] + - ['ель'] + - ['ЕЛь'] + ... + tarantool> box.space.T.index.I:select{'ЁлКа'} + --- + - [] + ... + +* with ``unicode_ci`` collation: + + .. code-block:: tarantoolsession + + tarantool> box.space.T:create_index('I', {parts = {{field = 1, type ='str', collation='unicode_ci'}}}) + ... + tarantool> box.space.T.index.I:select() + --- + - - ['ЕЛЕ'] + - ['елейный'] + - ['ёлка'] + - ['еловый'] + - ['елозить'] + - ['Ёлочка'] + - ['ёлочный'] + - ['ЕЛь'] + ... + tarantool> box.space.T.index.I:select{'ЁлКа'} + --- + - - ['ёлка'] + ... + + +In all, collation involves much more than these simple examples of +upper case / lower case and accented / unaccented equivalence in alphabets. +We also consider variations of the same character, non-alphabetic writing systems, +and special rules that apply for combinations of characters. + +For English, Russian, and most other languages and use cases, use the "unicode" and "unicode_ci" collations. +If you need Cyrillic letters 'Е' and 'Ё' to have the same level-1 weights, +try the Kyrgyz collation. + +**The tailored optional collations**: for other languages, Tarantool supplies tailored collations for every +modern language that has more than a million native speakers, and +for specialized situations such as the difference between dictionary +order and telephone book order. +Run ``box.space._collation:select()`` to see the complete list. + +The tailored collation names have the form +``unicode_[language code]_[strength]``, where language code is a standard +2-character or 3-character language abbreviation, and strength is ``s1`` +for "primary strength" (level-1 weights), ``s2`` for "secondary", ``s3`` for "tertiary". +Tarantool uses the same language codes as the ones in the "list of tailorable locales" on man pages of +`Ubuntu `_ and +`Fedora `_. +Charts explaining the precise differences from DUCET order are +in the +`Common Language Data Repository `_. + +.. _index-constraints: + +Constraints +----------- + +For better control over stored data, Tarantool supports **constraints** – user-defined +limitations on the values of certain fields or entire tuples. Together with data types, +constraints allow limiting the ranges of available field values both syntactically and semantically. + +For example, the field ``age`` typically has the ``number`` type, so it cannot store +strings or boolean values. However, it can still have values that don't make sense, +such as negative numbers. This is where constraints come to help. + +.. _index-constraint_types: + +Constraint types +~~~~~~~~~~~~~~~~ + +There are two types of constraints in Tarantool: + +* *Field constraints* check that the value being assigned to a field + satisfies a given condition. For example, ``age`` must be non-negative. + +* *Tuple constraints* check complex conditions that can involve all fields of + a tuple. For example, a tuple contains a date in three fields: + ``year``, ``month``, and ``day``. You can validate ``day`` values based on + the ``month`` value (and even ``year`` if you consider leap years). + +Field constraints work faster, while tuple constraints allow implementing +a wider range of limitations. + +.. _index-constraint_functions: + +Constraint functions +~~~~~~~~~~~~~~~~~~~~ + +Constraints use stored Lua functions, which must return ``true`` when the constraint +is satisfied. Other return values (including ``nil``) and exceptions make the +check fail and prevent tuple insertion or modification. + +To create a constraint function, use :ref:`func.create with function body `. + +Constraint functions take two parameters: + +* The field value and the constraint name for field constraints. + + .. code-block:: tarantoolsession + + tarantool> box.schema.func.create('check_age', + > {language = 'LUA', is_deterministic = true, body = 'function(f, c) return (f >= 0 and f < 150) end'}) + --- + ... + +* The tuple and the constraint name for tuple constraints. + + .. code-block:: tarantoolsession + + tarantool> box.schema.func.create('check_person', + > {language = 'LUA', is_deterministic = true, body = 'function(t, c) return (t.age >= 0 and #(t.name) > 3) end'}) + --- + ... + +.. warning:: + + Tarantool doesn't check field names used in tuple constraint functions. + If a field referenced in a tuple constraint gets renamed, this constraint will break + and prevent further insertions and modifications in the space. + +.. _index-constraint_apply: + +Creating constraints +~~~~~~~~~~~~~~~~~~~~ + +To create a constraint in a space, specify the corresponding function's name +in the ``constraint`` parameter: + +* Field constraints: when setting up the space format: + + .. code-block:: tarantoolsession + + tarantool> box.space.person:format({ + > {name = 'id', type = 'number'}, + > {name = 'name', type = 'string'}, + > {name = 'age', type = 'number', constraint = 'check_age'}, + > }) + +* Tuple constraints: when creating or altering a space: + + .. code-block:: tarantoolsession + + tarantool> box.schema.space.create('person', { engine = 'memtx', constraint = 'check_tuple'}) + +In both cases, ``constraint`` can contain multiple function names passed as a tuple. +Each constraint can have an optional name: + +.. code-block:: lua + + constraint = {'age_constraint' = 'check_age', 'name_constraint' = 'check_name'} + +.. note:: + + When adding a constraint to an existing space with data, Tarantool checks it + against the stored data. If there are fields or tuples that don't satisfy + the constraint, it won't be applied to the space. + + +.. _index-box_foreign_keys: + +Foreign keys +------------ + +**Foreign keys** provide links between related spaces, therefore maintaining the +`referential integrity `_ +of the database. + +Some fields can only contain values present in other spaces. For example, +shop orders always belong to existing customers. Hence, all values of the ``customer`` +field of the ``orders`` space must exist in the ``customers`` space. In this case, +``customers`` is a **parent space** for ``orders`` (its **child space**). When two +spaces are linked with a foreign key, each time a tuple is inserted or modified +in the child space, Tarantool checks that a corresponding value is present in +the parent space. + + +.. image:: foreign_key.svg + :align: center + +Foreign key types +~~~~~~~~~~~~~~~~~ + +There are two types of foreign keys in Tarantool: + +* *Field foreign keys* check that the value being assigned to a field + is present in a particular field of another space. For example, the ``customer`` + value in a tuple from the ``orders`` space must match an ``id`` stored in the ``customers`` space. + +* *Tuple foreign keys* check that multiple fields of a tuple have a match in + another space. For example, if the ``orders`` space has fields ``customer_id`` + and ``customer_name``, a tuple foreign key can check that the ``customers`` space + contains a tuple with both these values in the corresponding fields. + +Field foreign keys work faster while tuple foreign keys allow implementing +more strict references. + +Creating foreign keys +~~~~~~~~~~~~~~~~~~~~~ + +.. important:: + + For each foreign key, there must exist an index that includes all its fields. + +To create a foreign key in a space, specify the parent space and linked fields in the ``foreign_key`` parameter. +Fields can be referenced by name or by number: + +* Field foreign keys: when setting up the space format. + + .. code-block:: tarantoolsession + + tarantool> box.space.orders:format({ + > {name = 'id', type = 'number'}, + > {name = 'customer_id', foreign_key = {space = 'customers', field = 'id'}}, -- or field = 1 + > {name = 'price_total', type = 'number'}, + > }) + +* Tuple foreign keys: when creating or altering a space. Note that for foreign + keys with multiple fields there must exist an index that includes all these fields. + + .. code-block:: tarantoolsession + + tarantool> box.schema.space.create("orders", {foreign_key={space='customers', field={customer_id='id', customer_name='name'}}}) + --- + ... + tarantool> box.space.orders:format({ + > {name = "id", type = "number"}, + > {name = "customer_id" }, + > {name = "customer_name"}, + > {name = "price_total", type = "number"}, + > }) + +.. note:: + + Type can be omitted for foreign key fields because it's + defined in the parent space. + +Foreign keys can have an optional name. + +.. code-block:: lua + + foreign_key = {customer = {space = '...', field = {...}}} + +A space can have multiple tuple foreign keys. In this case, they all must have names. + +.. code-block:: lua + + foreign_key = {customer = {space = '...', field = {...} }, item = { space = '...', field = {...}}} + +Tarantool performs integrity checks upon data modifications in parent spaces. +If you try to remove a tuple referenced by a foreign key or an entire parent space, +you will get an error. + +.. important:: + + Renaming parent spaces or referenced fields may break the corresponding foreign + keys and prevent further insertions or modifications in the child spaces. diff --git a/doc/book/box/engines/index.rst b/doc/concepts/engines/index.rst similarity index 100% rename from doc/book/box/engines/index.rst rename to doc/concepts/engines/index.rst diff --git a/doc/book/box/engines/memtx.rst b/doc/concepts/engines/memtx.rst similarity index 96% rename from doc/book/box/engines/memtx.rst rename to doc/concepts/engines/memtx.rst index 672d7b1d3e..432a0e41b5 100644 --- a/doc/book/box/engines/memtx.rst +++ b/doc/concepts/engines/memtx.rst @@ -44,7 +44,7 @@ Within the TX thread, there is a memory area allocated for Tarantool to store da .. image:: memtx/arena2.svg Data is stored in :term:`spaces `. Spaces contain database records—:term:`tuples `. -To access and manipulate the data stored in spaces and tuples, Tarantool builds :doc:`indexes `. +To access and manipulate the data stored in spaces and tuples, Tarantool builds :doc:`indexes `. Special `allocators `__ manage memory allocations for spaces, tuples, and indexes within the Arena. The slab allocator is the main allocator used to store tuples. @@ -117,7 +117,7 @@ The possible types are TREE, HASH, BITSET, and RTREE. Select query are possible against secondary index keys as well as primary keys. Indexes can have multi-part keys. -For detailed information about indexes, refer to the :doc:`/book/box/indexes` page. +For detailed information about indexes, refer to the :doc:`/concepts/data_model/indexes` page. .. _memtx-replication: @@ -145,7 +145,7 @@ replicas. are not considered committed and are not responded to a client until they are replicated onto some number of replicas. -For more information on replication, refer to the :doc:`corresponding chapter `. +For more information on replication, refer to the :ref:`corresponding chapter `. .. _memtx-summary: diff --git a/doc/book/box/engines/memtx/arena2.svg b/doc/concepts/engines/memtx/arena2.svg similarity index 100% rename from doc/book/box/engines/memtx/arena2.svg rename to doc/concepts/engines/memtx/arena2.svg diff --git a/doc/book/box/engines/memtx/fibers-channels.svg b/doc/concepts/engines/memtx/fibers-channels.svg similarity index 100% rename from doc/book/box/engines/memtx/fibers-channels.svg rename to doc/concepts/engines/memtx/fibers-channels.svg diff --git a/doc/book/box/engines/memtx/iproto.svg b/doc/concepts/engines/memtx/iproto.svg similarity index 100% rename from doc/book/box/engines/memtx/iproto.svg rename to doc/concepts/engines/memtx/iproto.svg diff --git a/doc/book/box/engines/memtx/replica-xlogs.svg b/doc/concepts/engines/memtx/replica-xlogs.svg similarity index 100% rename from doc/book/box/engines/memtx/replica-xlogs.svg rename to doc/concepts/engines/memtx/replica-xlogs.svg diff --git a/doc/book/box/engines/memtx/snapshot03.svg b/doc/concepts/engines/memtx/snapshot03.svg similarity index 100% rename from doc/book/box/engines/memtx/snapshot03.svg rename to doc/concepts/engines/memtx/snapshot03.svg diff --git a/doc/book/box/engines/memtx/spaces_indexes.svg b/doc/concepts/engines/memtx/spaces_indexes.svg similarity index 100% rename from doc/book/box/engines/memtx/spaces_indexes.svg rename to doc/concepts/engines/memtx/spaces_indexes.svg diff --git a/doc/book/box/engines/memtx/wal.svg b/doc/concepts/engines/memtx/wal.svg similarity index 100% rename from doc/book/box/engines/memtx/wal.svg rename to doc/concepts/engines/memtx/wal.svg diff --git a/doc/book/box/engines/memtx_vinyl_diff.rst b/doc/concepts/engines/memtx_vinyl_diff.rst similarity index 100% rename from doc/book/box/engines/memtx_vinyl_diff.rst rename to doc/concepts/engines/memtx_vinyl_diff.rst diff --git a/doc/book/box/engines/vinyl.rst b/doc/concepts/engines/vinyl.rst similarity index 100% rename from doc/book/box/engines/vinyl.rst rename to doc/concepts/engines/vinyl.rst diff --git a/doc/book/box/engines/vinyl/1.svg b/doc/concepts/engines/vinyl/1.svg similarity index 100% rename from doc/book/box/engines/vinyl/1.svg rename to doc/concepts/engines/vinyl/1.svg diff --git a/doc/book/box/engines/vinyl/10.svg b/doc/concepts/engines/vinyl/10.svg similarity index 100% rename from doc/book/box/engines/vinyl/10.svg rename to doc/concepts/engines/vinyl/10.svg diff --git a/doc/book/box/engines/vinyl/11.svg b/doc/concepts/engines/vinyl/11.svg similarity index 100% rename from doc/book/box/engines/vinyl/11.svg rename to doc/concepts/engines/vinyl/11.svg diff --git a/doc/book/box/engines/vinyl/12.svg b/doc/concepts/engines/vinyl/12.svg similarity index 100% rename from doc/book/box/engines/vinyl/12.svg rename to doc/concepts/engines/vinyl/12.svg diff --git a/doc/book/box/engines/vinyl/13.svg b/doc/concepts/engines/vinyl/13.svg similarity index 100% rename from doc/book/box/engines/vinyl/13.svg rename to doc/concepts/engines/vinyl/13.svg diff --git a/doc/book/box/engines/vinyl/14.svg b/doc/concepts/engines/vinyl/14.svg similarity index 100% rename from doc/book/box/engines/vinyl/14.svg rename to doc/concepts/engines/vinyl/14.svg diff --git a/doc/book/box/engines/vinyl/15.svg b/doc/concepts/engines/vinyl/15.svg similarity index 100% rename from doc/book/box/engines/vinyl/15.svg rename to doc/concepts/engines/vinyl/15.svg diff --git a/doc/book/box/engines/vinyl/16.svg b/doc/concepts/engines/vinyl/16.svg similarity index 100% rename from doc/book/box/engines/vinyl/16.svg rename to doc/concepts/engines/vinyl/16.svg diff --git a/doc/book/box/engines/vinyl/17.svg b/doc/concepts/engines/vinyl/17.svg similarity index 100% rename from doc/book/box/engines/vinyl/17.svg rename to doc/concepts/engines/vinyl/17.svg diff --git a/doc/book/box/engines/vinyl/2.svg b/doc/concepts/engines/vinyl/2.svg similarity index 100% rename from doc/book/box/engines/vinyl/2.svg rename to doc/concepts/engines/vinyl/2.svg diff --git a/doc/book/box/engines/vinyl/3.svg b/doc/concepts/engines/vinyl/3.svg similarity index 100% rename from doc/book/box/engines/vinyl/3.svg rename to doc/concepts/engines/vinyl/3.svg diff --git a/doc/book/box/engines/vinyl/4.svg b/doc/concepts/engines/vinyl/4.svg similarity index 100% rename from doc/book/box/engines/vinyl/4.svg rename to doc/concepts/engines/vinyl/4.svg diff --git a/doc/book/box/engines/vinyl/5.svg b/doc/concepts/engines/vinyl/5.svg similarity index 100% rename from doc/book/box/engines/vinyl/5.svg rename to doc/concepts/engines/vinyl/5.svg diff --git a/doc/book/box/engines/vinyl/6.svg b/doc/concepts/engines/vinyl/6.svg similarity index 100% rename from doc/book/box/engines/vinyl/6.svg rename to doc/concepts/engines/vinyl/6.svg diff --git a/doc/book/box/engines/vinyl/7.svg b/doc/concepts/engines/vinyl/7.svg similarity index 100% rename from doc/book/box/engines/vinyl/7.svg rename to doc/concepts/engines/vinyl/7.svg diff --git a/doc/book/box/engines/vinyl/8.svg b/doc/concepts/engines/vinyl/8.svg similarity index 100% rename from doc/book/box/engines/vinyl/8.svg rename to doc/concepts/engines/vinyl/8.svg diff --git a/doc/book/box/engines/vinyl/9.svg b/doc/concepts/engines/vinyl/9.svg similarity index 100% rename from doc/book/box/engines/vinyl/9.svg rename to doc/concepts/engines/vinyl/9.svg diff --git a/doc/book/box/engines/vinyl/actor_threads.png b/doc/concepts/engines/vinyl/actor_threads.png similarity index 100% rename from doc/book/box/engines/vinyl/actor_threads.png rename to doc/concepts/engines/vinyl/actor_threads.png diff --git a/doc/book/box/engines/vinyl/classical_b_tree.png b/doc/concepts/engines/vinyl/classical_b_tree.png similarity index 100% rename from doc/book/box/engines/vinyl/classical_b_tree.png rename to doc/concepts/engines/vinyl/classical_b_tree.png diff --git a/doc/book/box/engines/vinyl/compaction.png b/doc/concepts/engines/vinyl/compaction.png similarity index 100% rename from doc/book/box/engines/vinyl/compaction.png rename to doc/concepts/engines/vinyl/compaction.png diff --git a/doc/book/box/engines/vinyl/curve.png b/doc/concepts/engines/vinyl/curve.png similarity index 100% rename from doc/book/box/engines/vinyl/curve.png rename to doc/concepts/engines/vinyl/curve.png diff --git a/doc/book/box/engines/vinyl/deletion_1.png b/doc/concepts/engines/vinyl/deletion_1.png similarity index 100% rename from doc/book/box/engines/vinyl/deletion_1.png rename to doc/concepts/engines/vinyl/deletion_1.png diff --git a/doc/book/box/engines/vinyl/deletion_2.png b/doc/concepts/engines/vinyl/deletion_2.png similarity index 100% rename from doc/book/box/engines/vinyl/deletion_2.png rename to doc/concepts/engines/vinyl/deletion_2.png diff --git a/doc/book/box/engines/vinyl/deletion_3.png b/doc/concepts/engines/vinyl/deletion_3.png similarity index 100% rename from doc/book/box/engines/vinyl/deletion_3.png rename to doc/concepts/engines/vinyl/deletion_3.png diff --git a/doc/book/box/engines/vinyl/dump_from_shadow.png b/doc/concepts/engines/vinyl/dump_from_shadow.png similarity index 100% rename from doc/book/box/engines/vinyl/dump_from_shadow.png rename to doc/concepts/engines/vinyl/dump_from_shadow.png diff --git a/doc/book/box/engines/vinyl/dumps.png b/doc/concepts/engines/vinyl/dumps.png similarity index 100% rename from doc/book/box/engines/vinyl/dumps.png rename to doc/concepts/engines/vinyl/dumps.png diff --git a/doc/book/box/engines/vinyl/factor_lsm.png b/doc/concepts/engines/vinyl/factor_lsm.png similarity index 100% rename from doc/book/box/engines/vinyl/factor_lsm.png rename to doc/concepts/engines/vinyl/factor_lsm.png diff --git a/doc/book/box/engines/vinyl/lsm.png b/doc/concepts/engines/vinyl/lsm.png similarity index 100% rename from doc/book/box/engines/vinyl/lsm.png rename to doc/concepts/engines/vinyl/lsm.png diff --git a/doc/book/box/engines/vinyl/lsm_single.png b/doc/concepts/engines/vinyl/lsm_single.png similarity index 100% rename from doc/book/box/engines/vinyl/lsm_single.png rename to doc/concepts/engines/vinyl/lsm_single.png diff --git a/doc/book/box/engines/vinyl/purge.png b/doc/concepts/engines/vinyl/purge.png similarity index 100% rename from doc/book/box/engines/vinyl/purge.png rename to doc/concepts/engines/vinyl/purge.png diff --git a/doc/book/box/engines/vinyl/range_search.png b/doc/concepts/engines/vinyl/range_search.png similarity index 100% rename from doc/book/box/engines/vinyl/range_search.png rename to doc/concepts/engines/vinyl/range_search.png diff --git a/doc/book/box/engines/vinyl/read_speed.png b/doc/concepts/engines/vinyl/read_speed.png similarity index 100% rename from doc/book/box/engines/vinyl/read_speed.png rename to doc/concepts/engines/vinyl/read_speed.png diff --git a/doc/book/box/engines/vinyl/search.png b/doc/concepts/engines/vinyl/search.png similarity index 100% rename from doc/book/box/engines/vinyl/search.png rename to doc/concepts/engines/vinyl/search.png diff --git a/doc/book/box/engines/vinyl/secondary.png b/doc/concepts/engines/vinyl/secondary.png similarity index 100% rename from doc/book/box/engines/vinyl/secondary.png rename to doc/concepts/engines/vinyl/secondary.png diff --git a/doc/concepts/index.rst b/doc/concepts/index.rst new file mode 100644 index 0000000000..60b72ec810 --- /dev/null +++ b/doc/concepts/index.rst @@ -0,0 +1,125 @@ +:fullwidth: + +.. _concepts: + +Concepts +======== + +Data model +---------- + +Tarantool is a NoSQL database. It stores data in :ref:`spaces `, +which can be thought of as tables in a relational database, and :ref:`tuples `, +which are analogous to rows. There are six basic :ref:`data operations ` in Tarantool. + +The platform allows :ref:`describing the data schema ` but does not require it. + +Tarantool supports highly customizable :ref:`indexes ` of various types. + +To ensure :ref:`data persistence ` and recover quickly in case of failure, +Tarantool uses mechanisms like the write-ahead log (WAL) and snapshots. + +For details, check the :ref:`Data model ` page. + +Fibers and cooperative multitasking +----------------------------------- + +Tarantool executes code in :ref:`fibers ` that are managed via +:ref:`cooperative multitasking `. +Learn more about Tarantool's :ref:`thread model `. + +For details, check the page :ref:`Fibers, yields, and cooperative multitasking `. + +Transactions +------------ + +Tarantool's ACID-compliant :ref:`transaction model ` lets the user choose +between two modes of transactions. + +The :ref:`default mode ` allows for fast monopolistic atomic transactions. +It doesn't support interactive transactions, and in case of an error, all transaction changes are rolled back. + +The :ref:`MVCC mode ` relies on a multi-version concurrency control engine +that allows yielding within a longer transaction. +This mode only works with the default in-memory :ref:`memtx ` storage engine. + +For details, check the :ref:`Transactions ` page. + +.. _concepts-application_server: + +Application server +------------------ + +Using Tarantool as an application server, you can write +applications in Lua, C, or C++. You can also create reusable :ref:`modules `. + +A convenient way to serve a clustered application on Tarantool is using :ref:`Tarantool Cartridge ` -- +a framework for developing, deploying, and managing applications. + +To increase the speed of code execution, Tarantool has a Lua Just-In-Time compiler (LuaJIT) on board. +LuaJIT compiles hot paths in the code -- paths that are used many times -- +thus making the application work faster. +To enable developers to work with LuaJIT, Tarantool provides tools like the :ref:`memory profiler ` +and the :ref:`getmetrics ` module. + +For details on Tarantool's modular structure, check the :ref:`Modules ` page. + +To learn how to use Tarantool as an application server, refer to the :ref:`guides ` in the How-to section. + +Sharding +-------- + +Tarantool implements database sharding via the ``vshard`` module. +For details, go to the :ref:`Sharding ` page. + +Triggers +-------- + +Tarantool allows specifying callback functions that run upon certain database events. +They can be useful for resolving replication conflicts. +For details, go to the :ref:`Triggers ` page. + +Replication +----------- + +Replication allows keeping the data in copies of the same database for better reliability. + +Several Tarantool instances can be organized in a replica set. +They communicate and transfer data via the :ref:`iproto ` binary protocol. +Learn more about Tarantool's :ref:`replication architecture `. + +By default, replication in Tarantool is asynchronous. +A transaction committed locally on the master node +may not get replicated onto other instances before the client receives a success response. +Thus, if the master reports success and then dies, the client might not see the result of the transaction. + +With :ref:`synchronous replication `, transactions on the master node are not considered committed +or successful before they are replicated onto a number of instances. This is slower, but more reliable. +Synchronous replication in Tarantool is based on an :ref:`implementation of the RAFT algorithm `. + +For details, check the :ref:`Replication ` section. + +Storage engines +--------------- + +A storage engine is a set of low-level routines that store and +retrieve values. Tarantool offers a choice of two storage engines: + +* :ref:`memtx ` is the in-memory storage engine used by default. +* :ref:`vinyl ` is the on-disk storage engine. + +For details, check the :ref:`Storage engines ` section. + + +.. toctree:: + :hidden: + + data_model/index + coop_multitasking + atomic + modules + Tarantool Cartridge + sharding/index + replication/index + triggers + engines/index diff --git a/doc/concepts/modules.rst b/doc/concepts/modules.rst new file mode 100644 index 0000000000..a61ca26ccf --- /dev/null +++ b/doc/concepts/modules.rst @@ -0,0 +1,51 @@ +.. _concepts-modules: + +Modules +======= + +Any logic that is used in Tarantool can be packaged as an application +(like a :ref:`Cartridge application `) or a reusable **module**. +A module is an optional library that enhances Tarantool functionality. +It can be used by Tarantool applications or other modules. +Modules allow for easier code management and hot code reload without restarting the Tarantool instance. +Like applications, modules in Tarantool can be written in Lua, +C, or C++. Lua modules are also referred to as "rocks". + +For example, here is a Lua module named ``mymodule.lua`` that exports +one function named ``myfun``: + +.. code-block:: lua + + local exports = {} + exports.myfun = function(input_string) + print('Hello', input_string) + end + return exports + +To launch the function ``myfun()`` -- from another module, from a Lua application, +or from Tarantool itself, -- save this module as a file, then load +this module with the ``require()`` directive and call the exported function. + +For example, here's a Lua application that uses ``myfun()`` from +``mymodule.lua``: + +.. code-block:: lua + + -- loading the module + local mymodule = require('mymodule') + + -- calling myfun() from within test() + local test = function() + mymodule.myfun() + end + +Tarantool provides an `extensive library `_ of compatible modules. +Install them using Tarantool's CLI utilities like :ref:`tarantoolctl ` +or :ref:`tt CLI `. +Some modules are also included in the Tarantool repository and can be installed +via your operating system's package manager. + +Learn how to: + +* :ref:`install a module ` +* :ref:`contribute a module ` diff --git a/doc/book/replication/cascade-problem-1.svg b/doc/concepts/replication/images/cascade-problem-1.svg similarity index 100% rename from doc/book/replication/cascade-problem-1.svg rename to doc/concepts/replication/images/cascade-problem-1.svg diff --git a/doc/book/replication/cascade-problem-2.svg b/doc/concepts/replication/images/cascade-problem-2.svg similarity index 100% rename from doc/book/replication/cascade-problem-2.svg rename to doc/concepts/replication/images/cascade-problem-2.svg diff --git a/doc/book/replication/cascade-to-ring.svg b/doc/concepts/replication/images/cascade-to-ring.svg similarity index 100% rename from doc/book/replication/cascade-to-ring.svg rename to doc/concepts/replication/images/cascade-to-ring.svg diff --git a/doc/book/replication/mm-3m-mesh-add.svg b/doc/concepts/replication/images/mm-3m-mesh-add.svg similarity index 100% rename from doc/book/replication/mm-3m-mesh-add.svg rename to doc/concepts/replication/images/mm-3m-mesh-add.svg diff --git a/doc/book/replication/mm-3m-mesh.svg b/doc/concepts/replication/images/mm-3m-mesh.svg similarity index 100% rename from doc/book/replication/mm-3m-mesh.svg rename to doc/concepts/replication/images/mm-3m-mesh.svg diff --git a/doc/book/replication/mr-1m-2r-mesh-add.svg b/doc/concepts/replication/images/mr-1m-2r-mesh-add.svg similarity index 100% rename from doc/book/replication/mr-1m-2r-mesh-add.svg rename to doc/concepts/replication/images/mr-1m-2r-mesh-add.svg diff --git a/doc/book/replication/mr-1m-2r-mesh.svg b/doc/concepts/replication/images/mr-1m-2r-mesh.svg similarity index 100% rename from doc/book/replication/mr-1m-2r-mesh.svg rename to doc/concepts/replication/images/mr-1m-2r-mesh.svg diff --git a/doc/book/replication/mr-1m-2r-oneway.svg b/doc/concepts/replication/images/mr-1m-2r-oneway.svg similarity index 100% rename from doc/book/replication/mr-1m-2r-oneway.svg rename to doc/concepts/replication/images/mr-1m-2r-oneway.svg diff --git a/doc/book/replication/no-cascade.svg b/doc/concepts/replication/images/no-cascade.svg similarity index 100% rename from doc/book/replication/no-cascade.svg rename to doc/concepts/replication/images/no-cascade.svg diff --git a/doc/book/replication/replication.svg b/doc/concepts/replication/images/replication.svg similarity index 100% rename from doc/book/replication/replication.svg rename to doc/concepts/replication/images/replication.svg diff --git a/doc/concepts/replication/index.rst b/doc/concepts/replication/index.rst new file mode 100644 index 0000000000..17194039f2 --- /dev/null +++ b/doc/concepts/replication/index.rst @@ -0,0 +1,28 @@ +:noindex: +:fullwidth: + +.. _replication: + +Replication +=========== + +Replication allows multiple Tarantool instances to work on copies of the same +databases. The databases are kept in sync because each instance can communicate +its changes to all the other instances. + +This chapter includes the following sections: + +.. toctree:: + :maxdepth: 2 + :numbered: 0 + + repl_architecture + repl_sync + repl_leader_elect + +For practical guides to replication, see the :ref:`How-to section `. +You can learn about :ref:`bootstrapping a replica set `, +:ref:`adding instances ` to the replica set +or :ref:`removing them `, +:ref:`using synchronous replication ` +and :ref:`managing leader elections `. diff --git a/doc/book/replication/repl_architecture.rst b/doc/concepts/replication/repl_architecture.rst similarity index 79% rename from doc/book/replication/repl_architecture.rst rename to doc/concepts/replication/repl_architecture.rst index 1faf901624..7ff3d8fe55 100644 --- a/doc/book/replication/repl_architecture.rst +++ b/doc/concepts/replication/repl_architecture.rst @@ -1,26 +1,24 @@ -.. _replication-architecture: +.. _replication-architecture: -================================================================================ Replication architecture -================================================================================ +======================== -.. _replication-mechanism: +.. _replication-mechanism: --------------------------------------------------------------------------------- Replication mechanism --------------------------------------------------------------------------------- +--------------------- A pack of instances which operate on copies of the same databases make up a **replica set**. Each instance in a replica set has a role, **master** or **replica**. A replica gets all updates from the master by continuously fetching and applying -its :ref:`write ahead log (WAL)`. Each record in the WAL represents a single -Tarantool data-change request such as :ref:`INSERT`, -:ref:`UPDATE` or :ref:`DELETE`, and is assigned +its :ref:`write ahead log (WAL) `. Each record in the WAL represents a single +Tarantool data-change request such as :ref:`INSERT `, +:ref:`UPDATE ` or :ref:`DELETE `, and is assigned a monotonically growing log sequence number (**LSN**). In essence, Tarantool replication is **row-based**: each data-change request is fully deterministic -and operates on a single :ref:`tuple`. However, unlike a classical row-based log, which +and operates on a single :ref:`tuple `. However, unlike a classical row-based log, which contains entire copies of the changed rows, Tarantool's WAL contains copies of the requests. For example, for UPDATE requests, Tarantool only stores the primary key of the row and the update operations, to save space. @@ -36,7 +34,7 @@ temporary spaces is stored in non-temporary system spaces, such as :ref:`box.space._space `. Data change operations on temporary spaces are not written to the WAL and are not replicated. -.. _replication-local: +.. _replication-local: Data change operations on **replication-local** spaces (spaces :doc:`created ` @@ -67,14 +65,14 @@ Each replica set is identified by a globally unique identifier, called the very first checkpoint, and is part of the checkpoint file. It is stored in system space :ref:`box.space._schema `. For example: -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession tarantool> box.space._schema:select{'cluster'} --- - - ['cluster', '6308acb9-9788-42fa-8101-2e0cb9d3c9a0'] ... -.. _replication-replica-id: +.. _replication-replica-id: Additionally, each instance in a replica set is assigned its own UUID, when it joins the replica set. It is called an **instance UUID** and is a globally unique @@ -90,7 +88,7 @@ used to refer to the instance in the write ahead log. It is called **instance id**. All identifiers are stored in system space :ref:`box.space._cluster `. For example: -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession tarantool> box.space._cluster:select{} --- @@ -104,7 +102,7 @@ Using instance IDs is also handy for tracking the state of the entire replica set. For example, :ref:`box.info.vclock ` describes the state of replication in regard to each connected peer. -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession tarantool> box.info.vclock --- @@ -119,31 +117,12 @@ the instance UUID and the replica set UUID values, rather than let the system generate them -- see the description of the :ref:`replicaset_uuid ` configuration parameter. -.. _replication-setup: +To learn how to enable replication, check the :ref:`how-to guide `. --------------------------------------------------------------------------------- -Replication setup --------------------------------------------------------------------------------- +.. _replication-roles: -To enable replication, you need to specify two parameters in a ``box.cfg{}`` -request: - -* :ref:`replication ` which defines the - replication source(s), and -* :ref:`read_only ` which is ``true`` for a - replica and ``false`` for a master. - -Both these parameters are "dynamic". This allows a replica to become a master -and vice versa on the fly with the help of a ``box.cfg{}`` request. - -Later we will give a detailed example of -:ref:`bootstrapping a replica set `. - -.. _replication-roles: - --------------------------------------------------------------------------------- Replication roles: master and replica --------------------------------------------------------------------------------- +------------------------------------- The replication role (master or replica) is set by the :ref:`read_only ` configuration parameter. The recommended @@ -152,21 +131,21 @@ role is "read_only" (replica) for all but one instance in the replica set. In a master-replica configuration, every change that happens on the master will be visible on the replicas, but not vice versa. -.. image:: mr-1m-2r-oneway.svg +.. image:: images/mr-1m-2r-oneway.svg :align: center A simple two-instance replica set with the master on one machine and the replica on a different machine provides two benefits: -* **failover**, because if the master goes down then the replica can take over, - and -* **load balancing**, because clients can connect to either the master or the - replica for read requests. +* **failover**, because if the master goes down then the replica can take over, + and +* **load balancing**, because clients can connect to either the master or the + replica for read requests. In a **master-master** configuration (also called "multi-master"), every change that happens on either instance will be visible on the other one. -.. image:: mm-3m-mesh.svg +.. image:: images/mm-3m-mesh.svg :align: center The failover benefit in this case is still present, and the load-balancing @@ -198,11 +177,10 @@ order in which the changes are applied. You can start learning more about conflict-free replicated data types `here `_. -.. _replication-topologies: +.. _replication-topologies: --------------------------------------------------------------------------------- Replication topologies: cascade, ring and full mesh --------------------------------------------------------------------------------- +--------------------------------------------------- Replication topology is set by the :ref:`replication ` configuration parameter. The recommended topology is a **full mesh**, because it @@ -211,7 +189,7 @@ makes potential failover easy. Some database products offer **cascading replication** topologies: creating a replica on a replica. Tarantool does not recommend such setup. -.. image:: no-cascade.svg +.. image:: images/no-cascade.svg :align: center The problem with a cascading replica set is that some instances have no @@ -221,14 +199,14 @@ is an entry in ``box.space._cluster`` system space with the replica set UUID. Without knowing the replica set UUID, a master refuses to accept connections from such instances when replication topology changes. Here is how this can happen: -.. image:: cascade-problem-1.svg +.. image:: images/cascade-problem-1.svg :align: center We have a chain of three instances. Instance #1 contains entries for instances #1 and #2 in its ``_cluster`` space. Instances #2 and #3 contain entries for instances #1, #2 and #3 in their ``_cluster`` spaces. -.. image:: cascade-problem-2.svg +.. image:: images/cascade-problem-2.svg :align: center Now instance #2 is faulty. Instance #3 tries connecting to instance #1 as its @@ -237,7 +215,7 @@ instance #3. **Ring replication** topology is, however, supported: -.. image:: cascade-to-ring.svg +.. image:: images/cascade-to-ring.svg :align: center So, if you need a cascading topology, you may first create a ring to ensure all @@ -247,7 +225,7 @@ desire. A stock recommendation for a master-master replication topology, however, is a **full mesh**: -.. image:: mm-3m-mesh.svg +.. image:: images/mm-3m-mesh.svg :align: center You then can decide where to locate instances of the mesh -- within the same @@ -260,3 +238,13 @@ the instances failing in one of the data centers, as well as in case of an entire data center failure. The maximal number of replicas in a mesh is 32. + +Orphan status +------------- + +During ``box.cfg()``, an instance will try to join all masters listed +in :ref:`box.cfg.replication `. +If the instance does not succeed with at least +the number of masters specified in +:ref:`replication_connect_quorum `, +then it will switch to :ref:`orphan status `. diff --git a/doc/book/replication/repl_leader_elect.rst b/doc/concepts/replication/repl_leader_elect.rst similarity index 59% rename from doc/book/replication/repl_leader_elect.rst rename to doc/concepts/replication/repl_leader_elect.rst index 4d3bdf1b40..af12a9594e 100644 --- a/doc/book/replication/repl_leader_elect.rst +++ b/doc/concepts/replication/repl_leader_elect.rst @@ -10,6 +10,9 @@ This functionality increases the fault tolerance of the systems built on the base of Tarantool and decreases dependency on the external tools for replica set management. +To learn how to configure and monitor automated leader elections, +check the :ref:`how-to guide `. + The following topics are described below: .. contents:: @@ -131,109 +134,3 @@ Term numbers also work as a kind of a filter. For example, you can be sure that if election is enabled on two nodes and ``node1`` has the term number less than ``node2``, then ``node2`` won't accept any transactions from ``node1``. - -.. _repl_leader_elect_config: - -Configuration -------------- - -.. code-block:: console - - box.cfg({ - election_mode = , - election_timeout = , - replication_timeout = , - replication_synchro_quorum = , - election_fencing_enabled = - }) - -* ``election_mode`` -- specifies the role of a node in the leader election - process. For the details, refer to the :ref:`option description ` - in the configuration reference. -* ``election_timeout`` -- specifies the timeout between election rounds if the - previous round ended up with a split vote. For the details, refer to the - :ref:`option description ` in the configuration - reference. -* ``replication_timeout`` -- reuse of the :ref:`replication_timeout ` - configuration option for the purpose of the leader election process. - Heartbeats sent by an active leader have a timeout after which a new election - starts. Heartbeats are sent once per seconds. - Default value is ``1``. The leader is considered dead if it hasn't sent any - heartbeats for the period of ``replication_timeout * 4``. -* ``replication_synchro_quorum`` -- reuse of the :ref:`replication_synchro_quorum ` - option for the purpose of configuring the election quorum. The default value is ``1``, - meaning that each node becomes a leader immediately after voting for itself. - It is the best to set up this option value to the ``( / 2) + 1``. - Otherwise, there is no guarantee that there is only one leader at a time. -* ``election_fencing_enabled`` -- switches the :ref:`leader fencing mode ` on and off. - For the details, refer to the :ref:`option description ` in the configuration reference. - -Besides, it is important to know that -being a leader is not the only requirement for a node to be writable. -A leader node should have its :ref:`read_only ` option set -to ``false`` (``box.cfg{read_only = false}``), -and its :ref:`connectivity quorum ` -should be satisfied (``box.cfg{replication_connect_quorum = }``) -or disabled (``box.cfg{replication_connect_quorum = 0}``). - -Nothing prevents from setting the ``read_only`` option to ``true``, -but the leader just won't be writable then. The option doesn't affect the -election process itself, so a read-only instance can still vote and become -a leader. - -.. _repl_leader_elect_monitoring: - -Monitoring ----------- - -To monitor the current state of a node regarding the leader election, you can -use the ``box.info.election`` function. -For details, -refer to the :doc:`function description `. - -**Example:** - -.. code-block:: console - - tarantool> box.info.election - --- - - state: follower - vote: 0 - leader: 0 - term: 1 - ... - -The Raft-based election implementation logs all its actions -with the ``RAFT:`` prefix. The actions are new Raft message handling, -node state changing, voting, term bumping, and so on. - -.. _repl_leader_elect_important: - -Important notes ---------------- - -Leader election won't work correctly if the election quorum is set to less or equal -than `` / 2`` because in that case, a split vote can lead to -a state when two leaders are elected at once. - -For example, let's assume there are five nodes. When quorum is set to ``2``, ``node1`` -and ``node2`` can both vote for ``node1``. ``node3`` and ``node4`` can both vote -for ``node5``. In this case, ``node1`` and ``node5`` both win the election. -When the quorum is set to the cluster majority, that is -``( / 2) + 1`` or bigger, the split vote is not possible. - -That should be considered when adding new nodes. -If the majority value is changing, it's better to update the quorum on all the existing nodes -before adding a new one. - -Also, the automated leader election won't bring many benefits in terms of data -safety when used *without* :ref:`synchronous replication `. -If the replication is asynchronous and a new leader gets elected, -the old leader is still active and considers itself the leader. -In such case, nothing stops -it from accepting requests from clients and making transactions. -Non-synchronous transactions will be successfully committed because -they won't be checked against the quorum of replicas. -Synchronous transactions will fail because they won't be able -to collect the quorum -- most of the replicas will reject -these old leader's transactions since it is not a leader anymore. diff --git a/doc/concepts/replication/repl_sync.rst b/doc/concepts/replication/repl_sync.rst new file mode 100644 index 0000000000..3f5389ad7a --- /dev/null +++ b/doc/concepts/replication/repl_sync.rst @@ -0,0 +1,69 @@ +.. _repl_sync: + +Synchronous replication +======================= + +Overview +-------- + +By default, replication in Tarantool is **asynchronous**: if a transaction +is committed locally on a master node, it does not mean it is replicated onto any +replicas. If a master responds success to a client and then dies, after failover +to a replica, from the client's point of view the transaction will disappear. + +**Synchronous** replication exists to solve this problem. Synchronous transactions +are not considered committed and are not responded to a client until they are +replicated onto some number of replicas. + +To learn how to enable and use synchronous replication, +check the :ref:`guide `. + +Synchronous and asynchronous transactions +----------------------------------------- + +A killer feature of Tarantool's synchronous replication is its being *per-space*. +So, if you need it only rarely for some critical data changes, you won't pay for +it in performance terms. + +When there is more than one synchronous transaction, they all wait for being +replicated. Moreover, if an asynchronous transaction appears, it will +also be blocked by the existing synchronous transactions. This behavior is very +similar to a regular queue of asynchronous transactions because all the transactions +are committed in the same order as they make the ``box.commit()`` call. +So, here comes **the commit rule**: +transactions are committed in the same order as they make +the ``box.commit()`` call—regardless of being synchronous or asynchronous. + +If one of the waiting synchronous transactions times out and is rolled back, it +will first roll back all the newer pending transactions. Again, just like how +asynchronous transactions are rolled back when WAL write fails. +So, here comes **the rollback rule:** +transactions are always rolled back in the order reversed from the one they +make the ``box.commit()`` call—regardless of being synchronous or asynchronous. + +One more important thing is that if an asynchronous transaction is blocked by +a synchronous transaction, it does not become synchronous as well. +This just means it will wait for the synchronous transaction to be committed. +But once it is done, the asynchronous transaction will be committed +immediately—it won't wait for being replicated itself. + +Limitations and known problems +------------------------------ + +Until version :doc:`2.5.2 `, +there was no way to enable synchronous replication for +existing spaces, but since 2.5.2 it can be enabled by +:ref:`space_object:alter({is_sync = true}) `. + +Synchronous transactions work only for master-slave topology. You can have multiple +replicas, anonymous replicas, but only one node can make synchronous transactions. + +Since Tarantool :doc:`2.10.0 `, anonymous replicas do not participate in the quorum. + +Leader election +--------------- + +Starting from version :doc:`2.6.1 `, +Tarantool has the built-in functionality +managing automated leader election in a replica set. For more information, +refer to the :ref:`corresponding chapter `. diff --git a/doc/reference/reference_rock/vshard/bucket.svg b/doc/concepts/sharding/bucket.svg similarity index 100% rename from doc/reference/reference_rock/vshard/bucket.svg rename to doc/concepts/sharding/bucket.svg diff --git a/doc/reference/reference_rock/vshard/buckets.svg b/doc/concepts/sharding/buckets.svg similarity index 100% rename from doc/reference/reference_rock/vshard/buckets.svg rename to doc/concepts/sharding/buckets.svg diff --git a/doc/reference/reference_rock/vshard/hierarchy.png b/doc/concepts/sharding/hierarchy.png similarity index 100% rename from doc/reference/reference_rock/vshard/hierarchy.png rename to doc/concepts/sharding/hierarchy.png diff --git a/doc/reference/reference_rock/vshard/_includes/vshard_summary.rst b/doc/concepts/sharding/index.rst similarity index 81% rename from doc/reference/reference_rock/vshard/_includes/vshard_summary.rst rename to doc/concepts/sharding/index.rst index bae4ceef0e..c447f70beb 100644 --- a/doc/reference/reference_rock/vshard/_includes/vshard_summary.rst +++ b/doc/concepts/sharding/index.rst @@ -1,4 +1,8 @@ -.. _vshard-summary: +.. _sharding: +.. _vshard-summary: + +Sharding +======== Scaling databases in a growing project is often considered one of the most challenging issues. Once a single server cannot withstand the load, scaling @@ -30,3 +34,14 @@ a server instance is active and available for all types of requests, or a failov occurred and the instance accepts only read requests. The ``vshard`` module provides router and storage API (public and internal) for sharding-aware applications. + +Check out the :ref:`quick start guide ` or +learn more about :ref:`how sharding works ` in Tarantool: + +.. toctree:: + :maxdepth: 2 + + vshard_architecture + +You can also find out more about :ref:`sharding administration ` +or dive into the ``vshard`` configuration and API :ref:`reference `. diff --git a/doc/reference/reference_rock/vshard/master_replica.svg b/doc/concepts/sharding/master_replica.svg similarity index 100% rename from doc/reference/reference_rock/vshard/master_replica.svg rename to doc/concepts/sharding/master_replica.svg diff --git a/doc/reference/reference_rock/vshard/schema.svg b/doc/concepts/sharding/schema.svg similarity index 100% rename from doc/reference/reference_rock/vshard/schema.svg rename to doc/concepts/sharding/schema.svg diff --git a/doc/reference/reference_rock/vshard/states.svg b/doc/concepts/sharding/states.svg similarity index 100% rename from doc/reference/reference_rock/vshard/states.svg rename to doc/concepts/sharding/states.svg diff --git a/doc/reference/reference_rock/vshard/vbuckets.svg b/doc/concepts/sharding/vbuckets.svg similarity index 100% rename from doc/reference/reference_rock/vshard/vbuckets.svg rename to doc/concepts/sharding/vbuckets.svg diff --git a/doc/reference/reference_rock/vshard/vshard_architecture.rst b/doc/concepts/sharding/vshard_architecture.rst similarity index 63% rename from doc/reference/reference_rock/vshard/vshard_architecture.rst rename to doc/concepts/sharding/vshard_architecture.rst index 2688cbb587..d9ebc9d08a 100644 --- a/doc/reference/reference_rock/vshard/vshard_architecture.rst +++ b/doc/concepts/sharding/vshard_architecture.rst @@ -1,14 +1,12 @@ -.. _vshard-architecture: +.. _vshard-architecture: -=============================================================================== Architecture -=============================================================================== +============ -.. _vshard-architecture-overview: +.. _vshard-architecture-overview: ------------------------------------------------------------------------------- Overview ------------------------------------------------------------------------------- +-------- Consider a distributed Tarantool cluster that consists of subclusters called **shards**, each storing some part of data. Each shard, in its turn, constitutes @@ -29,7 +27,7 @@ the granularity of rebalancing. Each shard stores a unique subset of buckets, which means that a bucket cannot belong to several shards at once, as illustrated below: -.. image:: bucket.svg +.. image:: bucket.svg :align: center This shard-to-bucket mapping is stored in a table in one of Tarantool’s system @@ -54,11 +52,10 @@ transparent for the application. Storing the mapping table in a system space ensures sharding is performed consistently in case of a failover, as all the replicas in a shard share a common table state. -.. _vshard-vbuckets: +.. _vshard-vbuckets: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Virtual buckets -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +~~~~~~~~~~~~~~~ The sharded dataset is partitioned into a large number of abstract nodes called **virtual buckets** (further just **buckets**). @@ -67,7 +64,7 @@ The dataset is partitioned using the sharding key (or **bucket id**, in Tarantoo terminology). Bucket id is a number from 1 to N, where N is the total number of buckets. -.. image:: buckets.svg +.. image:: buckets.svg :align: center Each replica set stores a unique subset of buckets. One bucket cannot belong to @@ -79,33 +76,31 @@ initial cluster configuration. Every space you plan to shard must have a numeric field containing bucket id-s. This field must comply with the following requirements: -* The field's data type can be: unsigned, number or integer. -* The field must be not nullable. -* The field must be indexed by the :ref:`shard_index `. - The default name for this index is ``bucket_id``. +* The field's data type can be: unsigned, number or integer. +* The field must be not nullable. +* The field must be indexed by the :ref:`shard_index `. + The default name for this index is ``bucket_id``. See the :ref:`configuration example `. -.. _vshard-structure: +.. _vshard-structure: ------------------------------------------------------------------------------- Structure ------------------------------------------------------------------------------- +--------- A sharded cluster in Tarantool consists of: -* storages, -* routers, -* and a rebalancer. +* storages, +* routers, +* and a rebalancer. -.. image:: schema.svg +.. image:: schema.svg :align: center -.. _vshard-architecture-storage: +.. _vshard-architecture-storage: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Storage -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +~~~~~~~ **Storage** is a node storing a subset of the dataset. Multiple replicated (for redundancy) storages comprise a **replica set** (also called **shard**). @@ -114,14 +109,13 @@ Each storage in a replica set has a role, **master** or **replica**. A master processes read and write requests. A replica processes read requests but cannot process write requests. -.. image:: master_replica.svg +.. image:: master_replica.svg :align: center -.. _vshard-architecture-router: +.. _vshard-architecture-router: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Router -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +~~~~~~ **Router** is a standalone software component that routes read and write requests from the client application to shards. @@ -130,9 +124,9 @@ All requests from the application come to the sharded cluster through a ``router The ``router`` keeps the topology of a sharded cluster transparent for the application, thus keeping the application unaware of: -* the number and location of shards, -* data rebalancing process, -* the fact and the process of a failover that occurred after a replica's failure. +* the number and location of shards, +* data rebalancing process, +* the fact and the process of a failover that occurred after a replica's failure. A router can also calculate a bucket id on its own provided that the application clearly defines rules for calculating a bucket id based on the request data. @@ -154,30 +148,28 @@ It is assumed that the application itself handles all the interactions with such systems and passes sharding parameters. That said, the configuration can be changed dynamically - for example, when adding or deleting one or several shards: -#. To add a new shard to the cluster, a system administrator first changes the - configuration of all the routers and then the configuration of all the storages. -#. The new shard becomes available to the storage layer for rebalancing. -#. As a result of rebalancing, one of the vbuckets is moved to the new shard. -#. When trying to access the vbucket, a router receives a special error code - that specifies the new vbucket location. +#. To add a new shard to the cluster, a system administrator first changes the + configuration of all the routers and then the configuration of all the storages. +#. The new shard becomes available to the storage layer for rebalancing. +#. As a result of rebalancing, one of the vbuckets is moved to the new shard. +#. When trying to access the vbucket, a router receives a special error code + that specifies the new vbucket location. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CRUD (create, read, update, delete) operations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CRUD operations can be: -* executed in a stored procedure inside a storage, or -* initialized by the application. +* executed in a stored procedure inside a storage, or +* initialized by the application. In any case, the application must include the operation bucket id in a request. When executing an INSERT request, the operation bucket id is stored in a newly created tuple. In other cases, it is checked if the specified operation bucket id matches the bucket id of a tuple being modified. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SELECT requests -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^ Since a storage is not aware of the mapping between a bucket id and a primary key, all the SELECT requests executed in stored procedures inside a storage are @@ -185,26 +177,24 @@ only executed locally. Those SELECT requests that were initialized by the application are forwarded to a router. Then, if the application has passed a bucket id, a router uses it for shard calculation. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Calling stored procedures -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^^ There are several ways of calling stored procedures in cluster replica sets. Stored procedures can be called: -* on a specific vbucket located in a replica set (in this case, it is necessary - to differentiate between read and write procedures, as write procedures are not - applicable to vbuckets that are being migrated), or -* without specifying any particular vbucket. +* on a specific vbucket located in a replica set (in this case, it is necessary + to differentiate between read and write procedures, as write procedures are not + applicable to vbuckets that are being migrated), or +* without specifying any particular vbucket. All the routing validity checks performed for sharded DML operations hold true for vbucket-bound stored procedures as well. .. _vshard-rebalancer: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Rebalancer -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +---------- **Rebalancer** is a background rebalancing process that ensures an even distribution of buckets across the shards. During rebalancing, buckets are being @@ -216,15 +206,14 @@ of a replica set exceeds a disbalance threshold specified in the configuration. The disbalance threshold is calculated as follows: -.. code-block:: none +.. code-block:: none |etalon_bucket_number - real_bucket_number| / etalon_bucket_number * 100 -.. _vshard-migrate-buckets: +.. _vshard-migrate-buckets: ------------------------------------------------------------------------------- Migration of buckets ------------------------------------------------------------------------------- +-------------------- A replica set from which the bucket is being migrated is called a **source** ; a target replica set to which the bucket is being migrated is called a **destination**. @@ -234,58 +223,57 @@ replica set can neither receive new buckets nor migrate its own buckets. While a bucket is being migrated, it can have different states: -* ACTIVE – the bucket is available for read and write requests. -* PINNED – the bucket is locked for migrating to another replica set. Otherwise - pinned buckets are similar to buckets in the ACTIVE state. -* SENDING – the bucket is currently being copied to the destination replica set; - read requests to the source replica set are still processed. -* RECEIVING – the bucket is currently being filled; all requests to it are rejected. -* SENT – the bucket was migrated to the destination replica set. The `router` - uses the SENT state to calculate the new location of the bucket. A bucket in - the SENT state goes to the GARBAGE state automatically after BUCKET_SENT_GARBAGE_DELAY - seconds, which by default is :ref:`0.5 seconds `. -* GARBAGE – the bucket was already migrated to the destination replica set during - rebalancing; or the bucket was initially in the RECEIVING state, but some error - occurred during the migration. +* ACTIVE – the bucket is available for read and write requests. +* PINNED – the bucket is locked for migrating to another replica set. Otherwise + pinned buckets are similar to buckets in the ACTIVE state. +* SENDING – the bucket is currently being copied to the destination replica set; + read requests to the source replica set are still processed. +* RECEIVING – the bucket is currently being filled; all requests to it are rejected. +* SENT – the bucket was migrated to the destination replica set. The `router` + uses the SENT state to calculate the new location of the bucket. A bucket in + the SENT state goes to the GARBAGE state automatically after BUCKET_SENT_GARBAGE_DELAY + seconds, which by default is :ref:`0.5 seconds `. +* GARBAGE – the bucket was already migrated to the destination replica set during + rebalancing; or the bucket was initially in the RECEIVING state, but some error + occurred during the migration. Buckets in the GARBAGE state are deleted by the garbage collector. -.. image:: states.svg +.. image:: states.svg :align: center Migration is performed as follows: -1. At the destination replica set, a new bucket is created and assigned the RECEIVING - state, the data copying starts, and the bucket rejects all requests. -2. The source bucket in the source replica set is assigned the SENDING state, and - the bucket continues to process read requests. -3. Once the data is copied, the bucket on the source replica set is assigned the SENT - and it starts rejecting all requests. -4. The bucket on the destination replica set is assigned the ACTIVE state and starts - accepting all requests. +1. At the destination replica set, a new bucket is created and assigned the RECEIVING + state, the data copying starts, and the bucket rejects all requests. +2. The source bucket in the source replica set is assigned the SENDING state, and + the bucket continues to process read requests. +3. Once the data is copied, the bucket on the source replica set is assigned the SENT + and it starts rejecting all requests. +4. The bucket on the destination replica set is assigned the ACTIVE state and starts + accepting all requests. -.. NOTE:: +.. note:: There is a specific error ``vshard.error.code.TRANSFER_IS_IN_PROGRESS`` that returns in case a request tries to perform an action not applicable to a bucket which is being relocated. You need to retry the request in this case. -.. _vshard-bucket-space: +.. _vshard-bucket-space: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -The `_bucket` system space -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +The _bucket system space +~~~~~~~~~~~~~~~~~~~~~~~~ The ``_bucket`` system space of each replica set stores the ids of buckets present in the replica set. The space contains the following fields: -* ``bucket`` – bucket id -* ``status`` – state of the bucket -* ``destination`` – UUID of the destination replica set +* ``bucket`` – bucket id +* ``status`` – state of the bucket +* ``destination`` – UUID of the destination replica set An example of ``_bucket.select{}``: -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession --- - - [1, ACTIVE, abfe2ef6-9d11-4756-b668-7f5bc5108e2a] @@ -298,9 +286,8 @@ the destination replica set UUID is equal to ``NULL``. .. _vshard-routing-table: -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ The routing table -++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +~~~~~~~~~~~~~~~~~ А routing table on the ``router`` stores the map of all bucket ids to replica sets. It ensures the consistency of sharding in case of failover. @@ -318,9 +305,8 @@ makes rebalancing transparent for the application. .. _vshard-process-requests: ------------------------------------------------------------------------------- Processing requests ------------------------------------------------------------------------------- +------------------- Requests to the database can be performed by the application or using stored procedures. Either way, the bucket id should be explicitly specified in the request. @@ -329,107 +315,106 @@ All requests are forwarded to the ``router`` first. The only operation supported by the ``router`` is ``call``. The operation is performed via the ``vshard.router.call()`` function: -.. code-block:: lua +.. code-block:: lua result = vshard.router.call(, , , {}, {}) Requests are processed as follows: -1. The ``router`` uses the bucket id to search for a replica set with the - corresponding bucket in the routing table. +1. The ``router`` uses the bucket id to search for a replica set with the + corresponding bucket in the routing table. - If the map of the bucket id to the replica set is not known to the ``router`` - (the discovery fiber hasn’t filled the table yet), the ``router`` makes requests - to all ``storages`` to find out where the bucket is located. -2. Once the bucket is located, the shard checks: + If the map of the bucket id to the replica set is not known to the ``router`` + (the discovery fiber hasn’t filled the table yet), the ``router`` makes requests + to all ``storages`` to find out where the bucket is located. +2. Once the bucket is located, the shard checks: - * whether the bucket is stored in the ``_bucket`` system space of the replica set; - * whether the bucket is ACTIVE or PINNED (for a read request, it can also be SENDING). + * whether the bucket is stored in the ``_bucket`` system space of the replica set; + * whether the bucket is ACTIVE or PINNED (for a read request, it can also be SENDING). -3. If all the checks succeed, the request is executed. Otherwise, it is terminated - with the error: ``“wrong bucket”``. +3. If all the checks succeed, the request is executed. Otherwise, it is terminated + with the error: ``“wrong bucket”``. -.. _vshard-glossary: +.. _vshard-glossary: -------------------------------------------------------------------------------- Glossary -------------------------------------------------------------------------------- +-------- -.. glossary:: +.. glossary:: - .. vshard-vertical_scaling: + .. vshard-vertical_scaling: **Vertical scaling** Adding more power to a single server: using a more powerful CPU, adding more capacity to RAM, adding more storage space, etc. - .. vshard-horizontal_scaling: + .. vshard-horizontal_scaling: **Horizontal scaling** Adding more servers to the pool of resources, then partitioning and distributing a dataset across the servers. - .. vshard-sharding: + .. vshard-sharding: **Sharding** A database architecture that allows partitioning a dataset using a sharding key and distributing a dataset across multiple servers. Sharding is a special case of horizontal scaling. - .. vshard-node: + .. vshard-node: **Node** A virtual or physical server instance. - .. vshard-cluster: + .. vshard-cluster: **Cluster** A set of nodes that make up a single group. - .. vshard-storage: + .. vshard-storage: **Storage** A node storing a subset of a dataset. - .. vshard-replica_set: + .. vshard-replica_set: **Replica set** A set of storage nodes storing copies of a dataset. Each storage in a replica set has a role, master or replica. - .. vshard-master: + .. vshard-master: **Master** A storage in a replica set processing read and write requests. - .. vshard-replica: + .. vshard-replica: **Replica** A storage in a replica set processing only read requests. - .. vshard-read_requests: + .. vshard-read_requests: **Read requests** Read-only requests, that is, select requests. - .. vshard-write_requests: + .. vshard-write_requests: **Write requests** Data-change operations, that is create, read, update, delete requests. - .. vshard-bucket: + .. vshard-bucket: **Buckets (virtual buckets)** The abstract virtual nodes into which the dataset is partitioned by the sharding key (bucket id). - .. vshard-bucket-id: + .. vshard-bucket-id: **Bucket id** A sharding key defining which bucket belongs to which replica set. A bucket id may be calculated from a :ref:`hash key `. - .. vshard-router: + .. vshard-router: **Router** A proxy server responsible for routing requests from an application to diff --git a/doc/book/box/triggers.rst b/doc/concepts/triggers.rst similarity index 100% rename from doc/book/box/triggers.rst rename to doc/concepts/triggers.rst diff --git a/doc/book/app_server/creating_app/yields.svg b/doc/concepts/yields.svg similarity index 100% rename from doc/book/app_server/creating_app/yields.svg rename to doc/concepts/yields.svg diff --git a/doc/contributing/docs/markup/admonitions.rst b/doc/contributing/docs/markup/admonitions.rst index 118db7922c..0eff1aa23b 100644 --- a/doc/contributing/docs/markup/admonitions.rst +++ b/doc/contributing/docs/markup/admonitions.rst @@ -44,7 +44,7 @@ In Tarantool we have 3 variants of css-style for admonitions: This block contains essential information that the user should know while doing something. - For example, the block :doc:`in Getting Started with Docker ` is used to warn the user against + For example, the block :doc:`in Getting Started with Docker ` is used to warn the user against closing the terminal window. * Custom admonition: diff --git a/doc/contributing/index.rst b/doc/contributing/index.rst index 358f936d76..9ec8df5384 100644 --- a/doc/contributing/index.rst +++ b/doc/contributing/index.rst @@ -12,4 +12,5 @@ Contributing contributing release_notes ../dev_guide/building_from_source + ../dev_guide/contributing_module ../dev_guide/guidelines_index diff --git a/doc/book/app_server/contributing_module.rst b/doc/dev_guide/contributing_module.rst similarity index 90% rename from doc/book/app_server/contributing_module.rst rename to doc/dev_guide/contributing_module.rst index 6c33120185..66482f3436 100644 --- a/doc/book/app_server/contributing_module.rst +++ b/doc/dev_guide/contributing_module.rst @@ -4,13 +4,14 @@ Contributing a module ================================================================================ -We have already discussed -:ref:`how to create a simple module in Lua for local usage `. -Now let's discuss how to create a more advanced Tarantool module and then get it +This page discusses how to create a Tarantool module and then get it published on `Tarantool rocks page `_ and included in `official Tarantool images `_ for Docker. +To learn how to create a simple module in Lua for local usage, check the corresponding +:ref:`how-to guide `. + To help our contributors, we have created `modulekit `_, a set of templates for creating Tarantool modules in Lua and C. diff --git a/doc/dev_guide/index.rst b/doc/dev_guide/index.rst index 191a5d65f8..8b1e4fd1bd 100644 --- a/doc/dev_guide/index.rst +++ b/doc/dev_guide/index.rst @@ -13,4 +13,6 @@ Contributor's Guide reference_capi/index internals/index building_from_source + ../book/admin/modules + contributing_module guidelines_index diff --git a/doc/dev_guide/internals/box_protocol.rst b/doc/dev_guide/internals/box_protocol.rst index de4f85eed9..8ac8cdecc4 100644 --- a/doc/dev_guide/internals/box_protocol.rst +++ b/doc/dev_guide/internals/box_protocol.rst @@ -1727,7 +1727,7 @@ and version :doc:`2.8.2 `. FLAGS ~~~~~ -For replication of :doc:`synchronous transactions ` +For replication of :ref:`synchronous transactions ` a header may contain a key = IPROTO_FLAGS and an MP_UINT value = one or more bits: IPROTO_FLAG_COMMIT or IPROTO_FLAG_WAIT_SYNC or IPROTO_FLAG_WAIT_ACK. diff --git a/doc/dev_guide/internals/index.rst b/doc/dev_guide/internals/index.rst index e8dcb73580..05d5a790e7 100644 --- a/doc/dev_guide/internals/index.rst +++ b/doc/dev_guide/internals/index.rst @@ -3,9 +3,8 @@ .. _internals: -================================================================================ Internals -================================================================================ +========= .. toctree:: :maxdepth: 2 @@ -14,4 +13,4 @@ Internals msgpack_extensions file_formats recovery_internals - replication_internals + replication/index diff --git a/doc/dev_guide/internals/replication/index.rst b/doc/dev_guide/internals/replication/index.rst new file mode 100644 index 0000000000..080dab3ce9 --- /dev/null +++ b/doc/dev_guide/internals/replication/index.rst @@ -0,0 +1,12 @@ +:noindex: +:fullwidth: + +.. _internals-replication: + +Replication internals +===================== + +.. toctree:: + + replication_server_startup + orphan diff --git a/doc/dev_guide/internals/replication/orphan.rst b/doc/dev_guide/internals/replication/orphan.rst new file mode 100644 index 0000000000..91d3224733 --- /dev/null +++ b/doc/dev_guide/internals/replication/orphan.rst @@ -0,0 +1,147 @@ +.. _internals-replication-orphan_status: + +Orphan status +============= + +Starting with Tarantool version 1.9, there is a change to the +procedure when an instance joins a replica set. +During ``box.cfg()`` the instance will try to join all masters listed +in :ref:`box.cfg.replication `. +If the instance does not succeed with at least +the number of masters specified in +:ref:`replication_connect_quorum `, +then it will switch to **orphan status**. +While an instance is in orphan status, it is read-only. + +To "join" a master, a replica instance must "connect" to the +master node and then "sync". + +"Connect" means contact the master over the physical network +and receive acknowledgment. If there is no acknowledgment after +:ref:`box.replication_connect_timeout ` +seconds (usually 4 seconds), and retries fail, then the connect step fails. + +"Sync" means receive updates +from the master in order to make a local database copy. +Syncing is complete when the replica has received all the +updates, or at least has received enough updates that the replica's lag +(see +:ref:`replication.upstream.lag ` +in ``box.info()``) +is less than or equal to the number of seconds specified in +:ref:`box.cfg.replication_sync_lag `. +If ``replication_sync_lag`` is unset (nil) or set to TIMEOUT_INFINITY, then +the replica skips the "sync" state and switches to "follow" immediately. + +In order to leave orphan mode you need to sync with a sufficient number +(:ref:`replication_connect_quorum `) of +instances. To do so, you may either: + +* Set :ref:`replication_connect_quorum ` + to a lower value. +* Reset ``box.cfg.replication`` to exclude instances that cannot be reached + or synced with. +* Set ``box.cfg.replication`` to ``""`` (empty string). + +The following situations are possible. + +.. _replication-leader: + +**Situation 1: bootstrap** + +Here ``box.cfg{}`` is being called for the first time. +A replica is joining but no replica set exists yet. + + 1. Set status to 'orphan'. + 2. Try to connect to all nodes from ``box.cfg.replication``, + or to the number of nodes required by + :ref:`replication_connect_quorum `. + Retrying up to 3 times in 30 seconds is possible because this is bootstrap, + :ref:`replication_connect_timeout ` + is overridden. + + 3. Abort and throw an error if not connected to all nodes in ``box.cfg.replication`` or + :ref:`replication_connect_quorum `. + + 4. This instance might be elected as the replica set 'leader'. + Criteria for electing a leader include vclock value (largest is best), + and whether it is read-only or read-write (read-write is best unless there is no other choice). + The leader is the master that other instances must join. + The leader is the master that executes + :doc:`box.once() ` functions. + + 5. If this instance is elected as the replica set leader, + then + perform an "automatic bootstrap": + + a. Set status to 'running'. + b. Return from ``box.cfg{}``. + + Otherwise this instance will be a replica joining an existing replica set, + so: + + a. Bootstrap from the leader. + See examples in section :ref:`Bootstrapping a replica set `. + b. In background, sync with all the other nodes in the replication set. + +**Situation 2: recovery** + +Here ``box.cfg{}`` is not being called for the first time. +It is being called again in order to perform recovery. + + 1. Perform :ref:`recovery ` from the last local + snapshot and the WAL files. + + 2. Connect to at least + :ref:`replication_connect_quorum ` + nodes. If failed -- set status to 'orphan'. + (Attempts to sync will continue in the background and when/if they succeed + then 'orphan' will be changed to 'connected'.) + + 3. If connected - sync with all connected nodes, until the difference is not more than + :ref:`replication_sync_lag ` seconds. + +.. _replication-configuration_update: + +**Situation 3: configuration update** + +Here ``box.cfg{}`` is not being called for the first time. +It is being called again because some replication parameter +or something in the replica set has changed. + + 1. Try to connect to all nodes from ``box.cfg.replication``, + or to the number of nodes required by + :ref:`replication_connect_quorum `, + within the time period specified in + :ref:`replication_connect_timeout `. + + 2. Try to sync with the connected nodes, + within the time period specified in + :ref:`replication_sync_timeout `. + + 3. If earlier steps fail, change status to 'orphan'. + (Attempts to sync will continue in the background and when/if they succeed + then 'orphan' status will end.) + + 4. If earlier steps succeed, set status to 'running' (master) or 'follow' (replica). + +.. _replication-configuration_rebootstrap: + +**Situation 4: rebootstrap** + +Here ``box.cfg{}`` is not being called. The replica connected successfully +at some point in the past, and is now ready for an update from the master. +But the master cannot provide an update. +This can happen by accident, or more likely can happen because the replica +is slow (its :ref:`lag ` is large), +and the WAL (.xlog) files containing the +updates have been deleted. This is not crippling. The replica can discard +what it received earlier, and then ask for the master's latest snapshot +(.snap) file contents. Since it is effectively going through the bootstrap +process a second time, this is called "rebootstrapping". However, there has +to be one difference from an ordinary bootstrap -- the replica's +:ref:`replica id ` will remain the same. +If it changed, then the master would think that the replica is a +new addition to the cluster, and would maintain a record of an +instance ID of a replica that has ceased to exist. Rebootstrapping was +introduced in Tarantool version 1.10.2 and is completely automatic. diff --git a/doc/dev_guide/internals/replication_internals.rst b/doc/dev_guide/internals/replication/replication_server_startup.rst similarity index 62% rename from doc/dev_guide/internals/replication_internals.rst rename to doc/dev_guide/internals/replication/replication_server_startup.rst index 1b39e9ef20..cdd0c94d86 100644 --- a/doc/dev_guide/internals/replication_internals.rst +++ b/doc/dev_guide/internals/replication/replication_server_startup.rst @@ -1,51 +1,52 @@ -.. _internals-replication: +.. _internals-replication-server_startup: --------------------------------------------------------------------------------- Server startup with replication --------------------------------------------------------------------------------- +=============================== -In addition to the recovery process described above, the server must take +In addition to the recovery process described in the +section :ref:`Recovery process `, the server must take additional steps and precautions if :ref:`replication ` is enabled. Once again the startup procedure is initiated by the ``box.cfg{}`` request. One of the ``box.cfg`` parameters may be -:ref:`replication ` that specifies replication +:ref:`replication ` which specifies replication source(-s). We will refer to this replica, which is starting up due to ``box.cfg``, as the "local" replica to distinguish it from the other replicas in a replica set, which we will refer to as "distant" replicas. -*#1. If there is no snapshot .snap file and the 'replication' parameter is empty and cfg.read_only=false*: |br| +*If there is no snapshot .snap file and the* ``replication`` *parameter is empty and* +``cfg.read_only=false``: |br| then the local replica assumes it is an unreplicated "standalone" instance, or is the first replica of a new replica set. It will generate new UUIDs for -itself and for the replica set. The replica UUID is stored in the ``_cluster`` space -(unless the replica is :ref:`anonymous `); the +itself and for the replica set. The replica UUID is stored in the ``_cluster`` space; the replica set UUID is stored in the ``_schema`` space. Since a snapshot contains all the data in all the spaces, that means the local replica's snapshot will contain the replica UUID and the replica set UUID. Therefore, when the local replica restarts on later occasions, it will be able to recover these UUIDs when it reads the .snap file. -*#1a. If there is no snapshot .snap file and the 'replication' parameter is empty and cfg.read_only=true*: |br| -When an instance is starting with ``box.cfg({... read_only = true})``, it cannot be the -first replica of a new replica set because the first replica must be a master. -Therefore an error message will occur: ER_BOOTSTRAP_READONLY. +*If there is no snapshot .snap file and the* ``replication`` *parameter is empty +and* ``cfg.read_only=true``: |br| +it cannot be the first replica of a new replica set because the first replica +must be a master. Therefore an error message will occur: ER_BOOTSTRAP_READONLY. To avoid this, change the setting for this (local) instance to ``read_only = false``, or ensure that another (distant) instance starts first and has the local instance's -UUID in its _cluster space. In the latter case, if ER_BOOTSTRAP_READONLY still +UUID in its ``_cluster`` space. In the latter case, if ER_BOOTSTRAP_READONLY still occurs, set the local instance's :ref:`box.replication_connect_timeout ` to a larger value. -*#2. If there is no snapshot .snap file and the 'replication' parameter is not empty -and the ``_cluster`` space contains no other replica UUIDs*: |br| +*If there is no snapshot .snap file and the* ``replication`` *parameter is not empty +and the* ``_cluster`` *space contains no other replica UUIDs*: |br| then the local replica assumes it is not a standalone instance, but is not yet part of a replica set. It must now join the replica set. It will send its replica UUID to the first distant replica which is listed in ``replication`` and which will act as a master. This is called the "join request". When a distant replica receives a join request, it will send back: -(1) the distant replica's replica set UUID, -(2) the contents of the distant replica's .snap file. |br| +* the distant replica's replica set UUID, + +* the contents of the distant replica's .snap file. |br| When the local replica receives this information, it puts the replica set UUID in its ``_schema`` space, puts the distant replica's UUID and connection information in its ``_cluster`` space, and makes a snapshot containing all the data sent by @@ -54,29 +55,30 @@ request, it will send back: receive this and update its own copy of the data, and add the local replica's UUID to its ``_cluster`` space. -*#3. If there is no snapshot .snap file and the 'replication' parameter is not empty -and the ``_cluster`` space contains other replica UUIDs*: |br| +*If there is no snapshot .snap file and the* ``replication`` *parameter is not empty +and the* ``_cluster`` *space contains other replica UUIDs*: |br| then the local replica assumes it is not a standalone instance, and is already part of a replica set. It will send its replica UUID and replica set UUID to all the distant replicas which are listed in ``replication``. This is called the "on-connect handshake". When a distant replica receives an on-connect handshake: |br| -(1) the distant replica compares its own copy of the replica set UUID to the one in +* the distant replica compares its own copy of the replica set UUID to the one in the on-connect handshake. If there is no match, then the handshake fails and the local replica will display an error. -(2) the distant replica looks for a record of the connecting instance in its + +* the distant replica looks for a record of the connecting instance in its ``_cluster`` space. If there is none, then the handshake fails. |br| Otherwise the handshake is successful. The distant replica will read any new information from its own .snap and .xlog files, and send the new requests to the local replica. -In the end ... the local replica knows what replica set it belongs to, the distant -replica knows that the local replica is a member of the replica set, and both replicas -have the same database contents. +In the end, the local replica knows what replica set it belongs to, the distant +replica knows that the local replica is a member of the replica set, and both +replicas have the same database contents. -.. _internals-vector: +.. _replication-vector: -*#4. If there is a snapshot file and replication source is not empty*: |br| +*If there is a snapshot file and replication source is not empty*: |br| first the local replica goes through the recovery process described in the previous section, using its own .snap and .xlog files. Then it sends a "subscribe" request to all the other replicas of the replica set. The subscribe @@ -88,10 +90,18 @@ greater than (lsn of the vector clock in the subscribe request). After all the other replicas of the replica set have responded to the local replica's subscribe request, the replica startup is complete. -The following temporary limitations apply for versions 1.7 and 2.1: +The following temporary limitations applied for Tarantool versions earlier than +1.7.7: + +* The URIs in the ``replication`` parameter should all be in the same order on all replicas. + This is not mandatory but is an aid to consistency. +* The replicas of a replica set should be started up at slightly different times. + This is not mandatory but prevents a situation where each replica is waiting + for the other replica to be ready. + +The following limitation still applies for the current Tarantool version: -* The URIs in the ``replication`` parameter should all be in the same order on all replicas. - This is not mandatory but is an aid to consistency. -* The maximum number of entries in the ``_cluster`` space is 32. Tuples for - out-of-date replicas are not automatically re-used, so if this 32-replica - limit is reached, users may have to reorganize the ``_cluster`` space manually. +* The maximum number of entries in the ``_cluster`` space is + :ref:`32 `. Tuples for + out-of-date replicas are not automatically re-used, so if this 32-replica + limit is reached, users may have to reorganize the ``_cluster`` space manually. diff --git a/doc/getting_started/change_schema_dynamically.rst b/doc/getting_started/change_schema_dynamically.rst index 742490562b..3577cf0349 100644 --- a/doc/getting_started/change_schema_dynamically.rst +++ b/doc/getting_started/change_schema_dynamically.rst @@ -13,7 +13,7 @@ to modify the schema after applying it. The easiest way to change it is to delete the database snapshots and create a schema from scratch. Of course, this is only acceptable during application development and debugging. -For production scenarios, read the section on :ref:`migrations`. +For production scenarios, read the section on :ref:`migrations `. To remove snapshots: @@ -26,4 +26,4 @@ To remove snapshots: These files have the .snap and .xlog extensions respectively, and they are located in the Tarantool working directory. -To understand how the Tarantool data schema works, read the :ref:`Data model` section. +To understand how the Tarantool data schema works, read the :ref:`Data model ` section. diff --git a/doc/getting_started/connecting_to_cluster.rst b/doc/getting_started/connecting_to_cluster.rst index 7d7fd6c17b..06665a5340 100644 --- a/doc/getting_started/connecting_to_cluster.rst +++ b/doc/getting_started/connecting_to_cluster.rst @@ -62,7 +62,7 @@ To learn how to call stored procedures in your programming language, see the cor * :ref:`for Python ` * :ref:`for Go ` * :ref:`for PHP ` -* :doc:`for C++ ` +* :doc:`for C++ ` For connectors to other languages, check the README for the connector of your choice `on GitHub `_. diff --git a/doc/getting_started/writing_cluster_code.rst b/doc/getting_started/writing_cluster_code.rst index a35bef0497..7a8f8ec10a 100644 --- a/doc/getting_started/writing_cluster_code.rst +++ b/doc/getting_started/writing_cluster_code.rst @@ -13,5 +13,5 @@ This functionality is implemented through the ``cartridge-extensions`` module. It is also included in the tutorial default application. However, in Tarantool, you can implement absolutely any business logic on top of a cluster. -This :doc:`Cartridge getting started section ` +This :doc:`Cartridge getting started section ` covers the cluster roles mechanism and writing a cluster application from scratch. diff --git a/doc/book/app_server/aster.svg b/doc/how-to/app/aster.svg similarity index 100% rename from doc/book/app_server/aster.svg rename to doc/how-to/app/aster.svg diff --git a/doc/book/app_server/cookbook.rst b/doc/how-to/app/cookbook.rst similarity index 99% rename from doc/book/app_server/cookbook.rst rename to doc/how-to/app/cookbook.rst index 9fe699f4a7..1902fc5450 100644 --- a/doc/book/app_server/cookbook.rst +++ b/doc/how-to/app/cookbook.rst @@ -1,7 +1,7 @@ .. _cookbook: -------------------------------------------------------------------------------- -Cookbook recipes +Lua cookbook recipes -------------------------------------------------------------------------------- Here are contributions of Lua programs for some frequent or tricky situations. diff --git a/doc/book/app_server/cookbook/main.go b/doc/how-to/app/cookbook/main.go similarity index 100% rename from doc/book/app_server/cookbook/main.go rename to doc/how-to/app/cookbook/main.go diff --git a/doc/book/app_server/creating_app.rst b/doc/how-to/app/creating_app.rst similarity index 95% rename from doc/book/app_server/creating_app.rst rename to doc/how-to/app/creating_app.rst index 7c98f99778..e452c8efa6 100644 --- a/doc/book/app_server/creating_app.rst +++ b/doc/how-to/app/creating_app.rst @@ -1,7 +1,7 @@ -:noindex: :fullwidth: -.. _app_server-creating_app: +.. _app_server: +.. _app_server-creating_app: Creating an application ======================= @@ -30,13 +30,13 @@ location in a while. We leave client-side applications outside the scope of this story. However, we promise a mini-demo in the end to simulate real users and give us some fun. -.. image:: aster.svg +.. image:: aster.svg :align: center Follow these topics to implement our application: -.. toctree:: +.. toctree:: :maxdepth: 3 creating_app/modules_rocks_and_applications diff --git a/doc/book/app_server/creating_app/GIS.rst b/doc/how-to/app/creating_app/GIS.rst similarity index 100% rename from doc/book/app_server/creating_app/GIS.rst rename to doc/how-to/app/creating_app/GIS.rst diff --git a/doc/book/app_server/creating_app/aster.svg b/doc/how-to/app/creating_app/aster.svg similarity index 100% rename from doc/book/app_server/creating_app/aster.svg rename to doc/how-to/app/creating_app/aster.svg diff --git a/doc/book/app_server/creating_app/avro_schemas.rst b/doc/how-to/app/creating_app/avro_schemas.rst similarity index 100% rename from doc/book/app_server/creating_app/avro_schemas.rst rename to doc/how-to/app/creating_app/avro_schemas.rst diff --git a/doc/book/app_server/creating_app/bootstrapping_a_database.rst b/doc/how-to/app/creating_app/bootstrapping_a_database.rst similarity index 100% rename from doc/book/app_server/creating_app/bootstrapping_a_database.rst rename to doc/how-to/app/creating_app/bootstrapping_a_database.rst diff --git a/doc/how-to/app/creating_app/fibers.rst b/doc/how-to/app/creating_app/fibers.rst new file mode 100644 index 0000000000..88f87e5098 --- /dev/null +++ b/doc/how-to/app/creating_app/fibers.rst @@ -0,0 +1,56 @@ +.. _application_server_fibers: + +Fibers, yields and cooperative multitasking +=========================================== + +But wait! If we launch it as shown above -- ``self.respawn()`` -- the function +will be executed only once, just like all the other methods. But we need to +execute ``respawn()`` every 60 seconds. Creating a :ref:`fiber ` +is the Tarantool way of making application logic work in the background at all +times. + +A **fiber** is a set of instructions that are executed with +:ref:`cooperative multitasking `: +the instructions contain :ref:`yield ` signals, upon which control is passed to another fiber. + +Let's launch ``respawn()`` in a fiber to make it work in the background all the time. +To do so, we'll need to amend ``respawn()``: + +.. code-block:: lua + + respawn = function(self) + -- let's give our fiber a name; + -- this will produce neat output in fiber.info() + fiber.name('Respawn fiber') + while true do + for _, tuple in box.space.pokemons.index.status:pairs( + self.state.CAUGHT) do + box.space.pokemons:update( + tuple[self.ID], + {{'=', self.STATUS, self.state.ACTIVE}} + ) + end + fiber.sleep(self.respawn_time) + end + end + +and call it as a fiber in ``start()``: + +.. code-block:: lua + + start = function(self) + -- create spaces and indexes + <...> + -- create models + <...> + -- compile models + <...> + -- start the game + self.pokemon_model = compiled_pokemon + self.player_model = compiled_player + fiber.create(self.respawn, self) + log.info('Started') + -- errors if schema creation or compilation fails + <...> + end + \ No newline at end of file diff --git a/doc/book/app_server/creating_app/index_iterators.rst b/doc/how-to/app/creating_app/index_iterators.rst similarity index 100% rename from doc/book/app_server/creating_app/index_iterators.rst rename to doc/how-to/app/creating_app/index_iterators.rst diff --git a/doc/book/app_server/creating_app/logging.rst b/doc/how-to/app/creating_app/logging.rst similarity index 100% rename from doc/book/app_server/creating_app/logging.rst rename to doc/how-to/app/creating_app/logging.rst diff --git a/doc/book/app_server/creating_app/modules_rocks_and_applications.rst b/doc/how-to/app/creating_app/modules_rocks_and_applications.rst similarity index 100% rename from doc/book/app_server/creating_app/modules_rocks_and_applications.rst rename to doc/how-to/app/creating_app/modules_rocks_and_applications.rst diff --git a/doc/book/app_server/creating_app/nginx.rst b/doc/how-to/app/creating_app/nginx.rst similarity index 100% rename from doc/book/app_server/creating_app/nginx.rst rename to doc/how-to/app/creating_app/nginx.rst diff --git a/doc/book/app_server/creating_app/non-blockng_io.rst b/doc/how-to/app/creating_app/non-blockng_io.rst similarity index 100% rename from doc/book/app_server/creating_app/non-blockng_io.rst rename to doc/how-to/app/creating_app/non-blockng_io.rst diff --git a/doc/book/app_server/ide_1.png b/doc/how-to/app/ide_1.png similarity index 100% rename from doc/book/app_server/ide_1.png rename to doc/how-to/app/ide_1.png diff --git a/doc/book/app_server/ide_2.png b/doc/how-to/app/ide_2.png similarity index 100% rename from doc/book/app_server/ide_2.png rename to doc/how-to/app/ide_2.png diff --git a/doc/book/app_server/ide_3.png b/doc/how-to/app/ide_3.png similarity index 100% rename from doc/book/app_server/ide_3.png rename to doc/how-to/app/ide_3.png diff --git a/doc/book/app_server/ide_4.png b/doc/how-to/app/ide_4.png similarity index 100% rename from doc/book/app_server/ide_4.png rename to doc/how-to/app/ide_4.png diff --git a/doc/book/app_server/ide_5.png b/doc/how-to/app/ide_5.png similarity index 100% rename from doc/book/app_server/ide_5.png rename to doc/how-to/app/ide_5.png diff --git a/doc/book/app_server/ide_6.png b/doc/how-to/app/ide_6.png similarity index 100% rename from doc/book/app_server/ide_6.png rename to doc/how-to/app/ide_6.png diff --git a/doc/book/app_server/ide_7.png b/doc/how-to/app/ide_7.png similarity index 100% rename from doc/book/app_server/ide_7.png rename to doc/how-to/app/ide_7.png diff --git a/doc/book/app_server/ide_8.png b/doc/how-to/app/ide_8.png similarity index 100% rename from doc/book/app_server/ide_8.png rename to doc/how-to/app/ide_8.png diff --git a/doc/book/app_server/ide_9.png b/doc/how-to/app/ide_9.png similarity index 100% rename from doc/book/app_server/ide_9.png rename to doc/how-to/app/ide_9.png diff --git a/doc/how-to/app/index.rst b/doc/how-to/app/index.rst index e0f04286de..9600843978 100644 --- a/doc/how-to/app/index.rst +++ b/doc/how-to/app/index.rst @@ -1,8 +1,20 @@ +.. _how-to-app-server: + Developing applications with Tarantool ====================================== +Using Tarantool as an application server, you can write your own applications. +Tarantool’s native language for writing applications is +`Lua `_, so a typical application would be +a file that contains your Lua script. But you can also write applications +in C or C++. + .. toctree:: :maxdepth: 1 + launching_app + creating_app + using_ide + cookbook lua_tutorials c_tutorial diff --git a/doc/book/app_server/launching_app.rst b/doc/how-to/app/launching_app.rst similarity index 100% rename from doc/book/app_server/launching_app.rst rename to doc/how-to/app/launching_app.rst diff --git a/doc/book/app_server/using_ide.rst b/doc/how-to/app/using_ide.rst similarity index 100% rename from doc/book/app_server/using_ide.rst rename to doc/how-to/app/using_ide.rst diff --git a/doc/how-to/crud.rst b/doc/how-to/db/crud.rst similarity index 100% rename from doc/how-to/crud.rst rename to doc/how-to/db/crud.rst diff --git a/doc/how-to/db/index.rst b/doc/how-to/db/index.rst new file mode 100644 index 0000000000..184a2cf2a1 --- /dev/null +++ b/doc/how-to/db/index.rst @@ -0,0 +1,11 @@ +Defining and manipulating data +============================== + +This section contains guides on performing data operations in Tarantool. + +.. toctree:: + :maxdepth: 1 + + crud + indexes + sequences diff --git a/doc/how-to/db/indexes.rst b/doc/how-to/db/indexes.rst new file mode 100644 index 0000000000..3adadfc28b --- /dev/null +++ b/doc/how-to/db/indexes.rst @@ -0,0 +1,230 @@ +.. _how-to-db-indexes: + +Using indexes +============= + +Creating an index +----------------- + +It is mandatory to create an index for a space before trying to insert +tuples into the space, or select tuples from the space. + +The simple :doc:`index-creation ` +operation is: + +.. cssclass:: highlight +.. parsed-literal:: + + :extsamp:`box.space.{**{space-name}**}:create_index('{*{index-name}*}')` + +This creates a unique :ref:`TREE ` index on the first field +of all tuples (often called "Field#1"), which is assumed to be numeric. + +A recommended design pattern for a data model is to base primary keys on the +first fields of a tuple. This speeds up tuple comparison due to the specifics of +data storage and the way comparisons are arranged in Tarantool. + +The simple :doc:`SELECT ` request is: + +.. cssclass:: highlight +.. parsed-literal:: + + :extsamp:`box.space.{**{space-name}**}:select({*{value}*})` + +This looks for a single tuple via the first index. Since the first index +is always unique, the maximum number of returned tuples will be 1. +You can call ``select()`` without arguments, and it will return all tuples. +Be careful! Using ``select()`` for huge spaces hangs your instance. + +An index definition may also include identifiers of tuple fields +and their expected **types**. See allowed indexed field types in section +:ref:`Details about indexed field types `: + +.. cssclass:: highlight +.. parsed-literal:: + + :extsamp:`box.space.{**{space-name}**}:create_index({**{index-name}**}, {type = 'tree', parts = {{field = 1, type = 'unsigned'}}}` + +Space definitions and index definitions are stored permanently in Tarantool's +system spaces :ref:`_space ` and :ref:`_index `. + +.. admonition:: Tip + :class: fact + + See full information about creating indexes, such as + how to create a multikey index, an index using the ``path`` option, or + how to create a functional index in our reference for + :doc:`/reference/reference_lua/box_space/create_index`. + +.. _index-box_index-operations: + +Index operations +---------------- + +Index operations are automatic: if a data manipulation request changes a tuple, +then it also changes the index keys defined for the tuple. + +#. Let's create a sample space named ``tester`` and + put it in a variable ``my_space``: + + .. code-block:: tarantoolsession + + tarantool> my_space = box.schema.space.create('tester') + +#. Format the created space by specifying field names and types: + + .. code-block:: tarantoolsession + + tarantool> my_space:format({ + > {name = 'id', type = 'unsigned'}, + > {name = 'band_name', type = 'string'}, + > {name = 'year', type = 'unsigned'}, + > {name = 'rate', type = 'unsigned', is_nullable = true}}) + +#. Create the **primary** index (named ``primary``): + + .. code-block:: tarantoolsession + + tarantool> my_space:create_index('primary', { + > type = 'tree', + > parts = {'id'} + > }) + + This is a primary index based on the ``id`` field of each tuple. + +#. Insert some :ref:`tuples ` into the space: + + .. code-block:: tarantoolsession + + tarantool> my_space:insert{1, 'Roxette', 1986, 1} + tarantool> my_space:insert{2, 'Scorpions', 2015, 4} + tarantool> my_space:insert{3, 'Ace of Base', 1993} + tarantool> my_space:insert{4, 'Roxette', 2016, 3} + +#. Create a **secondary index**: + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:create_index('secondary', {parts = {{field=3, type='unsigned'}}}) + --- + - unique: true + parts: + - type: unsigned + is_nullable: false + fieldno: 3 + id: 2 + space_id: 512 + type: TREE + name: secondary + ... + +#. Create a **multi-part index** with three parts: + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:create_index('thrine', {parts = { + > {field = 2, type = 'string'}, + > {field = 3, type = 'unsigned'}, + > {field = 4, type = 'unsigned'} + > }}) + --- + - unique: true + parts: + - type: string + is_nullable: false + fieldno: 2 + - type: unsigned + is_nullable: false + fieldno: 3 + - type: unsigned + is_nullable: true + fieldno: 4 + id: 6 + space_id: 513 + type: TREE + name: thrine + ... + +**There are the following SELECT variations:** + +* The search can use **comparisons** other than equality: + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:select(1, {iterator = 'GT'}) + --- + - - [2, 'Scorpions', 2015, 4] + - [3, 'Ace of Base', 1993] + - [4, 'Roxette', 2016, 3] + ... + + The :ref:`comparison operators ` are: + + * ``LT`` for "less than" + * ``LE`` for "less than or equal" + * ``GT`` for "greater" + * ``GE`` for "greater than or equal" . + * ``EQ`` for "equal", + * ``REQ`` for "reversed equal" + + Value comparisons make sense if and only if the index type is TREE. + The iterator types for other types of indexes are slightly different and work + differently. See details in section :ref:`Iterator types `. + + Note that we don't use the name of the index, which means we use primary index here. + + This type of search may return more than one tuple. The tuples will be sorted + in descending order by key if the comparison operator is LT or LE or REQ. + Otherwise they will be sorted in ascending order. + +* The search can use a **secondary index**. + + For a primary-key search, it is optional to specify an index name as + was demonstrated above. + For a secondary-key search, it is mandatory. + + .. code-block:: tarantoolsession + + tarantool> box.space.tester.index.secondary:select({1993}) + --- + - - [3, 'Ace of Base', 1993] + ... + + .. _partial_key_search: + +* **Partial key search:** The search may be for some key parts starting with + the prefix of the key. Note that partial key searches are available + only in TREE indexes. + + .. code-block:: tarantoolsession + + tarantool> box.space.tester.index.thrine:select({'Scorpions', 2015}) + --- + - - [2, 'Scorpions', 2015, 4] + ... + +* The search can be for all fields, using a table as the value: + + .. code-block:: tarantoolsession + + tarantool> box.space.tester.index.thrine:select({'Roxette', 2016, 3}) + --- + - - [4, 'Roxette', 2016, 3] + ... + + or the search can be for one field, using a table or a scalar: + + .. code-block:: tarantoolsession + + tarantool> box.space.tester.index.thrine:select({'Roxette'}) + --- + - - [1, 'Roxette', 1986, 5] + - [4, 'Roxette', 2016, 3] + ... + +.. admonition:: Tip + :class: fact + + You can also add, drop, or alter the definitions at runtime, with some + restrictions. Read more about index operations in reference for + :doc:`box.index submodule `. diff --git a/doc/how-to/db/sequences.rst b/doc/how-to/db/sequences.rst new file mode 100644 index 0000000000..eed62f1794 --- /dev/null +++ b/doc/how-to/db/sequences.rst @@ -0,0 +1,139 @@ +.. _index-box_sequence: + +Using sequences +=============== + +A **sequence** is a generator of ordered integer values. + +As with spaces and indexes, you should specify the sequence **name** and let +Tarantool generate a unique numeric identifier (sequence ID). + +As well, you can specify several options when creating a new sequence. +The options determine what value will be generated whenever the sequence is used. + +.. _index-box_sequence-options: + +Options for box.schema.sequence.create() +---------------------------------------- + +.. container:: table + + .. list-table:: + :widths: 20 40 15 25 + :header-rows: 1 + + * - Option name + - Type and meaning + - Default + - Examples + * - ``start`` + - Integer. The value to generate the first time a sequence is used + - 1 + - ``start=0`` + * - ``min`` + - Integer. Values smaller than this cannot be generated + - 1 + - ``min=-1000`` + * - ``max`` + - Integer. Values larger than this cannot be generated + - 9223372036854775807 + - ``max=0`` + * - ``cycle`` + - Boolean. Whether to start again when values cannot be generated + - false + - ``cycle=true`` + * - ``cache`` + - Integer. The number of values to store in a cache + - 0 + - ``cache=0`` + * - ``step`` + - Integer. What to add to the previous generated value, when generating a new value + - 1 + - ``step=-1`` + * - ``if_not_exists`` + - Boolean. If this is true and a sequence with this name exists already, + ignore other options and use the existing values + - ``false`` + - ``if_not_exists=true`` + + +Once a sequence exists, it can be altered, dropped, reset, forced to generate +the next value, or associated with an index. + +Associating a sequence with an index +------------------------------------ + +For an initial example, we generate a sequence named 'S'. + +.. code-block:: tarantoolsession + + tarantool> box.schema.sequence.create('S',{min=5, start=5}) + --- + - step: 1 + id: 5 + min: 5 + cache: 0 + uid: 1 + max: 9223372036854775807 + cycle: false + name: S + start: 5 + ... + +The result shows that the new sequence has all default values, +except for the two that were specified, ``min`` and ``start``. + +Then we get the next value, with the ``next()`` function. + +.. code-block:: tarantoolsession + + tarantool> box.sequence.S:next() + --- + - 5 + ... + +The result is the same as the start value. If we called ``next()`` +again, we would get 6 (because the previous value plus the +step value is 6), and so on. + +Then we create a new table and specify that its primary key should be +generated from the sequence. + +.. code-block:: tarantoolsession + + tarantool> s=box.schema.space.create('T') + --- + ... + tarantool> s:create_index('I',{sequence='S'}) + --- + - parts: + - type: unsigned + is_nullable: false + fieldno: 1 + sequence_id: 1 + id: 0 + space_id: 520 + unique: true + type: TREE + sequence_fieldno: 1 + name: I + ... + --- + ... + +Then we insert a tuple without specifying a value for the primary key. + +.. code-block:: tarantoolsession + + tarantool> box.space.T:insert{nil,'other stuff'} + --- + - [6, 'other stuff'] + ... + +The result is a new tuple where the first field has a value of 6. +This arrangement, where the system automatically generates the +values for a primary key, is sometimes called "auto-incrementing" +or "identity". + +For syntax and implementation details, see the reference for +:doc:`box.schema.sequence `. diff --git a/doc/how-to/index.rst b/doc/how-to/index.rst index c3428e77da..88f3459434 100644 --- a/doc/how-to/index.rst +++ b/doc/how-to/index.rst @@ -19,7 +19,9 @@ If you are new to Tarantool, please see our Basic Tarantool tutorial getting_started_connectors getting_started_cartridge - crud + db/index + vshard_quick app/index + replication/index sql/index other/index diff --git a/doc/how-to/replication/index.rst b/doc/how-to/replication/index.rst new file mode 100644 index 0000000000..463aa246eb --- /dev/null +++ b/doc/how-to/replication/index.rst @@ -0,0 +1,14 @@ +.. _how-to-replication: + +Replication tutorials +===================== + +.. toctree:: + :maxdepth: 2 + + repl_bootstrap + repl_add_instances + repl_remove_instances + repl_sync + repl_leader_elect + \ No newline at end of file diff --git a/doc/book/replication/mm-2m-mesh.png b/doc/how-to/replication/mm-2m-mesh.png similarity index 100% rename from doc/book/replication/mm-2m-mesh.png rename to doc/how-to/replication/mm-2m-mesh.png diff --git a/doc/book/replication/mm-2m-mesh.svg b/doc/how-to/replication/mm-2m-mesh.svg similarity index 100% rename from doc/book/replication/mm-2m-mesh.svg rename to doc/how-to/replication/mm-2m-mesh.svg diff --git a/doc/book/replication/mm-3m-mesh-add.png b/doc/how-to/replication/mm-3m-mesh-add.png similarity index 100% rename from doc/book/replication/mm-3m-mesh-add.png rename to doc/how-to/replication/mm-3m-mesh-add.png diff --git a/doc/book/replication/mr-1m-1r-twoway.png b/doc/how-to/replication/mr-1m-1r-twoway.png similarity index 100% rename from doc/book/replication/mr-1m-1r-twoway.png rename to doc/how-to/replication/mr-1m-1r-twoway.png diff --git a/doc/book/replication/mr-1m-1r-twoway.svg b/doc/how-to/replication/mr-1m-1r-twoway.svg similarity index 100% rename from doc/book/replication/mr-1m-1r-twoway.svg rename to doc/how-to/replication/mr-1m-1r-twoway.svg diff --git a/doc/book/replication/mr-1m-2r-mesh-add.png b/doc/how-to/replication/mr-1m-2r-mesh-add.png similarity index 100% rename from doc/book/replication/mr-1m-2r-mesh-add.png rename to doc/how-to/replication/mr-1m-2r-mesh-add.png diff --git a/doc/how-to/replication/repl_add_instances.rst b/doc/how-to/replication/repl_add_instances.rst new file mode 100644 index 0000000000..8eb87e5ce8 --- /dev/null +++ b/doc/how-to/replication/repl_add_instances.rst @@ -0,0 +1,166 @@ +.. _replication-add_instances: + +Adding instances +================ + +.. _replication-add_replica: + +This tutorial is intended as a follow-up to the +:ref:`replication bootstrapping ` guide. +It continues building on the examples from that page. +It is recommended that you complete the bootstrapping guide before you proceed. + + +Adding a replica +---------------- + +.. image:: mr-1m-2r-mesh-add.png + :align: center + +To add a second **replica** instance to the **master-replica** set from our +:ref:`bootstrapping example `, we need an +analog of the instance file that we created for the first replica in that set: + +.. code-block:: lua + + -- instance file for replica #2 + box.cfg{ + listen = 3301, + replication = {'replicator:password@192.168.0.101:3301', -- master URI + 'replicator:password@192.168.0.102:3301', -- replica #1 URI + 'replicator:password@192.168.0.103:3301'}, -- replica #2 URI + read_only = true + } + box.once("schema", function() + box.schema.user.create('replicator', {password = 'password'}) + box.schema.user.grant('replicator', 'replication') -- grant replication role + box.schema.space.create("test") + box.space.test:create_index("primary") + print('box.once executed on replica #2') + end) + +Here we add the URI of replica #2 to the :ref:`replication ` +parameter, so now it contains three URIs. + +After we launch the new replica instance, it gets connected to the master +instance and retrieves the master's write-ahead-log and snapshot files: + +.. code-block:: console + + $ # launching replica #2 + $ tarantool replica2.lua + 2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> version 1.7.4-52-g980d30092 + 2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> log level 5 + 2017-06-14 14:54:33.928 [46945] main/101/replica2.lua I> mapping 268435456 bytes for tuple arena... + 2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301 + 2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> authenticated + 2017-06-14 14:54:33.930 [46945] main/101/replica2.lua I> bootstrapping replica from 192.168.0.101:3301 + 2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> initial data received + 2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> final data received + 2017-06-14 14:54:33.934 [46945] snapshot/101/main I> saving snapshot `/var/lib/tarantool/replica2/00000000000000000010.snap.inprogress' + 2017-06-14 14:54:33.934 [46945] snapshot/101/main I> done + 2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> vinyl checkpoint done + 2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> ready to accept requests + 2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> set 'read_only' configuration option to true + 2017-06-14 14:54:33.936 [46945] main C> entering the event loop + +Since we are adding a read-only instance, there is no need to dynamically +update the ``replication`` parameter on the other running instances. This update +would be required if we :ref:`added a master instance `. + +However, we recommend specifying the URI of replica #3 in all instance files of the +replica set. This will keep all the files consistent with each other and with +the current replication topology, and so will help to avoid configuration errors +in case of further configuration updates and replica set restart. + +.. _replication-add_master: + +Adding a master +--------------- + +.. image:: mm-3m-mesh-add.png + :align: center + +To add a third master instance to the **master-master** set from our +:ref:`bootstrapping example `, we need an +analog of the instance files that we created to bootstrap the other master +instances in that set: + +.. code-block:: lua + + -- instance file for master #3 + box.cfg{ + listen = 3301, + replication = {'replicator:password@192.168.0.101:3301', -- master#1 URI + 'replicator:password@192.168.0.102:3301', -- master#2 URI + 'replicator:password@192.168.0.103:3301'}, -- master#3 URI + read_only = true, -- temporarily read-only + } + box.once("schema", function() + box.schema.user.create('replicator', {password = 'password'}) + box.schema.user.grant('replicator', 'replication') -- grant replication role + box.schema.space.create("test") + box.space.test:create_index("primary") + end) + +Here we make the following changes: + +* Add the URI of master #3 to the :ref:`replication ` + parameter. +* Temporarily specify :ref:`read_only=true ` to disable + data-change operations on the instance. After launch, master #3 will act as a + replica until it retrieves all data from the other masters in the replica set. + +After we launch master #3, it gets connected to the other master +instances and retrieves their write-ahead-log and snapshot files: + +.. code-block:: console + + $ # launching master #3 + $ tarantool master3.lua + 2017-06-14 17:10:00.556 [47121] main/101/master3.lua C> version 1.7.4-52-g980d30092 + 2017-06-14 17:10:00.557 [47121] main/101/master3.lua C> log level 5 + 2017-06-14 17:10:00.557 [47121] main/101/master3.lua I> mapping 268435456 bytes for tuple arena... + 2017-06-14 17:10:00.559 [47121] iproto/101/main I> binary: bound to [::]:3301 + 2017-06-14 17:10:00.559 [47121] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301 + 2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.102:3301 + 2017-06-14 17:10:00.559 [47121] main/106/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.103:3301 + 2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> authenticated + 2017-06-14 17:10:00.559 [47121] main/101/master3.lua I> bootstrapping replica from 192.168.0.102:3301 + 2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> initial data received + 2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> final data received + 2017-06-14 17:10:00.562 [47121] snapshot/101/main I> saving snapshot `/Users/e.shebunyaeva/work/tarantool-test-repl/master3_dir/00000000000000000009.snap.inprogress' + 2017-06-14 17:10:00.562 [47121] snapshot/101/main I> done + 2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> vinyl checkpoint done + 2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> ready to accept requests + 2017-06-14 17:10:00.565 [47121] main/101/master3.lua I> set 'read_only' configuration option to true + 2017-06-14 17:10:00.565 [47121] main C> entering the event loop + 2017-06-14 17:10:00.565 [47121] main/104/applier/replicator@192.168.0.10 I> authenticated + +Next, we add the URI of master #3 to the ``replication`` parameter on the existing two +masters. Replication-related parameters are dynamic, so we only need to make a +``box.cfg{}`` request on each of the running instances: + +.. code-block:: tarantoolsession + + # adding master #3 URI to replication sources + tarantool> box.cfg{replication = + > {'replicator:password@192.168.0.101:3301', + > 'replicator:password@192.168.0.102:3301', + > 'replicator:password@192.168.0.103:3301'}} + --- + ... + +When master #3 catches up with the other masters' state, we can disable +read-only mode for this instance: + +.. code-block:: tarantoolsession + + # making master #3 a real master + tarantool> box.cfg{read_only=false} + --- + ... + +We also recommend to specify master #3 URI in all instance files in order to +keep all the files consistent with each other and with the current replication +topology. diff --git a/doc/how-to/replication/repl_bootstrap.rst b/doc/how-to/replication/repl_bootstrap.rst new file mode 100644 index 0000000000..a6f1a81bff --- /dev/null +++ b/doc/how-to/replication/repl_bootstrap.rst @@ -0,0 +1,386 @@ +.. _replication-bootstrap: + +Bootstrapping a replica set +=========================== + +.. _replication-setup: + +Replication setup +----------------- + +To enable replication, you need to specify two parameters in a ``box.cfg{}`` +request: + +* :ref:`replication ` which defines the + replication source(s), and +* :ref:`read_only ` which is ``true`` for a + replica and ``false`` for a master. + +Both these parameters are "dynamic". This allows a replica to become a master +and vice versa on the fly with the help of a ``box.cfg{}`` request. + +.. _replication-master_replica_bootstrap: + +Master-replica bootstrap +------------------------ + +Let us first bootstrap a simple **master-replica** set containing two instances, +each located on its own machine. For easier administration, we make the +:ref:`instance files ` almost identical. + +.. image:: mr-1m-1r-twoway.png + :align: center + +Here is an example of the master's instance file: + +.. code-block:: lua + + -- instance file for the master + box.cfg{ + listen = 3301, + replication = {'replicator:password@192.168.0.101:3301', -- master URI + 'replicator:password@192.168.0.102:3301'}, -- replica URI + read_only = false + } + box.once("schema", function() + box.schema.user.create('replicator', {password = 'password'}) + box.schema.user.grant('replicator', 'replication') -- grant replication role + box.schema.space.create("test") + box.space.test:create_index("primary") + print('box.once executed on master') + end) + +where: + +* the ``box.cfg()`` :ref:`listen ` parameter defines a URI + (port 3301 in our example), on which the master can accept connections from + replicas. +* the ``box.cfg()`` :ref:`replication ` parameter + defines the URIs at which all instances in the replica set can accept connections. + It includes the replica's URI as well, although the replica is not a replication + source right now. This parameter is mandatory only for master-master or full-mesh + cluster setups. + + .. note:: + + For security reasons, we recommend that administrators prevent unauthorized + replication sources by associating a password with every user that has a + replication :ref:`role `. That way, the :ref:`URI + ` for ``replication`` parameter must have the long form + ``username:password@host:port``. + +* the :ref:`read_only = false ` parameter setting enables + data-change operations on the instance and makes the instance act as a master, + not as a replica. *That is the only parameter setting in our instance files + that will differ.* +* the :doc:`box.once() ` function contains database initialization logic + that should be executed only once during the replica set lifetime. + +In this example, we create a space with a primary index, and a user for +replication purposes. We also say ``print('box.once executed on master')`` +so that it will later be visible on a console whether ``box.once()`` was executed. + +.. note:: + + Replication requires privileges. We can grant privileges for accessing spaces + directly to the user who will start the instance. However, it is more usual + to grant privileges for accessing spaces to a + :ref:`role `, and then grant the role to the user who + will start the replica. + +Here we use Tarantool's predefined role named "replication" which by default +grants "read" privileges for all database objects ("universe"), and we can +change privileges for this role as required. + +In the replica's instance file, we set the ``read_only`` parameter to "true", and +say ``print('box.once executed on replica')`` so that later it will be visible +that ``box.once()`` was not executed more than once. +Otherwise the replica's instance file is identical to the master's instance file. + +.. code-block:: lua + + -- instance file for the replica + box.cfg{ + listen = 3301, + replication = {'replicator:password@192.168.0.101:3301', -- master URI + 'replicator:password@192.168.0.102:3301'}, -- replica URI + read_only = true + } + box.once("schema", function() + box.schema.user.create('replicator', {password = 'password'}) + box.schema.user.grant('replicator', 'replication') -- grant replication role + box.schema.space.create("test") + box.space.test:create_index("primary") + print('box.once executed on replica') + end) + +.. note:: + + The replica does not inherit the master’s configuration parameters, such as + those making the :ref:`checkpoint daemon ` run on + the master. To get the same behavior, set the relevant parameters + explicitly so that they are the same on both master and replica. + +Now we can launch the two instances. The master... + +.. code-block:: console + + $ # launching the master + $ tarantool master.lua + 2017-06-14 14:12:03.847 [18933] main/101/master.lua C> version 1.7.4-52-g980d30092 + 2017-06-14 14:12:03.848 [18933] main/101/master.lua C> log level 5 + 2017-06-14 14:12:03.849 [18933] main/101/master.lua I> mapping 268435456 bytes for tuple arena... + 2017-06-14 14:12:03.859 [18933] iproto/101/main I> binary: bound to [::]:3301 + 2017-06-14 14:12:03.861 [18933] main/105/applier/replicator@192.168.0. I> can't connect to master + 2017-06-14 14:12:03.861 [18933] main/105/applier/replicator@192.168.0. coio.cc:105 !> SystemError connect, called on fd 14, aka 192.168.0.102:56736: Connection refused + 2017-06-14 14:12:03.861 [18933] main/105/applier/replicator@192.168.0. I> will retry every 1 second + 2017-06-14 14:12:03.861 [18933] main/104/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.101:3301 + 2017-06-14 14:12:19.878 [18933] main/105/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.102:3301 + 2017-06-14 14:12:19.879 [18933] main/101/master.lua I> initializing an empty data directory + 2017-06-14 14:12:19.908 [18933] snapshot/101/main I> saving snapshot `/var/lib/tarantool/master/00000000000000000000.snap.inprogress' + 2017-06-14 14:12:19.914 [18933] snapshot/101/main I> done + 2017-06-14 14:12:19.914 [18933] main/101/master.lua I> vinyl checkpoint done + 2017-06-14 14:12:19.917 [18933] main/101/master.lua I> ready to accept requests + 2017-06-14 14:12:19.918 [18933] main/105/applier/replicator@192.168.0. I> failed to authenticate + 2017-06-14 14:12:19.918 [18933] main/105/applier/replicator@192.168.0. xrow.cc:431 E> ER_LOADING: Instance bootstrap hasn't finished yet + box.once executed on master + 2017-06-14 14:12:19.920 [18933] main C> entering the event loop + +... (the display confirms that ``box.once()`` was executed on the master) -- and the replica: + +.. code-block:: console + + $ # launching the replica + $ tarantool replica.lua + 2017-06-14 14:12:19.486 [18934] main/101/replica.lua C> version 1.7.4-52-g980d30092 + 2017-06-14 14:12:19.486 [18934] main/101/replica.lua C> log level 5 + 2017-06-14 14:12:19.487 [18934] main/101/replica.lua I> mapping 268435456 bytes for tuple arena... + 2017-06-14 14:12:19.494 [18934] iproto/101/main I> binary: bound to [::]:3311 + 2017-06-14 14:12:19.495 [18934] main/104/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.101:3301 + 2017-06-14 14:12:19.495 [18934] main/105/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.102:3302 + 2017-06-14 14:12:19.496 [18934] main/104/applier/replicator@192.168.0. I> failed to authenticate + 2017-06-14 14:12:19.496 [18934] main/104/applier/replicator@192.168.0. xrow.cc:431 E> ER_LOADING: Instance bootstrap hasn't finished yet + +In both logs, there are messages saying that the replica was bootstrapped from the master: + +.. code-block:: console + + $ # bootstrapping the replica (from the master's log) + <...> + 2017-06-14 14:12:20.503 [18933] main/106/main I> initial data sent. + 2017-06-14 14:12:20.505 [18933] relay/[::ffff:192.168.0.101]:/101/main I> recover from `/var/lib/tarantool/master/00000000000000000000.xlog' + 2017-06-14 14:12:20.505 [18933] main/106/main I> final data sent. + 2017-06-14 14:12:20.522 [18933] relay/[::ffff:192.168.0.101]:/101/main I> recover from `/Users/e.shebunyaeva/work/tarantool-test-repl/master_dir/00000000000000000000.xlog' + 2017-06-14 14:12:20.922 [18933] main/105/applier/replicator@192.168.0. I> authenticated + +.. code-block:: console + + $ # bootstrapping the replica (from the replica's log) + <...> + 2017-06-14 14:12:20.498 [18934] main/104/applier/replicator@192.168.0. I> authenticated + 2017-06-14 14:12:20.498 [18934] main/101/replica.lua I> bootstrapping replica from 192.168.0.101:3301 + 2017-06-14 14:12:20.512 [18934] main/104/applier/replicator@192.168.0. I> initial data received + 2017-06-14 14:12:20.512 [18934] main/104/applier/replicator@192.168.0. I> final data received + 2017-06-14 14:12:20.517 [18934] snapshot/101/main I> saving snapshot `/var/lib/tarantool/replica/00000000000000000005.snap.inprogress' + 2017-06-14 14:12:20.518 [18934] snapshot/101/main I> done + 2017-06-14 14:12:20.519 [18934] main/101/replica.lua I> vinyl checkpoint done + 2017-06-14 14:12:20.520 [18934] main/101/replica.lua I> ready to accept requests + 2017-06-14 14:12:20.520 [18934] main/101/replica.lua I> set 'read_only' configuration option to true + 2017-06-14 14:12:20.520 [18934] main C> entering the event loop + +Notice that ``box.once()`` was executed only at the master, although we added +``box.once()`` to both instance files. + +We could as well launch the replica first: + +.. code-block:: console + + $ # launching the replica + $ tarantool replica.lua + 2017-06-14 14:35:36.763 [18952] main/101/replica.lua C> version 1.7.4-52-g980d30092 + 2017-06-14 14:35:36.765 [18952] main/101/replica.lua C> log level 5 + 2017-06-14 14:35:36.765 [18952] main/101/replica.lua I> mapping 268435456 bytes for tuple arena... + 2017-06-14 14:35:36.772 [18952] iproto/101/main I> binary: bound to [::]:3301 + 2017-06-14 14:35:36.772 [18952] main/104/applier/replicator@192.168.0. I> can't connect to master + 2017-06-14 14:35:36.772 [18952] main/104/applier/replicator@192.168.0. coio.cc:105 !> SystemError connect, called on fd 13, aka 192.168.0.101:56820: Connection refused + 2017-06-14 14:35:36.772 [18952] main/104/applier/replicator@192.168.0. I> will retry every 1 second + 2017-06-14 14:35:36.772 [18952] main/105/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.102:3301 + +... and the master later: + +.. code-block:: console + + $ # launching the master + $ tarantool master.lua + 2017-06-14 14:35:43.701 [18953] main/101/master.lua C> version 1.7.4-52-g980d30092 + 2017-06-14 14:35:43.702 [18953] main/101/master.lua C> log level 5 + 2017-06-14 14:35:43.702 [18953] main/101/master.lua I> mapping 268435456 bytes for tuple arena... + 2017-06-14 14:35:43.709 [18953] iproto/101/main I> binary: bound to [::]:3301 + 2017-06-14 14:35:43.709 [18953] main/105/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.102:3301 + 2017-06-14 14:35:43.709 [18953] main/104/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.101:3301 + 2017-06-14 14:35:43.709 [18953] main/101/master.lua I> initializing an empty data directory + 2017-06-14 14:35:43.721 [18953] snapshot/101/main I> saving snapshot `/var/lib/tarantool/master/00000000000000000000.snap.inprogress' + 2017-06-14 14:35:43.722 [18953] snapshot/101/main I> done + 2017-06-14 14:35:43.723 [18953] main/101/master.lua I> vinyl checkpoint done + 2017-06-14 14:35:43.723 [18953] main/101/master.lua I> ready to accept requests + 2017-06-14 14:35:43.724 [18953] main/105/applier/replicator@192.168.0. I> failed to authenticate + 2017-06-14 14:35:43.724 [18953] main/105/applier/replicator@192.168.0. xrow.cc:431 E> ER_LOADING: Instance bootstrap hasn't finished yet + box.once executed on master + 2017-06-14 14:35:43.726 [18953] main C> entering the event loop + 2017-06-14 14:35:43.779 [18953] main/103/main I> initial data sent. + 2017-06-14 14:35:43.780 [18953] relay/[::ffff:192.168.0.101]:/101/main I> recover from `/var/lib/tarantool/master/00000000000000000000.xlog' + 2017-06-14 14:35:43.780 [18953] main/103/main I> final data sent. + 2017-06-14 14:35:43.796 [18953] relay/[::ffff:192.168.0.102]:/101/main I> recover from `/var/lib/tarantool/master/00000000000000000000.xlog' + 2017-06-14 14:35:44.726 [18953] main/105/applier/replicator@192.168.0. I> authenticated + +In this case, the replica would wait for the master to become available, so the +launch order doesn't matter. Our ``box.once()`` logic would also be executed +only once, at the master. + +.. code-block:: console + + $ # the replica has eventually connected to the master + $ # and got bootstrapped (from the replica's log) + 2017-06-14 14:35:43.777 [18952] main/104/applier/replicator@192.168.0. I> remote master is 1.7.4 at 192.168.0.101:3301 + 2017-06-14 14:35:43.777 [18952] main/104/applier/replicator@192.168.0. I> authenticated + 2017-06-14 14:35:43.777 [18952] main/101/replica.lua I> bootstrapping replica from 192.168.0.199:3310 + 2017-06-14 14:35:43.788 [18952] main/104/applier/replicator@192.168.0. I> initial data received + 2017-06-14 14:35:43.789 [18952] main/104/applier/replicator@192.168.0. I> final data received + 2017-06-14 14:35:43.793 [18952] snapshot/101/main I> saving snapshot `/var/lib/tarantool/replica/00000000000000000005.snap.inprogress' + 2017-06-14 14:35:43.793 [18952] snapshot/101/main I> done + 2017-06-14 14:35:43.795 [18952] main/101/replica.lua I> vinyl checkpoint done + 2017-06-14 14:35:43.795 [18952] main/101/replica.lua I> ready to accept requests + 2017-06-14 14:35:43.795 [18952] main/101/replica.lua I> set 'read_only' configuration option to true + 2017-06-14 14:35:43.795 [18952] main C> entering the event loop + +.. _replication-controlled_failover: + +Controlled failover +------------------- + +To perform a **controlled failover**, that is, swap the roles of the master and +replica, all we need to do is to set ``read_only=true`` at the master, and +``read_only=false`` at the replica. The order of actions is important here. +If a system is running in production, we do not want concurrent writes happening +both at the replica and the master. Nor do we want the new replica to accept +any writes until it has finished fetching all replication data from the old +master. To compare replica and master state, we can use +:ref:`box.info.signature `. + +1. Set ``read_only=true`` at the master. + + .. code-block:: tarantoolsession + + # at the master + tarantool> box.cfg{read_only=true} + +2. Record the master’s current position with ``box.info.signature``, containing + the sum of all LSNs in the master’s vector clock. + + .. code-block:: tarantoolsession + + # at the master + tarantool> box.info.signature + +3. Wait until the replica’s signature is the same as the master’s. + + .. code-block:: tarantoolsession + + # at the replica + tarantool> box.info.signature + +4. Set ``read_only=false`` at the replica to enable write operations. + + .. code-block:: tarantoolsession + + # at the replica + tarantool> box.cfg{read_only=false} + +These four steps ensure that the replica doesn’t accept new writes until it’s done +fetching writes from the master. + +.. _replication-master_master_bootstrap: + +Master-master bootstrap +----------------------- + +Now let us bootstrap a two-instance **master-master** set. For easier +administration, we make master#1 and master#2 instance files fully identical. + +.. image:: mm-2m-mesh.png + :align: center + +We re-use the master's instance file from the +:ref:`master-replica example ` above. + +.. code-block:: lua + + -- instance file for any of the two masters + box.cfg{ + listen = 3301, + replication = {'replicator:password@192.168.0.101:3301', -- master1 URI + 'replicator:password@192.168.0.102:3301'}, -- master2 URI + read_only = false + } + box.once("schema", function() + box.schema.user.create('replicator', {password = 'password'}) + box.schema.user.grant('replicator', 'replication') -- grant replication role + box.schema.space.create("test") + box.space.test:create_index("primary") + print('box.once executed on master #1') + end) + +In the :ref:`replication ` parameter, we define the +URIs of both masters in the replica set and say +``print('box.once executed on master #1')`` so it will be clear when and where the +``box.once()`` logic is executed. + +Now we can launch the two masters. Again, the launch order doesn't matter. +The ``box.once()`` logic will also be executed only once, at the master which +is elected as the replica set :ref:`leader ` at bootstrap. + +.. code-block:: console + + $ # launching master #1 + $ tarantool master1.lua + 2017-06-14 15:39:03.062 [47021] main/101/master1.lua C> version 1.7.4-52-g980d30092 + 2017-06-14 15:39:03.062 [47021] main/101/master1.lua C> log level 5 + 2017-06-14 15:39:03.063 [47021] main/101/master1.lua I> mapping 268435456 bytes for tuple arena... + 2017-06-14 15:39:03.065 [47021] iproto/101/main I> binary: bound to [::]:3301 + 2017-06-14 15:39:03.065 [47021] main/105/applier/replicator@192.168.0.10 I> can't connect to master + 2017-06-14 15:39:03.065 [47021] main/105/applier/replicator@192.168.0.10 coio.cc:107 !> SystemError connect, called on fd 14, aka 192.168.0.102:57110: Connection refused + 2017-06-14 15:39:03.065 [47021] main/105/applier/replicator@192.168.0.10 I> will retry every 1 second + 2017-06-14 15:39:03.065 [47021] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301 + 2017-06-14 15:39:08.070 [47021] main/105/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.102:3301 + 2017-06-14 15:39:08.071 [47021] main/105/applier/replicator@192.168.0.10 I> authenticated + 2017-06-14 15:39:08.071 [47021] main/101/master1.lua I> bootstrapping replica from 192.168.0.102:3301 + 2017-06-14 15:39:08.073 [47021] main/105/applier/replicator@192.168.0.10 I> initial data received + 2017-06-14 15:39:08.074 [47021] main/105/applier/replicator@192.168.0.10 I> final data received + 2017-06-14 15:39:08.074 [47021] snapshot/101/main I> saving snapshot `/Users/e.shebunyaeva/work/tarantool-test-repl/master1_dir/00000000000000000008.snap.inprogress' + 2017-06-14 15:39:08.074 [47021] snapshot/101/main I> done + 2017-06-14 15:39:08.076 [47021] main/101/master1.lua I> vinyl checkpoint done + 2017-06-14 15:39:08.076 [47021] main/101/master1.lua I> ready to accept requests + box.once executed on master #1 + 2017-06-14 15:39:08.077 [47021] main C> entering the event loop + +.. code-block:: console + + $ # launching master #2 + $ tarantool master2.lua + 2017-06-14 15:39:07.452 [47022] main/101/master2.lua C> version 1.7.4-52-g980d30092 + 2017-06-14 15:39:07.453 [47022] main/101/master2.lua C> log level 5 + 2017-06-14 15:39:07.453 [47022] main/101/master2.lua I> mapping 268435456 bytes for tuple arena... + 2017-06-14 15:39:07.455 [47022] iproto/101/main I> binary: bound to [::]:3301 + 2017-06-14 15:39:07.455 [47022] main/104/applier/replicator@192.168.0.19 I> remote master is 1.7.4 at 192.168.0.101:3301 + 2017-06-14 15:39:07.455 [47022] main/105/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.102:3301 + 2017-06-14 15:39:07.455 [47022] main/101/master2.lua I> initializing an empty data directory + 2017-06-14 15:39:07.457 [47022] snapshot/101/main I> saving snapshot `/Users/e.shebunyaeva/work/tarantool-test-repl/master2_dir/00000000000000000000.snap.inprogress' + 2017-06-14 15:39:07.457 [47022] snapshot/101/main I> done + 2017-06-14 15:39:07.458 [47022] main/101/master2.lua I> vinyl checkpoint done + 2017-06-14 15:39:07.459 [47022] main/101/master2.lua I> ready to accept requests + 2017-06-14 15:39:07.460 [47022] main C> entering the event loop + 2017-06-14 15:39:08.072 [47022] main/103/main I> initial data sent. + 2017-06-14 15:39:08.073 [47022] relay/[::ffff:192.168.0.102]:/101/main I> recover from `/Users/e.shebunyaeva/work/tarantool-test-repl/master2_dir/00000000000000000000.xlog' + 2017-06-14 15:39:08.073 [47022] main/103/main I> final data sent. + 2017-06-14 15:39:08.077 [47022] relay/[::ffff:192.168.0.102]:/101/main I> recover from `/Users/e.shebunyaeva/work/tarantool-test-repl/master2_dir/00000000000000000000.xlog' + 2017-06-14 15:39:08.461 [47022] main/104/applier/replicator@192.168.0.10 I> authenticated diff --git a/doc/how-to/replication/repl_leader_elect.rst b/doc/how-to/replication/repl_leader_elect.rst new file mode 100644 index 0000000000..d3053b497f --- /dev/null +++ b/doc/how-to/replication/repl_leader_elect.rst @@ -0,0 +1,115 @@ +.. _how-to-repl_leader_elect: + +Managing leader elections +========================= + +Starting from version :doc:`2.6.1 `, +Tarantool has the built-in functionality +managing automated leader election in a replica set. +Learn more about the :ref:`concept of leader election `. + +.. _repl_leader_elect_config: + +Configuration +------------- + +.. code-block:: console + + box.cfg({ + election_mode = , + election_timeout = , + replication_timeout = , + replication_synchro_quorum = , + election_fencing_enabled = + }) + +* ``election_mode`` -- specifies the role of a node in the leader election + process. For the details, refer to the :ref:`option description ` + in the configuration reference. +* ``election_timeout`` -- specifies the timeout between election rounds if the + previous round ended up with a split vote. For the details, refer to the + :ref:`option description ` in the configuration + reference. +* ``replication_timeout`` -- reuse of the :ref:`replication_timeout ` + configuration option for the purpose of the leader election process. + Heartbeats sent by an active leader have a timeout after which a new election + starts. Heartbeats are sent once per seconds. + Default value is ``1``. The leader is considered dead if it hasn't sent any + heartbeats for the period of ``replication_timeout * 4``. +* ``replication_synchro_quorum`` -- reuse of the :ref:`replication_synchro_quorum ` + option for the purpose of configuring the election quorum. The default value is ``1``, + meaning that each node becomes a leader immediately after voting for itself. + It is the best to set up this option value to the ``( / 2) + 1``. + Otherwise, there is no guarantee that there is only one leader at a time. +* ``election_fencing_enabled`` -- switches the :ref:`leader fencing mode ` on and off. + For the details, refer to the :ref:`option description ` in the configuration reference. + +Besides, it is important to know that +being a leader is not the only requirement for a node to be writable. +A leader node should have its :ref:`read_only ` option set +to ``false`` (``box.cfg{read_only = false}``), +and its :ref:`connectivity quorum ` +should be satisfied (``box.cfg{replication_connect_quorum = }``) +or disabled (``box.cfg{replication_connect_quorum = 0}``). + +Nothing prevents from setting the ``read_only`` option to ``true``, +but the leader just won't be writable then. The option doesn't affect the +election process itself, so a read-only instance can still vote and become +a leader. + +.. _repl_leader_elect_monitoring: + +Monitoring +---------- + +To monitor the current state of a node regarding the leader election, you can +use the ``box.info.election`` function. +For details, +refer to the :doc:`function description `. + +**Example:** + +.. code-block:: console + + tarantool> box.info.election + --- + - state: follower + vote: 0 + leader: 0 + term: 1 + ... + +The Raft-based election implementation logs all its actions +with the ``RAFT:`` prefix. The actions are new Raft message handling, +node state changing, voting, term bumping, and so on. + +.. _repl_leader_elect_important: + +Important notes +--------------- + +Leader election won't work correctly if the election quorum is set to less or equal +than `` / 2`` because in that case, a split vote can lead to +a state when two leaders are elected at once. + +For example, let's assume there are five nodes. When quorum is set to ``2``, ``node1`` +and ``node2`` can both vote for ``node1``. ``node3`` and ``node4`` can both vote +for ``node5``. In this case, ``node1`` and ``node5`` both win the election. +When the quorum is set to the cluster majority, that is +``( / 2) + 1`` or bigger, the split vote is not possible. + +That should be considered when adding new nodes. +If the majority value is changing, it's better to update the quorum on all the existing nodes +before adding a new one. + +Also, the automated leader election won't bring many benefits in terms of data +safety when used *without* :ref:`synchronous replication `. +If the replication is asynchronous and a new leader gets elected, +the old leader is still active and considers itself the leader. +In such case, nothing stops +it from accepting requests from clients and making transactions. +Non-synchronous transactions will be successfully committed because +they won't be checked against the quorum of replicas. +Synchronous transactions will fail because they won't be able +to collect the quorum -- most of the replicas will reject +these old leader's transactions since it is not a leader anymore. diff --git a/doc/how-to/replication/repl_remove_instances.rst b/doc/how-to/replication/repl_remove_instances.rst new file mode 100644 index 0000000000..4ebd93cc25 --- /dev/null +++ b/doc/how-to/replication/repl_remove_instances.rst @@ -0,0 +1,225 @@ +.. _replication-remove_instances: + +Removing instances +================== + +Let's assume that we have the following configured replica set with 3 instances +(*instance1*, *instance2* and *intance3*) and we want to remove *instance2*. + +.. image:: /concepts/replication/images/replication.svg + :align: left + +To remove it politely, follow these steps: + +1. Disconnect *instance2* from the cluster. +2. Disconnect the cluster from *instance2*. +3. Remove *instance2* from the ``_cluster`` space. + +.. image:: replicationX.svg + :align: left + +**Step 1: disconnecting an instance from the cluster** + +On the disconnecting instance *instance2*, run ``box.cfg{}`` +with a blank replication source: + +.. code-block:: tarantoolsession + + tarantool> box.cfg{replication=''} + +Then check that it was disconnected. Take a look at ``box.info.replication`` +on *instance2* (notice that ``replication.{1,3}.upstream`` is absent): + +.. code-block:: tarantoolsession + + tarantool> box.info.replication + --- + - 1: + id: 1 + uuid: db89978f-7115-4537-8417-9982bb5a256f + lsn: 9 + -- upstream is absent + downstream: + status: follow + idle: 0.93983899999876 + vclock: {1: 9} + 2: + id: 2 + uuid: 0a756d14-e437-4296-85b0-d27a0621613e + lsn: 0 + 3: + id: 3 + uuid: bb362584-c265-4e53-aeb6-450ae818bf59 + lsn: 0 + -- upstream is absent + downstream: + status: follow + idle: 0.26624799999991 + vclock: {1: 9} + ... + +Check *instance1* and *instance3* as well +(notice that the status of ``replication.2.downstream`` is ``stopped``): + +.. code-block:: tarantoolsession + + -- instance1 + tarantool> box.info.replication + --- + - 1: + id: 1 + uuid: db89978f-7115-4537-8417-9982bb5a256f + lsn: 9 + 2: + id: 2 + uuid: 0a756d14-e437-4296-85b0-d27a0621613e + lsn: 0 + upstream: + status: follow + idle: 0.3533439999992 + peer: replicator@localhost:3302 + lag: 0.0001220703125 + downstream: + status: stopped -- status has changed: + message: unexpected EOF when reading from socket, called on fd 13, aka [::1]:3301, + peer of [::1]:53776 + system_message: Broken pipe + 3: + id: 3 + uuid: bb362584-c265-4e53-aeb6-450ae818bf59 + lsn: 0 + upstream: + status: follow + idle: 0.35327999999936 + peer: replicator@localhost:3303 + lag: 0.00018095970153809 + downstream: + status: follow + idle: 0.68685100000221 + vclock: {1: 9} + ... + +**Step 2: disconnecting the cluster from the decommissioned instance** + +On every other instance in the cluster remove *instance2* from +the ``box.cfg{ replication }`` list and call an appropriate +``box.cfg{ replication = {instance1, instance3} }``: + +.. code-block:: tarantoolsession + + tarantool> box.cfg{ replication = { 'instance1-uri', 'instance3-uri' } } + +Take a look at ``box.info.replication`` on *instance2* to check that *instance1* and *instance3* were +disconnected +(notice that the status of ``replication.{1,3}.downstream`` is ``stopped``): + +.. code-block:: tarantoolsession + + tarantool> box.info.replication + --- + - 1: + id: 1 + uuid: db89978f-7115-4537-8417-9982bb5a256f + lsn: 9 + downstream: + status: stopped -- status has changed + message: unexpected EOF when reading from socket, called on fd 16, aka [::1]:3302, + peer of [::1]:53832 + system_message: Broken pipe + 2: + id: 2 + uuid: 0a756d14-e437-4296-85b0-d27a0621613e + lsn: 0 + 3: + id: 3 + uuid: bb362584-c265-4e53-aeb6-450ae818bf59 + lsn: 0 + downstream: + status: stopped -- status has changed + message: unexpected EOF when reading from socket, called on fd 18, aka [::1]:3302, + peer of [::1]:53825 + system_message: Broken pipe + ... + +Check *instance1* and *instance3* as well +(notice that the status of ``replication.2.upstream`` is ``stopped``): + +.. code-block:: tarantoolsession + + -- instance1 + tarantool> box.info.replication + --- + - 1: + id: 1 + uuid: db89978f-7115-4537-8417-9982bb5a256f + lsn: 9 + 2: + id: 2 + uuid: 0a756d14-e437-4296-85b0-d27a0621613e + lsn: 0 + downstream: + status: stopped -- status has changed + message: unexpected EOF when reading from socket, called on fd 13, aka [::1]:3301, + peer of [::1]:53776 + system_message: Broken pipe + 3: + id: 3 + uuid: bb362584-c265-4e53-aeb6-450ae818bf59 + lsn: 0 + upstream: + status: follow + idle: 0.50240100000156 + peer: replicator@localhost:3303 + lag: 0.00015711784362793 + downstream: + status: follow + idle: 0.14237199999843 + vclock: {1: 9} + ... + +**Step 3: persistent removal** + +If a removed instance rejoins later, it will receive all the updates made +by the other instances while it was disconnected. + +If an instance is decommissioned forever, we should clean up the ``_cluster`` space. +First, discover the ``id`` and ``uuid`` of the instance. +On *instance2*, call ``return box.info.id, box.info.uuid``: + +.. code-block:: tarantoolsession + + tarantool> return box.info.id, box.info.uuid + --- + - 2 + - '0a756d14-e437-4296-85b0-d27a0621613e' + ... + +Take a note of ``id`` and ``uuid``. + +Now choose any master from the remaining cluster and perform the following actions on it +(let's assume that we chose *instance1*): + +1. Select all records from the ``_cluster`` space: + +.. code-block:: tarantoolsession + + tarantool> box.space._cluster:select{} + --- + - - [1, 'db89978f-7115-4537-8417-9982bb5a256f'] + - [2, '0a756d14-e437-4296-85b0-d27a0621613e'] + - [3, 'bb362584-c265-4e53-aeb6-450ae818bf59'] + ... + +2. Check if the ``id`` and ``uuid`` of *instance2* are correct and remove them + from the cluster: + +.. code-block:: tarantoolsession + + tarantool> box.space._cluster:delete(2) + --- + - [2, '0a756d14-e437-4296-85b0-d27a0621613e'] + ... + +**Final checks** + +After all modifications, say ``box.info.replication`` to check the health status. diff --git a/doc/how-to/replication/repl_sync.rst b/doc/how-to/replication/repl_sync.rst new file mode 100644 index 0000000000..9c89429eff --- /dev/null +++ b/doc/how-to/replication/repl_sync.rst @@ -0,0 +1,108 @@ +.. _how-to-repl_sync: + +Configuring synchronous replication +=================================== + +Since version :doc:`2.5.1 `, +:ref:`synchronous replication ` +can be enabled per-space by using the ``is_sync`` option: + +.. code-block:: lua + + box.schema.create_space('test1', {is_sync = true}) + +Any transaction doing a DML request on this space becomes synchronous. +Notice that DDL on this space (including truncation) is **not** synchronous. + +To control the behavior of synchronous transactions, there exist global +``box.cfg`` :ref:`options `: + +.. code-block:: lua + + box.cfg{replication_synchro_quorum = } + +.. code-block:: lua + + box.cfg{replication_synchro_quorum = "N / 2 + 1"} + +This option tells how many replicas should confirm the receipt of a synchronous transaction before it is committed. +Since version :doc:`2.5.3 `, the parameter supports dynamic evaluation of the quorum number +(see :ref:`reference for the replication_synchro_quorum parameter ` for details). +Since version :doc:`2.10.0 `, +this option does not account for anonymous replicas. +As a usage example, consider this: + +.. code-block:: lua + + -- Instance 1 + box.cfg{ + listen = 3313, + replication_synchro_quorum = 2, + } + box.schema.user.grant('guest', 'super') + _ = box.schema.space.create('sync', {is_sync=true}) + _ = _:create_index('pk') + +.. code-block:: lua + + -- Instance 2 + box.cfg{ + listen = 3314, + replication = 'localhost:3313' + } + +.. code-block:: lua + + -- Instance 1 + box.space.sync:replace{1} + +When the first instance makes ``replace()``, it won't finish until the second +instance confirms its receipt and successful appliance. Note that the quorum is +set to 2, but the transaction was still committed even though there is only one +replica. This is because the master instance itself also participates in the quorum. + +Now, if the second instance is down, the first one won't be able to commit any +synchronous change. + +.. code-block:: lua + + -- Instance 2 + Ctrl+D + +.. code-block:: tarantoolsession + + -- Instance 1 + tarantool> box.space.sync:replace{2} + --- + - error: Quorum collection for a synchronous transaction is timed out + ... + +The transaction wasn't committed because it failed to achieve the quorum in the +given time. The time is a second configuration option: + +.. code-block:: lua + + box.cfg{replication_synchro_timeout = } + +It tells how many seconds to wait for a synchronous transaction quorum +replication until it is declared failed and is rolled back. + +A successful synchronous transaction commit is persisted in the WAL as a special +CONFIRM record. The rollbacks are similarly persisted with a ROLLBACK record. + +The ``timeout`` and ``quorum`` options are not used on replicas. It means if +the master dies, the pending synchronous transactions will be kept waiting on +the replicas until a new master is elected. + + +Tips and tricks +--------------- + +If a transaction is rolled back, it does not mean the ROLLBACK message reached +the replicas. It still can happen that the master node suddenly dies, so the +transaction will be committed by the new master. Your application logic should be +ready for that. + +Synchronous transactions are better to use with full mesh. Then the replicas can +talk to each other in case of the master node's death and still confirm some +pending transactions. diff --git a/doc/book/replication/replicationX.svg b/doc/how-to/replication/replicationX.svg similarity index 100% rename from doc/book/replication/replicationX.svg rename to doc/how-to/replication/replicationX.svg diff --git a/doc/how-to/sql/sql_tutorial.rst b/doc/how-to/sql/sql_tutorial.rst index 74a01a3d0b..05ada58744 100644 --- a/doc/how-to/sql/sql_tutorial.rst +++ b/doc/how-to/sql/sql_tutorial.rst @@ -47,7 +47,7 @@ switch languages and specify the end-of-statement delimiter. Here we say: default language is SQL and statements end with semicolons. -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession tarantool> \set language sql tarantool> \set delimiter ; diff --git a/doc/reference/reference_rock/vshard/vshard_quick.rst b/doc/how-to/vshard_quick.rst similarity index 85% rename from doc/reference/reference_rock/vshard/vshard_quick.rst rename to doc/how-to/vshard_quick.rst index 3c94a3d252..0016c6f4cd 100644 --- a/doc/reference/reference_rock/vshard/vshard_quick.rst +++ b/doc/how-to/vshard_quick.rst @@ -1,8 +1,7 @@ -.. _vshard-quick-start: +.. _vshard-quick-start: -=============================================================================== -Quick start guide -=============================================================================== +Quick start with sharding +========================= For installation instructions, check out the :ref:`vshard installation manual `. @@ -20,7 +19,7 @@ All instances are managed using the ``tarantoolctl`` administrative utility whic Change the directory to ``example/`` and use ``make`` to run the development cluster: -.. code-block:: console +.. code-block:: console $ cd example/ $ make @@ -60,25 +59,25 @@ Change the directory to ``example/`` and use ``make`` to run the development clu Some ``tarantoolctl`` commands: -* ``tarantoolctl start router_1`` – start the router instance -* ``tarantoolctl enter router_1`` – enter the admin console +* ``tarantoolctl start router_1`` – start the router instance +* ``tarantoolctl enter router_1`` – enter the admin console The full list of ``tarantoolctl`` commands for managing Tarantool instances is available in the :ref:`tarantoolctl reference `. Essential ``make`` commands you need to know: -* ``make start`` – start all Tarantool instances -* ``make stop`` – stop all Tarantool instances -* ``make logcat`` – show logs from all instances -* ``make enter`` – enter the admin console on ``router_1`` -* ``make clean`` – clean up all persistent data -* ``make test`` – run the test suite (you can also run ``test-run.py`` in the ``test`` directory) -* ``make`` – execute ``make stop``, ``make clean``, ``make start`` and ``make enter`` +* ``make start`` – start all Tarantool instances +* ``make stop`` – stop all Tarantool instances +* ``make logcat`` – show logs from all instances +* ``make enter`` – enter the admin console on ``router_1`` +* ``make clean`` – clean up all persistent data +* ``make test`` – run the test suite (you can also run ``test-run.py`` in the ``test`` directory) +* ``make`` – execute ``make stop``, ``make clean``, ``make start`` and ``make enter`` For example, to start all instances, use ``make start``: -.. code-block:: console +.. code-block:: console $ make start $ ps x|grep tarantool @@ -91,7 +90,7 @@ For example, to start all instances, use ``make start``: To perform commands in the admin console, use the router's :ref:`public API `: -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession unix/:./data/router_1.control> vshard.router.info() --- @@ -121,15 +120,14 @@ To perform commands in the admin console, use the router's alerts: [] ... -.. _vshard-config-cluster-example: +.. _vshard-config-cluster-example: -------------------------------------------------------------------------------- Sample configuration -------------------------------------------------------------------------------- +-------------------- The configuration of a simple sharded cluster can look like this: -.. code-block:: kconfig +.. code-block:: kconfig local cfg = { memtx_memory = 100 * 1024 * 1024, @@ -175,7 +173,7 @@ See the :ref:`Configuration reference ` section for det On routers, call ``vshard.router.cfg(cfg)``: -.. code-block:: lua +.. code-block:: lua cfg.listen = 3300 @@ -185,7 +183,7 @@ On routers, call ``vshard.router.cfg(cfg)``: On storages, call ``vshard.storage.cfg(cfg, instance_uuid)``: -.. code-block:: lua +.. code-block:: lua -- Get instance name local MY_UUID = "de0ea826-e71d-4a82-bbf3-b04a6413e417" diff --git a/doc/index.rst b/doc/index.rst index 03ffbae555..e900f24d6c 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -53,18 +53,10 @@ overview getting_started/index how-to/index - book/box/data_model + concepts/index CRUD operations - book/box/indexes - book/box/atomic - book/box/authentication - book/box/triggers - reference/reference_rock/vshard/vshard_index Cluster on Cartridge - book/app_server/index book/admin/index - book/replication/index - book/box/engines/index book/connectors reference/index contributing/index diff --git a/doc/overview.rst b/doc/overview.rst index 89447021aa..6bff5e7049 100644 --- a/doc/overview.rst +++ b/doc/overview.rst @@ -14,20 +14,26 @@ Here are some of Tarantool's key characteristics: * **Easy handling of OLTP workloads**: processes hundreds of thousands RPS -* **Data integrity**: write-ahead log (WAL) and data snapshots +* **Data integrity**: :ref:`write-ahead log (WAL) ` + and :ref:`data snapshots ` -* **Cooperative multitasking**: transactions are performed in lightweight coroutines with no interthread locking +* **Cooperative multitasking**: transactions are performed in + :ref:`lightweight coroutines ` with no interthread locking -* **Advanced indexing**: composite indexes, locale support, indexing by nested fields and arrays +* **Advanced indexing**: :ref:`composite indexes `, + :ref:`locale support `, + indexing by :ref:`nested fields and arrays ` -* **Compute close to data**: Lua server and Just-In-Time compiler on board +* **Compute close to data**: :ref:`Lua server ` + and Just-In-Time compiler on board -* **Durable distributed storage**: multiple failover modes and RAFT-based synchronous replication available +* **Durable distributed storage**: multiple failover modes and + :ref:`RAFT-based synchronous replication ` available Tarantool allows executing code alongside data, which helps increase the speed of operations. -Developers can implement any business logic with Lua, -and a single Tarantool instance can also receive SQL requests. +Developers can :ref:`implement any business logic with Lua `, +and a single Tarantool instance can also receive :ref:`SQL requests `. Tarantool has a variety of compatible `modules `__ (Lua rocks). You can pick the ones that you need and install them manually. diff --git a/doc/reference/configuration/index.rst b/doc/reference/configuration/index.rst index 147aa5a21d..4dab4a9502 100644 --- a/doc/reference/configuration/index.rst +++ b/doc/reference/configuration/index.rst @@ -312,7 +312,7 @@ The priority of parameter sources is the following, from higher to lower: * ``box.cfg`` options * :ref:`environment variables ` -* :doc:`tarantoolctl ` options +* :doc:`tarantoolctl ` options * default values. .. _box-cfg-params-env: diff --git a/doc/reference/index.rst b/doc/reference/index.rst index e21c08b3b9..eb61be86a6 100644 --- a/doc/reference/index.rst +++ b/doc/reference/index.rst @@ -10,14 +10,12 @@ Reference .. toctree:: :maxdepth: 2 + configuration/index + tooling/index reference_sql/index reference_lua/index reference_rock/index - configuration/index ../dev_guide/reference_capi/index ../dev_guide/internals/index ../book/box/limitations - interactive_console - tt_cli/index - tarantoolctl lua_tips diff --git a/doc/reference/reference_lua/box_ctl/promote.rst b/doc/reference/reference_lua/box_ctl/promote.rst index caaa39fa82..d209aa37ee 100644 --- a/doc/reference/reference_lua/box_ctl/promote.rst +++ b/doc/reference/reference_lua/box_ctl/promote.rst @@ -7,7 +7,7 @@ box.ctl.promote() Wait, then choose new replication leader. - For :doc:`synchronous transactions ` it is + For :ref:`synchronous transactions ` it is possible that a new leader will be chosen but the transactions of the old leader have not been completed. Therefore to finalize the transaction, the function ``box.ctl.promote()`` diff --git a/doc/reference/reference_lua/box_events.rst b/doc/reference/reference_lua/box_events.rst index 513c57faed..5d9d355732 100644 --- a/doc/reference/reference_lua/box_events.rst +++ b/doc/reference/reference_lua/box_events.rst @@ -24,7 +24,7 @@ Each event subscription is defined by a certain key. To update a state, use the ``box.broadcast()`` function. Watcher - A watcher is a :doc:`callback ` that is invoked when a state change occurs. + A watcher is a :doc:`callback ` that is invoked when a state change occurs. To register a local watcher, use the ``box.watch()`` function. To create a remote watcher, use the ``watch()`` function from the ``net.box`` module. Note that it is possible to register more than one watcher for the same key. diff --git a/doc/reference/reference_lua/box_index/stat.rst b/doc/reference/reference_lua/box_index/stat.rst index 1b998ecb8d..da66347c0e 100644 --- a/doc/reference/reference_lua/box_index/stat.rst +++ b/doc/reference/reference_lua/box_index/stat.rst @@ -28,7 +28,7 @@ index_object:stat() * ``index_object:stat().dumps_per_compaction`` -- average number of dumps required to trigger major compaction in any range of the LSM tree. Summary index statistics are also available via - :ref:`box.stat.vinyl() `. + :ref:`box.stat.vinyl() `. :param index_object index_object: an :ref:`object reference `. diff --git a/doc/reference/reference_lua/box_info/replication.rst b/doc/reference/reference_lua/box_info/replication.rst index 02f7de74eb..35d37328a1 100644 --- a/doc/reference/reference_lua/box_info/replication.rst +++ b/doc/reference/reference_lua/box_info/replication.rst @@ -130,6 +130,6 @@ box.info.replication For better understanding, see the following diagram illustrating the ``upstream`` and ``downstream`` connections within the replica set of three instances: - .. image:: /book/replication/replication.svg + .. image:: /concepts/replication/images/replication.svg :align: left diff --git a/doc/reference/reference_lua/box_stat/vinyl.rst b/doc/reference/reference_lua/box_stat/vinyl.rst index ff5bb43fc3..90fed307b4 100644 --- a/doc/reference/reference_lua/box_stat/vinyl.rst +++ b/doc/reference/reference_lua/box_stat/vinyl.rst @@ -189,4 +189,5 @@ for dumping or compaction: try to arrange a dump before this hard limit is reached. A dump will also occur during a - :doc:`snapshot ` operation. \ No newline at end of file + :doc:`snapshot ` operation. + \ No newline at end of file diff --git a/doc/reference/reference_rock/vshard/index.rst b/doc/reference/reference_rock/vshard/index.rst index f63cc3803b..3d1c7a63da 100644 --- a/doc/reference/reference_rock/vshard/index.rst +++ b/doc/reference/reference_rock/vshard/index.rst @@ -8,16 +8,14 @@ The ``vshard`` module introduces an advanced sharding feature based on the concept of :ref:`virtual buckets ` and enables horizontal scaling in Tarantool. -Check out the :ref:`Quick start guide ` -- or dive into the -complete ``vshard`` documentation: +To learn how sharding works in Tarantool, refer to the :ref:`Sharding ` page. + +You can also check out the :ref:`Quick start guide ` -- or dive into the +``vshard`` reference: .. toctree:: :maxdepth: 2 :numbered: 0 - vshard_summary_index - vshard_architecture - vshard_admin - vshard_quick vshard_ref vshard_api diff --git a/doc/reference/reference_rock/vshard/vshard_index.rst b/doc/reference/reference_rock/vshard/vshard_index.rst deleted file mode 100644 index 2f34faafa5..0000000000 --- a/doc/reference/reference_rock/vshard/vshard_index.rst +++ /dev/null @@ -1,23 +0,0 @@ -:fullwidth: - -.. _sharding: - -******************************************************************************** -Sharding -******************************************************************************** - -.. include:: ./_includes/vshard_summary.rst - -Check out the :ref:`Quick start guide ` -- or dive into the -complete ``vshard`` documentation: - -.. toctree:: - :maxdepth: 2 - :numbered: 0 - - vshard_architecture - vshard_admin - vshard_quick - vshard_ref - vshard_api - diff --git a/doc/reference/reference_rock/vshard/vshard_summary_index.rst b/doc/reference/reference_rock/vshard/vshard_summary_index.rst deleted file mode 100644 index f12dc2ee74..0000000000 --- a/doc/reference/reference_rock/vshard/vshard_summary_index.rst +++ /dev/null @@ -1,5 +0,0 @@ -=============================================================================== -Summary -=============================================================================== - -.. include:: ./_includes/vshard_summary.rst diff --git a/doc/reference/tooling/index.rst b/doc/reference/tooling/index.rst new file mode 100644 index 0000000000..d68e4c91ec --- /dev/null +++ b/doc/reference/tooling/index.rst @@ -0,0 +1,14 @@ +Tooling +======= + +This chapter describes the tools that enable developers and administrators +to work with Tarantool. + +.. toctree:: + :maxdepth: 1 + + interactive_console + tt_cli/index + tarantoolctl + luajit_memprof + luajit_getmetrics diff --git a/doc/reference/interactive_console.rst b/doc/reference/tooling/interactive_console.rst similarity index 100% rename from doc/reference/interactive_console.rst rename to doc/reference/tooling/interactive_console.rst diff --git a/doc/book/app_server/luajit_getmetrics.rst b/doc/reference/tooling/luajit_getmetrics.rst similarity index 99% rename from doc/book/app_server/luajit_getmetrics.rst rename to doc/reference/tooling/luajit_getmetrics.rst index 6afcec1123..8fb026c181 100644 --- a/doc/book/app_server/luajit_getmetrics.rst +++ b/doc/reference/tooling/luajit_getmetrics.rst @@ -1,3 +1,4 @@ +.. _luajit_getmetrics: LuaJIT getmetrics ================= @@ -124,7 +125,7 @@ Note: Although value names are similar to value names in `ujit.getmetrics() `_ the values are not the same, primarily because many ujit numbers are not monotonic. -Note: Although value names are similar to value names in :ref:`LuaJIT metrics `, +Note: Although value names are similar to value names in :ref:`LuaJIT metrics `, and the values are exactly the same, misc.getmetrics() is slightly easier because there is no need to ‘require’ the misc module. diff --git a/doc/book/app_server/luajit_memprof.rst b/doc/reference/tooling/luajit_memprof.rst similarity index 99% rename from doc/book/app_server/luajit_memprof.rst rename to doc/reference/tooling/luajit_memprof.rst index 5985a1a262..fb533bb1b9 100644 --- a/doc/book/app_server/luajit_memprof.rst +++ b/doc/reference/tooling/luajit_memprof.rst @@ -1,3 +1,4 @@ +.. _luajit_memprof: LuaJIT memory profiler ====================== diff --git a/doc/reference/tarantoolctl.rst b/doc/reference/tooling/tarantoolctl.rst similarity index 100% rename from doc/reference/tarantoolctl.rst rename to doc/reference/tooling/tarantoolctl.rst diff --git a/doc/reference/tt_cli/arguments.rst b/doc/reference/tooling/tt_cli/arguments.rst similarity index 100% rename from doc/reference/tt_cli/arguments.rst rename to doc/reference/tooling/tt_cli/arguments.rst diff --git a/doc/reference/tt_cli/cat.rst b/doc/reference/tooling/tt_cli/cat.rst similarity index 100% rename from doc/reference/tt_cli/cat.rst rename to doc/reference/tooling/tt_cli/cat.rst diff --git a/doc/reference/tt_cli/check.rst b/doc/reference/tooling/tt_cli/check.rst similarity index 100% rename from doc/reference/tt_cli/check.rst rename to doc/reference/tooling/tt_cli/check.rst diff --git a/doc/reference/tt_cli/commands.rst b/doc/reference/tooling/tt_cli/commands.rst similarity index 100% rename from doc/reference/tt_cli/commands.rst rename to doc/reference/tooling/tt_cli/commands.rst diff --git a/doc/reference/tt_cli/completion.rst b/doc/reference/tooling/tt_cli/completion.rst similarity index 100% rename from doc/reference/tt_cli/completion.rst rename to doc/reference/tooling/tt_cli/completion.rst diff --git a/doc/reference/tt_cli/configuration.rst b/doc/reference/tooling/tt_cli/configuration.rst similarity index 100% rename from doc/reference/tt_cli/configuration.rst rename to doc/reference/tooling/tt_cli/configuration.rst diff --git a/doc/reference/tt_cli/connect.rst b/doc/reference/tooling/tt_cli/connect.rst similarity index 100% rename from doc/reference/tt_cli/connect.rst rename to doc/reference/tooling/tt_cli/connect.rst diff --git a/doc/reference/tt_cli/coredump.rst b/doc/reference/tooling/tt_cli/coredump.rst similarity index 100% rename from doc/reference/tt_cli/coredump.rst rename to doc/reference/tooling/tt_cli/coredump.rst diff --git a/doc/reference/tt_cli/external_modules.rst b/doc/reference/tooling/tt_cli/external_modules.rst similarity index 100% rename from doc/reference/tt_cli/external_modules.rst rename to doc/reference/tooling/tt_cli/external_modules.rst diff --git a/doc/reference/tt_cli/help.rst b/doc/reference/tooling/tt_cli/help.rst similarity index 100% rename from doc/reference/tt_cli/help.rst rename to doc/reference/tooling/tt_cli/help.rst diff --git a/doc/reference/tt_cli/index.rst b/doc/reference/tooling/tt_cli/index.rst similarity index 92% rename from doc/reference/tt_cli/index.rst rename to doc/reference/tooling/tt_cli/index.rst index 1b3fa60c92..875a269e96 100644 --- a/doc/reference/tt_cli/index.rst +++ b/doc/reference/tooling/tt_cli/index.rst @@ -1,3 +1,5 @@ +.. _tt-cli: + tt CLI utility ============== @@ -6,7 +8,7 @@ Tarantool-based applications. It covers a wide range of tasks -- from installing a specific Tarantool version to managing remote instances and developing applications. A multi-purpose tool for working with Tarantool from the command line, ``tt`` is -a potential replacement for :doc:`tarantoolctl ` +a potential replacement for :ref:`tarantoolctl ` and :doc:`Cartridge CLI `. .. warning:: diff --git a/doc/reference/tt_cli/installation.rst b/doc/reference/tooling/tt_cli/installation.rst similarity index 100% rename from doc/reference/tt_cli/installation.rst rename to doc/reference/tooling/tt_cli/installation.rst diff --git a/doc/reference/tt_cli/logrotate.rst b/doc/reference/tooling/tt_cli/logrotate.rst similarity index 100% rename from doc/reference/tt_cli/logrotate.rst rename to doc/reference/tooling/tt_cli/logrotate.rst diff --git a/doc/reference/tt_cli/play.rst b/doc/reference/tooling/tt_cli/play.rst similarity index 100% rename from doc/reference/tt_cli/play.rst rename to doc/reference/tooling/tt_cli/play.rst diff --git a/doc/reference/tt_cli/restart.rst b/doc/reference/tooling/tt_cli/restart.rst similarity index 100% rename from doc/reference/tt_cli/restart.rst rename to doc/reference/tooling/tt_cli/restart.rst diff --git a/doc/reference/tt_cli/rocks.rst b/doc/reference/tooling/tt_cli/rocks.rst similarity index 100% rename from doc/reference/tt_cli/rocks.rst rename to doc/reference/tooling/tt_cli/rocks.rst diff --git a/doc/reference/tt_cli/start.rst b/doc/reference/tooling/tt_cli/start.rst similarity index 100% rename from doc/reference/tt_cli/start.rst rename to doc/reference/tooling/tt_cli/start.rst diff --git a/doc/reference/tt_cli/status.rst b/doc/reference/tooling/tt_cli/status.rst similarity index 100% rename from doc/reference/tt_cli/status.rst rename to doc/reference/tooling/tt_cli/status.rst diff --git a/doc/reference/tt_cli/stop.rst b/doc/reference/tooling/tt_cli/stop.rst similarity index 100% rename from doc/reference/tt_cli/stop.rst rename to doc/reference/tooling/tt_cli/stop.rst diff --git a/doc/reference/tt_cli/version.rst b/doc/reference/tooling/tt_cli/version.rst similarity index 100% rename from doc/reference/tt_cli/version.rst rename to doc/reference/tooling/tt_cli/version.rst diff --git a/doc/release/2.5.1.rst b/doc/release/2.5.1.rst index 4dbb6bdcd3..777100fee6 100644 --- a/doc/release/2.5.1.rst +++ b/doc/release/2.5.1.rst @@ -80,7 +80,7 @@ Replication exception is that anonymous replicas are indexed by their uuid strings (:tarantool-issue:`4900`). - Allow anonymous replicas to be followed by other ones (:tarantool-issue:`4696`). -- :doc:`Synchronous replication ` +- :ref:`Synchronous replication ` can be enabled per-space using the ``is_sync`` space option (:tarantool-issue:`4842`). Build diff --git a/doc/release/2.6.1.rst b/doc/release/2.6.1.rst index a87d683cf0..3aeb8c43af 100644 --- a/doc/release/2.6.1.rst +++ b/doc/release/2.6.1.rst @@ -34,7 +34,7 @@ Notable changes are: Read more: - * :doc:`/book/replication/repl_leader_elect` + * :ref:`Automated leader election ` * :ref:`election_mode configuration parameter ` * :ref:`election_timeout configuration parameter ` * :doc:`/reference/reference_lua/box_info/election` @@ -111,7 +111,7 @@ Replication ~~~~~~~~~~~ - Automated leader election based on Raft algorithm (:tarantool-issue:`1146`). - Read more: :doc:`/book/replication/repl_leader_elect`. + Read more: :ref:`Automated leader election `. - When election is enabled, a newly elected leader will automatically finish all the synchronous transactions, created by the old leader (:tarantool-issue:`5339`). diff --git a/doc/release/2.7.1.rst b/doc/release/2.7.1.rst index c05e9cd309..ea869f942c 100644 --- a/doc/release/2.7.1.rst +++ b/doc/release/2.7.1.rst @@ -17,7 +17,7 @@ issue `_ on GitHub. Notable changes are: -- :doc:`LuaJIT memory profiler `; +- :ref:`LuaJIT memory profiler `; - Expression evaluation for ``replication_synchro_quorum``; - The :ref:`ALTER TABLE ADD COLUMN ` statement. @@ -64,7 +64,7 @@ LuaJIT - Introduced the LuaJIT memory profiler (:tarantool-issue:`5442`) and the profile parser (:tarantool-issue:`5490`). - Read more: :doc:`/book/app_server/luajit_memprof`. + Read more: :ref:`LuaJIT memory profiler `. Lua ~~~ diff --git a/doc/release/major-features.rst b/doc/release/major-features.rst index 476846b92a..4b2ee2ba38 100644 --- a/doc/release/major-features.rst +++ b/doc/release/major-features.rst @@ -68,7 +68,7 @@ Versions that only include bug fixes are not listed in this table. - ``--leak-only`` LuaJIT memory profiler option (:tarantool-issue:`5812`) * - 2.7.1 - - :doc:`LuaJIT memory profiler ` (:tarantool-issue:`5442`) + - :ref:`LuaJIT memory profiler ` (:tarantool-issue:`5442`) * - 2.7.1 - SQL :doc:`ALTER TABLE ADD COLUMN ` statement support for empty tables (:tarantool-issue:`2349`, :tarantool-issue:`3075`) @@ -83,7 +83,7 @@ Versions that only include bug fixes are not listed in this table. - :ref:`LuaJIT platform metrics ` (:tarantool-issue:`5187`) * - 2.6.1 - - :doc:`Automated leader election ` based on Raft algorithm (:tarantool-issue:`1146`) + - :ref:`Automated leader election ` based on Raft algorithm (:tarantool-issue:`1146`) * - 2.6.1 - :ref:`Transactional manager ` for memtx engine (:tarantool-issue:`4897`) @@ -95,7 +95,7 @@ Versions that only include bug fixes are not listed in this table. - :doc:`box.ctl.is_recovery_finished() ` for memtx engine (:tarantool-issue:`5187`) * - 2.5.1 - - :doc:`Synchronous replication ` (beta) (:tarantool-issue:`4842`) + - :ref:`Synchronous replication ` (beta) (:tarantool-issue:`4842`) * - 2.5.1 - Allow an :doc:`anonymous replica ` to follow another anonymous replica (:tarantool-issue:`4696`) diff --git a/doc/toctree.rst b/doc/toctree.rst index ff117ede8e..feb0908bcd 100644 --- a/doc/toctree.rst +++ b/doc/toctree.rst @@ -8,18 +8,10 @@ overview getting_started/index how-to/index - book/box/data_model + concepts/index CRUD operations - book/box/indexes - book/box/atomic - book/box/authentication - book/box/triggers - reference/reference_rock/vshard/vshard_index Cluster on Cartridge - book/app_server/index book/admin/index - book/replication/index - book/box/engines/index book/connectors reference/index release/index diff --git a/locale/ru/LC_MESSAGES/book/box/authentication.po b/locale/ru/LC_MESSAGES/book/admin/access_control.po similarity index 98% rename from locale/ru/LC_MESSAGES/book/box/authentication.po rename to locale/ru/LC_MESSAGES/book/admin/access_control.po index af9420e721..0023920162 100644 --- a/locale/ru/LC_MESSAGES/book/box/authentication.po +++ b/locale/ru/LC_MESSAGES/book/admin/access_control.po @@ -3,14 +3,12 @@ msgid "Access control" msgstr "Управление доступом" msgid "" -"Understanding security details is primarily an issue for administrators. " -"However, ordinary users should at least skim this section to get an idea of " +"This section explains " "how Tarantool makes it possible for administrators to prevent unauthorized " "access to the database and to certain functions." msgstr "" -"В основном администраторы занимаются вопросами настроек безопасности. Однако" -" обычные пользователи должны хотя бы бегло прочитать этот раздел, чтобы " -"понять, как Tarantool позволяет администраторам не допустить " +"В этом разделе объясняется, " +"как Tarantool позволяет администраторам не допустить " "неавторизованный доступ к базе данных и некоторым функциям." msgid "Briefly:" diff --git a/locale/ru/LC_MESSAGES/book/app_server/reloading_module.po b/locale/ru/LC_MESSAGES/book/admin/modules.po similarity index 54% rename from locale/ru/LC_MESSAGES/book/app_server/reloading_module.po rename to locale/ru/LC_MESSAGES/book/admin/modules.po index 60414bbba4..0768df042d 100644 --- a/locale/ru/LC_MESSAGES/book/app_server/reloading_module.po +++ b/locale/ru/LC_MESSAGES/book/admin/modules.po @@ -1,4 +1,147 @@ +msgid "Installing a module" +msgstr "Установка модуля" + +msgid "" +"Modules in Lua and C that come from Tarantool developers and community " +"contributors are available in the following locations:" +msgstr "" +"Модули на Lua и C от разработчиков Tarantool и сторонних разработчиков " +"доступны здесь:" + +msgid "" +"Tarantool modules repository (see :ref:`below `)" +msgstr "" +"Репозиторий модулей Tarantool (см. :ref:`ниже `)" + +msgid "" +"Tarantool deb/rpm repositories (see :ref:`below `)" +msgstr "" +"Репозитории deb/rpm Tarantool (см. :ref:`ниже `)" + +msgid "Installing a module from a repository" +msgstr "Установка модуля из репозитория" + +msgid "" +"See `README in tarantool/rocks repository " +"`_ " +"for detailed instructions." +msgstr "" +"Для получения подробной информации см. `README в репозитории tarantool/rocks" +" `_." + +msgid "Installing a module from deb/rpm" +msgstr "Установка модуля из deb/rpm" + +msgid "Follow these steps:" +msgstr "Выполните следующие действия:" + +msgid "" +"Install Tarantool as recommended on the `download page " +"`_." +msgstr "" +"Установите Tarantool в соответствии с рекомендациями на `странице загрузки " +"`_." + +msgid "" +"Install the module you need. Look up the module's name on `Tarantool rocks " +"page `_ and put the prefix \"tarantool-\" " +"before the module name to avoid ambiguity:" +msgstr "" +"Установите необходимый модуль. Найдите имя модуля на `странице со сторонними" +" библиотеками Tarantool `_ и введите " +"префикс \"tarantool-\" перед названием модуля во избежание неоднозначности:" + +msgid "" +"$ # for Ubuntu/Debian:\n" +"$ sudo apt-get install tarantool-\n" +"\n" +"$ # for RHEL/CentOS/Amazon:\n" +"$ sudo yum install tarantool-" +msgstr "" +"$ # для Ubuntu/Debian:\n" +"$ sudo apt-get install tarantool-\n" +"\n" +"$ # для RHEL/CentOS/Amazon:\n" +"$ sudo yum install tarantool-" + +msgid "" +"For example, to install the module `shard " +"`_ on Ubuntu, say:" +msgstr "" +"Например, чтобы установить модуль `shard " +"`_ на Ubuntu, введите:" + +msgid "$ sudo apt-get install tarantool-shard" +msgstr "$ sudo apt-get install tarantool-shard" + +msgid "Once these steps are complete, you can:" +msgstr "Теперь можно:" + +msgid "load any module with" +msgstr "загружать любой модуль с помощью" + +msgid "tarantool> name = require('module-name')" +msgstr "tarantool> name = require('module-name')" + +msgid "for example:" +msgstr "например:" + +msgid "tarantool> shard = require('shard')" +msgstr "tarantool> shard = require('shard')" + +msgid "" +"search locally for installed modules using ``package.path`` (Lua) or " +"``package.cpath`` (C):" +msgstr "" +"локально находить установленные модули с помощью ``package.path`` (Lua) или " +"``package.cpath`` (C):" + +msgid "" +"tarantool> package.path\n" +"---\n" +"- ./?.lua;./?/init.lua; /usr/local/share/tarantool/?.lua;/usr/local/share/\n" +"tarantool/?/init.lua;/usr/share/tarantool/?.lua;/usr/share/tarantool/?/ini\n" +"t.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/\n" +"usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;\n" +"...\n" +"\n" +"tarantool> package.cpath\n" +"---\n" +"- ./?.so;/usr/local/lib/x86_64-linux-gnu/tarantool/?.so;/usr/lib/x86_64-li\n" +"nux-gnu/tarantool/?.so;/usr/local/lib/tarantool/?.so;/usr/local/lib/x86_64\n" +"-linux-gnu/lua/5.1/?.so;/usr/lib/x86_64-linux-gnu/lua/5.1/?.so;/usr/local/\n" +"lib/lua/5.1/?.so;\n" +"..." +msgstr "" +"tarantool> package.path\n" +"---\n" +"- ./?.lua;./?/init.lua; /usr/local/share/tarantool/?.lua;/usr/local/share/\n" +"tarantool/?/init.lua;/usr/share/tarantool/?.lua;/usr/share/tarantool/?/ini\n" +"t.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/\n" +"usr/share/lua/5.1/?.lua;/usr/share/lua/5.1/?/init.lua;\n" +"...\n" +"\n" +"tarantool> package.cpath\n" +"---\n" +"- ./?.so;/usr/local/lib/x86_64-linux-gnu/tarantool/?.so;/usr/lib/x86_64-li\n" +"nux-gnu/tarantool/?.so;/usr/local/lib/tarantool/?.so;/usr/local/lib/x86_64\n" +"-linux-gnu/lua/5.1/?.so;/usr/lib/x86_64-linux-gnu/lua/5.1/?.so;/usr/local/\n" +"lib/lua/5.1/?.so;\n" +"..." + +msgid "" +"Question-marks stand for the module name that was specified earlier when " +"saying ``require('module-name')``." +msgstr "" +"Знаки вопроса стоят вместо имени модуля, которое было указано ранее при " +"вызове ``require('module-name')``." + + msgid "Reloading a module" msgstr "Перезагрузка модуля" @@ -194,3 +337,4 @@ msgstr "" "``*.so``), вызовите функцию :doc:`box.schema.func.reload('module-name') " "` из Lua-скрипта для " "перезагрузки модуля." + diff --git a/locale/ru/LC_MESSAGES/book/replication/repl_monitoring.po b/locale/ru/LC_MESSAGES/book/admin/replication/repl_monitoring.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/replication/repl_monitoring.po rename to locale/ru/LC_MESSAGES/book/admin/replication/repl_monitoring.po diff --git a/locale/ru/LC_MESSAGES/book/replication/repl_problem_solving.po b/locale/ru/LC_MESSAGES/book/admin/replication/repl_problem_solving.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/replication/repl_problem_solving.po rename to locale/ru/LC_MESSAGES/book/admin/replication/repl_problem_solving.po diff --git a/locale/ru/LC_MESSAGES/book/replication/repl_recover.po b/locale/ru/LC_MESSAGES/book/admin/replication/repl_recover.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/replication/repl_recover.po rename to locale/ru/LC_MESSAGES/book/admin/replication/repl_recover.po diff --git a/locale/ru/LC_MESSAGES/book/replication/repl_reseed.po b/locale/ru/LC_MESSAGES/book/admin/replication/repl_reseed.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/replication/repl_reseed.po rename to locale/ru/LC_MESSAGES/book/admin/replication/repl_reseed.po diff --git a/locale/ru/LC_MESSAGES/reference/reference_rock/vshard/vshard_admin.po b/locale/ru/LC_MESSAGES/book/admin/vshard_admin.po similarity index 99% rename from locale/ru/LC_MESSAGES/reference/reference_rock/vshard/vshard_admin.po rename to locale/ru/LC_MESSAGES/book/admin/vshard_admin.po index 5fc25f1c7b..3ab375e2cd 100644 --- a/locale/ru/LC_MESSAGES/reference/reference_rock/vshard/vshard_admin.po +++ b/locale/ru/LC_MESSAGES/book/admin/vshard_admin.po @@ -1,6 +1,14 @@ -msgid "Administration" -msgstr "Администрирование" +msgid "Sharding with vshard" +msgstr "Шардирование с vshard" + +msgid "" +"Sharding in Tarantool is implemented in the ``vshard`` module. " +"For a quick start with ``vshard``, refer to the :ref:`guide `." +msgstr "" +"Шардирование БД в Tarantool реализует модуль ``vshard``. " +"Вы можете обратиться к :ref:`руководству по быстрому запуску ` " +"этого модуля." msgid "Installation" msgstr "Установка" diff --git a/locale/ru/LC_MESSAGES/book/box/data_model.po b/locale/ru/LC_MESSAGES/book/box/data_model.po deleted file mode 100644 index 9643036c91..0000000000 --- a/locale/ru/LC_MESSAGES/book/box/data_model.po +++ /dev/null @@ -1,2121 +0,0 @@ - -msgid "Data model" -msgstr "Модель данных" - -msgid "" -"This section describes how Tarantool stores values and what operations with " -"data it supports." -msgstr "" -"В этом разделе описывается то, как в Tarantool организовано хранение данных " -"и какие операции с данными он поддерживает." - -msgid "" -"If you tried to create a database as suggested in our :ref:`\"Getting " -"started\" exercises `, then your test database now looks" -" like this:" -msgstr "" -"Если вы пробовали создать базу данных, как предлагается в упражнениях в " -":ref:`\"Руководстве для начинающих\" `, то ваша тестовая" -" база данных выглядит следующим образом:" - -msgid "Tuples" -msgstr "Кортежи" - -msgid "Tarantool operates data in the form of tuples." -msgstr "Tarantool обрабатывает данные в виде кортежей." - -msgid "tuple" -msgstr "кортеж" - -msgid "" -"A tuple is a group of data values in Tarantool's memory. Think of it as a " -"\"database record\" or a \"row\". The data values in the tuple are called " -":term:`fields `." -msgstr "" -"Кортеж — это группа значений данных в памяти Tarantool. По сути, это " -"\"запись в базе данных\" или \"строка\". Значения данных в кортеже " -"называются :term:`полями `." - -msgid "" -"When Tarantool returns a tuple value in the console, by default, it uses " -":ref:`YAML ` format, for example: ``[3, 'Ace of Base', " -"1993]``." -msgstr "" -"Когда Tarantool выводит значение кортежа в консоль, по умолчанию " -"используется формат :ref:`YAML `, например: ``[3, 'Ace " -"of Base', 1993]``." - -msgid "" -"Internally, Tarantool stores tuples as `MsgPack " -"`_ arrays." -msgstr "" -"В Tarantool кортежи хранятся в виде массивов в формате `MsgPack " -"`_." - -msgid "field" -msgstr "поле" - -msgid "" -"Fields are distinct data values, contained in a tuple. They play the same " -"role as \"row columns\" or \"record fields\" in relational databases, with a" -" few improvements:" -msgstr "" -"Поля — это отдельные значения данных, которые содержатся в кортеже. Они " -"играют ту же роль, что и \"столбцы\" или \"поля записи\" в реляционных базах" -" данных, но несколько усовершенствованы:" - -msgid "fields can be composite structures, such as arrays or maps," -msgstr "" -"поля могут представлять собой композитные структуры, такие как таблицы типа " -"массива или ассоциативного массива," - -msgid "fields don't need to have names." -msgstr "полям не нужны имена." - -msgid "" -"A given tuple may have any number of fields, and the fields may be of " -"different :ref:`types `." -msgstr "" -"В кортеже может быть любое количество полей, и это могут быть поля разных " -":ref:`типов `." - -msgid "" -"The field's number is the identifier of the field. Numbers are counted from " -"base 1 in Lua and other 1-based languages, or from base 0 in languages like " -"PHP or C/C++. So, ``1`` or ``0`` can be used in some contexts to refer to " -"the first field of a tuple." -msgstr "" -"Номер поля служит его идентификатором. В Lua и некоторых других языках " -"нумерация начинается с 1, в других — с 0 (например, в PHP или C/C++). Таким " -"образом, в некоторых контекстах у первого поля кортежа будет индекс ``1`` " -"или ``0``." - -msgid "Spaces" -msgstr "Спейсы" - -msgid "" -"Tarantool stores tuples in containers called spaces. In the example above, " -"there's a space called ``tester``." -msgstr "" -"Tarantool хранит кортежи в контейнерах, называемых спейсами (space). Спейс в" -" примере выше называется ``tester``." - -msgid "space" -msgstr "спейс" - -msgid "" -"In Tarantool, a space is a primary container that stores data. It is " -"analogous to tables in relational databases. Spaces contain :term:`tuples " -"` -- the Tarantool name for database records. The number of tuples " -"in a space is unlimited." -msgstr "" -"В Tarantool спейс — это первичный контейнер, хранящий данные. Он похож на " -"таблицы в реляционных базах данных. Спейсы содержат :term:`кортежи ` " -"— так в Tarantool называются записи в базе данных. Количество кортежей в " -"спейсе не ограничено." - -msgid "" -"At least one space is required to store data with Tarantool. Each space has " -"the following attributes:" -msgstr "" -"Для хранения данных с помощью Tarantool требуется хотя бы один спейс. У " -"каждого спейса есть следующие атрибуты:" - -msgid "a unique **name** specified by the user," -msgstr "уникальное **имя**, указанное пользователем;" - -msgid "" -"a unique **numeric identifier** which can be specified by the user, but " -"usually is assigned automatically by Tarantool," -msgstr "" -"уникальный **числовой идентификатор**, обычно Tarantool назначает его " -"автоматически, но пользователь может его указать сам, если посчитает нужным;" - -msgid "" -"an **engine**: *memtx* (default) --- in-memory engine, fast but limited in " -"size, or *vinyl* --- on-disk engine for huge data sets." -msgstr "" -"**движок**: *memtx* (по умолчанию) — движок «in-memory», быстрый, но " -"ограниченный в размере, или *vinyl* — дисковый движок для огромных наборов " -"данных." - -msgid "" -"To be functional, a space also needs to have a :ref:`primary index `. It can also have secondary indexes." -msgstr "" -"Для работы спейсу нужен :ref:`первичный индекс `. Также он может\n" -"использовать вторичные индексы." - -msgid "Indexes" -msgstr "Индексы" - -msgid "" -"Read the full information about indexes on page :doc:`Indexes " -"`." -msgstr "" -"Всю информацию про индексы можно найти на странице :doc:`Индексы " -"`." - -msgid "An **index** is a group of key values and pointers." -msgstr "**Индекс** — это совокупность значений ключей и указателей." - -msgid "" -"As with spaces, you should specify the index **name** and let Tarantool come" -" up with a unique **numeric identifier** (\"index id\")." -msgstr "" -"Как и для спейсов, для индексов следует указать **имена**, а Tarantool " -"определит уникальный **числовой идентификатор** (\"ID индекса\")." - -msgid "" -"An index always has a **type**. The default index type is :ref:`TREE " -"`. TREE indexes are provided by all Tarantool engines, can " -"index unique and non-unique values, support partial key searches, " -"comparisons, and ordered results. Additionally, the memtx engine supports " -":ref:`HASH `, :ref:`RTREE ` and :ref:`BITSET " -"` indexes." -msgstr "" -"У индекса всегда есть определенный **тип**. Тип индекса по умолчанию — " -":ref:`TREE `. TREE-индексы поддерживаются обоими движками " -"Tarantool, могут индексировать уникальные и неуникальные значения, " -"поддерживают поиск по компонентам ключа, сравнение ключей и упорядочивание " -"результатов. Движок memtx поддерживает и другие типы индексов: :ref:`HASH " -"`, :ref:`RTREE ` и :ref:`BITSET `." - -msgid "" -"An index may be **multi-part**, that is, you can declare that an index key " -"value is composed of two or more fields in the tuple, in any order. For " -"example, for an ordinary TREE index, the maximum number of parts is 255." -msgstr "" -"Индекс может быть **многокомпонентным**, то есть можно объявить, что ключ " -"индекса состоит из двух или более полей в кортеже в любом порядке. Например," -" для обычного TREE-индекса максимальное количество частей равно 255." - -msgid "" -"An index may be **unique**, that is, you can declare that it would be " -"illegal to have the same key value twice." -msgstr "" -"Индекс может быть **уникальным**, то есть можно объявить, что недопустимо " -"дважды задавать одно значение ключа." - -msgid "" -"The first index defined on a space is called the **primary key index**, and " -"it must be unique. All other indexes are called **secondary indexes**, and " -"they may be non-unique." -msgstr "" -"Первый индекс, определенный для спейса, называется **первичный индекс**. Он " -"должен быть уникальным. Все остальные индексы называются **вторичными " -"индексами**, они могут строиться по неуникальным значениям." - -msgid "Data types" -msgstr "Типы данных" - -msgid "" -"Tarantool is both a database manager and an application server. Therefore a " -"developer often deals with two type sets: the types of the programming " -"language (such as Lua) and the types of the Tarantool storage format " -"(MsgPack)." -msgstr "" -"Tarantool представляет собой систему управления базой данных и сервер " -"приложений одновременно. Поэтому разработчику часто приходится работать с " -"двумя системами типов данных: типы языка программирования (например, Lua) и " -"типы формата хранения данных Tarantool (MsgPack)." - -msgid "Lua versus MsgPack" -msgstr "Lua в сравнении с MsgPack" - -msgid "Scalar / compound" -msgstr "Скалярный / составной" - -msgid "MsgPack |nbsp| type" -msgstr "MsgPack-тип |nbsp|" - -msgid "Lua type" -msgstr "Lua-тип" - -msgid "Example value" -msgstr "Пример значения" - -msgid "scalar" -msgstr "скалярный" - -msgid "nil" -msgstr "nil" - -msgid "\"`nil`_\"" -msgstr "\"`nil`_\"" - -msgid "``nil``" -msgstr "``nil``" - -msgid "boolean" -msgstr "boolean" - -msgid "\"`boolean`_\"" -msgstr "\"`boolean`_\" (логическое значение)" - -msgid "``true``" -msgstr "``true``" - -msgid "string" -msgstr "string" - -msgid "\"`string`_\"" -msgstr "\"`string`_\"" - -msgid "``'A B C'``" -msgstr "``'A B C'``" - -msgid "integer" -msgstr "integer" - -msgid "\"`number`_\"" -msgstr "\"`number`_\"" - -msgid "``12345``" -msgstr "``12345``" - -msgid "float 64 (double)" -msgstr "float 64 (double)" - -msgid "``1.2345``" -msgstr "``1.2345``" - -msgid "\"`cdata`_\"" -msgstr "\"`cdata`_\"" - -msgid "binary" -msgstr "binary" - -msgid "``[!!binary 3t7e]``" -msgstr "``[!!binary 3t7e]``" - -msgid "ext (for Tarantool decimal)" -msgstr "ext (для decimal в Tarantool)" - -msgid "``1.2``" -msgstr "``1.2``" - -msgid "ext (for Tarantool uuid)" -msgstr "ext (для uuid в Tarantool)" - -msgid "``12a34b5c-de67-8f90-`` |br| ``123g-h4567ab8901``" -msgstr "``12a34b5c-de67-8f90-`` |br| ``123g-h4567ab8901``" - -msgid "compound" -msgstr "составной" - -msgid "map" -msgstr "map (ассоциативный массив)" - -msgid "\"`table`_\" (with string keys)" -msgstr "\"`table`_\" (таблица со строковыми ключами)" - -msgid "``{'a': 5, 'b': 6}``" -msgstr "``{'a': 5, 'b': 6}``" - -msgid "array" -msgstr "array (массив)" - -msgid "\"`table`_\" (with integer keys)" -msgstr "\"`table`_\" (таблица с целочисленными ключами)" - -msgid "``[1, 2, 3, 4, 5]``" -msgstr "``[1, 2, 3, 4, 5]``" - -msgid "tuple (\"`cdata`_\")" -msgstr "tuple (\"`cdata`_\") (кортеж)" - -msgid "``[12345, 'A B C']``" -msgstr "``[12345, 'A B C']``" - -msgid "" -"MsgPack values have variable lengths. So, for example, the smallest number " -"requires only one byte, but the largest number requires nine bytes." -msgstr "" -"Данные в формате MsgPack имеют переменный размер. Так, например, для " -"наименьшего значения number потребуется только один байт, a для наибольшего " -"потребуется девять байтов." - -msgid "Field type details" -msgstr "Описание типов полей" - -msgid "" -"**nil**. In Lua, the nil type has only one possible value, also called " -"``nil``. Tarantool displays it as ``null`` when using the default :ref:`YAML" -" ` format. Nil may be compared to values of any types " -"with == (is-equal) or ~= (is-not-equal), but other comparison operations " -"will not work. Nil may not be used in Lua tables; the workaround is to use " -":ref:`box.NULL ` because ``nil == box.NULL`` is true. Example: " -"``nil``." -msgstr "" -"**nil**. В языке Lua у типа nil есть только одно значение, также называемое " -"``nil``. Tarantool отображает его как ``null`` при использовании формата по " -"умолчанию :ref:`YAML `. Значение nil можно сравнивать " -"со значениями любых типов данных с помощью операторов == (равно) или ~= (не " -"равно), но никакие другие операции сравнения к nil не применимы. Значение " -"nil также нельзя использовать в Lua-таблицах — в качестве обходного пути " -"вместо nil в таком случае можно указать :ref:`box.NULL `, " -"поскольку условие ``nil == box.NULL`` является истинным. Пример: ``nil``." - -msgid "" -"**boolean**. A boolean is either ``true`` or ``false``. Example: ``true``." -msgstr "" -"**boolean**. Логический тип данных boolean принимает значения ``true`` или " -"``false``. Пример: ``true``." - -msgid "" -"**integer**. The Tarantool integer type is for integers between " -"-9223372036854775808 and 18446744073709551615, which is about 18 " -"quintillion. This type corresponds to the number type in Lua and to the " -"integer type in MsgPack. Example: ``-2^63``." -msgstr "" -"**integer**. В Tarantool тип полей integer используется для целых чисел от " -"−9 223 372 036 854 775 808 до 18 446 744 073 709 551 615, то есть до " -"примерно 18 квинтиллионов. Такой тип данных соответствует типам number в Lua" -" и integer в MsgPack. Пример: ``-2^63``." - -msgid "" -"**unsigned**. The Tarantool unsigned type is for integers between 0 and " -"18446744073709551615. So it is a subset of integer. Example: ``123456``." -msgstr "" -"**unsigned**. Тип unsigned в Tarantool используется для целых чисел от 0 до " -"18 446 744 073 709 551 615. Он представляет собой подмножество типа integer." -" Пример: ``123456``." - -msgid "" -"**double**. The double field type exists mainly to be equivalent to " -"Tarantool/SQL's :ref:`DOUBLE data type `. In " -"`msgpuck.h `_ (Tarantool's interface to " -"MsgPack), the storage type is ``MP_DOUBLE`` and the size of the encoded " -"value is always 9 bytes. In Lua, fields of the double type can only contain " -"non-integer numeric values and cdata values with double floating-point " -"numbers. Examples: ``1.234``, ``-44``, ``1.447e+44``." -msgstr "" -"**double**. Поле типа double существует главным образом для соответствия " -"типу :ref:`DOUBLE data type ` в Tarantool/SQL . В " -"`msgpuck.h `_ (интерфейс Tarantool к " -"MsgPack) тип в хранилище — ``MP_DOUBLE``, а размер закодированного значения " -"всегда составляет 9 байтов. В Lua поля типа double могут содержать только не" -" целые числовые значения и значения cdata с числами с плавающей точкой " -"двойной точности (double). Примеры: ``1.234``, ``-44``, ``1.447e+44``." - -msgid "" -"To avoid using the wrong kind of values inadvertently, use ``ffi.cast()`` " -"when searching or changing ``double`` fields. For example, instead of " -":samp:`{space_object}:insert`:code:`{`:samp:`{value}`:code:`}` use ``ffi = " -"require('ffi') ...`` " -":samp:`{space_object}:insert`:code:`({ffi.cast('double',`:samp:`{value}`:code:`)})`." -" Example:" -msgstr "" -"Чтобы избежать случайного использования неправильного типа значений, " -"используйте явное преобразование типа ``ffi.cast()``, когда вы ищете или " -"изменяете поля типа ``double``. Например, вместо " -":samp:`{space_object}:insert`:code:`{`:samp:`{value}`:code:`}` используйте " -"``ffi = require('ffi') ...`` " -":samp:`{space_object}:insert`:code:`({ffi.cast('double',`:samp:`{value}`:code:`)})`." -" Пример:" - -msgid "" -"s = box.schema.space.create('s', {format = {{'d', 'double'}}})\n" -"s:create_index('ii')\n" -"s:insert({1.1})\n" -"ffi = require('ffi')\n" -"s:insert({ffi.cast('double', 1)})\n" -"s:insert({ffi.cast('double', tonumber('123'))})\n" -"s:select(1.1)\n" -"s:select({ffi.cast('double', 1)})" -msgstr "" -"s = box.schema.space.create('s', {format = {{'d', 'double'}}})\n" -"s:create_index('ii')\n" -"s:insert({1.1})\n" -"ffi = require('ffi')\n" -"s:insert({ffi.cast('double', 1)})\n" -"s:insert({ffi.cast('double', tonumber('123'))})\n" -"s:select(1.1)\n" -"s:select({ffi.cast('double', 1)})" - -msgid "" -"Arithmetic with cdata ``double`` will not work reliably, so for Lua, it is " -"better to use the ``number`` type. This warning does not apply for " -"Tarantool/SQL because Tarantool/SQL does :ref:`implicit casting " -"`." -msgstr "" -"Арифметические операции с cdata формата ``double`` работают ненадёжно, " -"поэтому для Lua лучше использовать тип ``number``. Это не относится к " -"Tarantool/SQL, так как Tarantool/SQL применяет :ref:`неявное приведение " -"типов `." - -msgid "" -"**number**. The Tarantool number field may have both integer and floating-" -"point values, although in Lua a ``number`` is a double-precision floating-" -"point." -msgstr "" -"**number**. Поле number в Tarantool может содержать значения как целые, так " -"и с плавающей точкой, хотя в Lua тип ``number`` означает число с плавающей " -"точкой двойной точности." - -msgid "" -"Tarantool will try to store a Lua number as floating-point if the value " -"contains a decimal point or is very large (greater than 100 trillion = " -"1e14), otherwise Tarantool will store it as an integer. To ensure that even " -"very large numbers are stored as integers, use the :ref:`tonumber64 ` function, or the LL (Long Long) suffix, or the ULL (Unsigned " -"Long Long) suffix. Here are examples of numbers using regular notation, " -"exponential notation, the ULL suffix and the ``tonumber64`` function: " -"``-55``, ``-2.7e+20``, ``100000000000000ULL``, " -"``tonumber64('18446744073709551615')``." -msgstr "" -"Tarantool по возможности сохраняет числа языка Lua в виде чисел с плавающей " -"запятой, если числовое значение содержит десятичную запятую или если оно " -"очень велико (более 100 триллионов = 1e14). В противном случае Tarantool " -"сохраняет такое значение в виде целого числа. Чтобы даже очень большие " -"величины гарантированно сохранялись как целые числа, используйте функцию " -":ref:`tonumber64 ` или приписывайте в конце суффикс LL " -"(Long Long) или ULL (Unsigned Long Long). Вот примеры записи чисел в обычном" -" представлении, экспоненциальном, с суффиксом ULL и с использованием функции" -" ``tonumber64``: ``−55``, ``−2.7e+20``, ``100000000000000ULL``, " -"``tonumber64('18446744073709551615')``." - -msgid "" -"**decimal**. The Tarantool decimal type is stored as a MsgPack ext " -"(Extension). Values with the decimal type are not floating-point values " -"although they may contain decimal points. They are exact with up to 38 " -"digits of precision. Example: a value returned by a function in the " -":ref:`decimal ` module." -msgstr "" -"**decimal**. Тип данных decimal в Tarantool хранится в формате MsgPack ext " -"(Extension). Значения с типом decimal не являются числами с плавающей " -"запятой, хотя могут содержать десятичную запятую. Они представляют собой " -"числа с точностью до 38 знаков. Пример: значение, которое возвращает функция" -" в модуле :ref:`decimal `." - -msgid "" -"**string**. A string is a variable-length sequence of bytes, usually " -"represented with alphanumeric characters inside single quotes. In both Lua " -"and MsgPack, strings are treated as binary data, with no attempts to " -"determine a string's character set or to perform any string conversion -- " -"unless there is an optional :ref:`collation `. So, usually," -" string sorting and comparison are done byte-by-byte, without any special " -"collation rules applied. For example, numbers are ordered by their point on " -"the number line, so 2345 is greater than 500; meanwhile, strings are ordered" -" by the encoding of the first byte, then the encoding of the second byte, " -"and so on, so ``'2345'`` is less than ``'500'``. Example: ``'A, B, C'``." -msgstr "" -"**string**. Строка (string) представляет собой последовательность байтов " -"переменной длины. Обычно она записывается буквенно-цифровыми символами в " -"одинарных кавычках. Как Lua, так и MsgPack рассматривают строки как двоичные" -" данные, не пытаясь определить кодировку строки или как-то её преобразовать," -" кроме случаев, когда указаны необязательные :ref:`правила сравнения " -"символов `. Таким образом, обычно сортировка и сравнение " -"строк выполняются побайтово, а дополнительные правила сравнения символов не " -"применяются. Например, числа упорядочены по их положению на числовой прямой," -" поэтому 2345 больше, чем 500. Строки же упорядочены сначала по кодировке " -"первого байта, затем по кодировке второго байта и так далее, так что " -"``'2345'`` меньше ``'500'``. Пример: ``'A, B, C'``." - -msgid "" -"**bin**. A bin (binary) value is not directly supported by Lua but there is " -"a Tarantool type ``varbinary`` which is encoded as MsgPack binary. For an " -"(advanced) example showing how to insert varbinary into a database, see the " -"Cookbook Recipe for :ref:`ffi_varbinary_insert `. Example: ``\"\\65 \\66 \\67\"``." -msgstr "" -"**bin**. Значения типа bin (двоичные значения) не поддерживаются " -"непосредственно в Lua, но в Tarantool есть тип ``varbinary``, который " -"кодируется в тип binary из MsgPack. Пример вставки varbinary в базу данных " -"см. в рекомендациях по разработке :ref:`ffi_varbinary_insert ` (продвинутого уровня). Пример: ``\"\\65 \\66 " -"\\67\"``." - -msgid "" -"**uuid**. The Tarantool uuid type is used for :ref:`Universally Unique " -"Identifiers `. Since version :doc:`2.4.1 ` " -"Tarantool stores ``uuid`` values as a :ref:`MsgPack ext ` (Extension)." -msgstr "" -"**uuid**. Тип uuid в Tarantool используется для :ref:`универсальных " -"уникальных идентификаторов (UUID) `. Начиная с версии " -":doc:`2.4.1 `, Tarantool хранит значения ``uuid`` в формате " -":ref:`MsgPack ext ` (Extension)." - -msgid "Example: ``64d22e4d-ac92-4a23-899a-e5934af5479``." -msgstr "Пример: ``64d22e4d-ac92-4a23-899a-e5934af5479``." - -msgid "" -"**array**. An array is represented in Lua with ``{...}`` (`braces " -"`_). Examples: lists of numbers " -"representing points in geometric figures: ``{10, 11}``, ``{3, 5, 9, 10}``." -msgstr "" -"**array**. В Lua массив (array) обозначается ``{...}`` (`фигурными скобками " -"`_). Примеры: списки чисел, которые " -"обозначают точки геометрической фигуры: ``{10, 11}``, ``{3, 5, 9, 10}``." - -msgid "" -"**table**. Lua tables with string keys are stored as MsgPack maps; Lua " -"tables with integer keys starting with 1 are stored as MsgPack arrays. Nils " -"may not be used in Lua tables; the workaround is to use :ref:`box.NULL `. Example: a ``box.space.tester:select()`` request will return a Lua " -"table." -msgstr "" -"**table**. Lua-таблицы со строковыми ключами хранятся в виде ассоциативных " -"массивов MsgPack map. Lua-таблицы с целочисленными ключами, начиная с 1, " -"хранятся в виде массивов MsgPack array. В Lua-таблицах нельзя использовать " -"nil; вместо этого можно использовать :ref:`box.NULL `. Пример: " -"запрос ``box.space.tester:select()`` вернет Lua-таблицу." - -msgid "" -"**tuple**. A tuple is a light reference to a MsgPack array stored in the " -"database. It is a special type (cdata) to avoid conversion to a Lua table on" -" retrieval. A few functions may return tables with multiple tuples. For " -"tuple examples, see :ref:`box.tuple `." -msgstr "" -"**tuple**. Кортеж (tuple) представляет собой легкую ссылку на массив типа " -"MsgPack array, который хранится в базе данных. Это особый тип (cdata), " -"который создан во избежание конвертации в Lua-таблицу при выборке данных. " -"Некоторые функции могут возвращать таблицы с множеством кортежей. Примеры с " -"кортежами см. в разделе :ref:`box.tuple `." - -msgid "" -"**scalar**. Values in a scalar field can be boolean, integer, unsigned, " -"double, number, decimal, string, uuid, or varbinary; but not array, map, or " -"tuple. Examples: ``true``, ``1``, ``'xxx'``." -msgstr "" -"**scalar**. Значения в поле типа scalar могут быть следующих типов: boolean," -" integer, unsigned, double, number, decimal, string, uuid, varbinary. Они не" -" могут иметь тип array, map или tuple. Примеры: ``true``, ``1``, ``'xxx'``." - -msgid "" -"**any**. Values in a field of this type can be boolean, integer, unsigned, " -"double, number, decimal, string, uuid, varbinary, array, map, or tuple. " -"Examples: ``true``, ``1``, ``'xxx'``, ``{box.NULL, 0}``." -msgstr "" -"**any**. Значения в поле типа any могут быть следующих типов: boolean, " -"integer, unsigned, double, number, decimal, string, uuid, varbinary, array, " -"map, tuple. Примеры: ``true``, ``1``, ``'xxx'``, ``{box.NULL, 0}``." - -msgid "Examples of insert requests with different field types:" -msgstr "Примеры запросов вставки с разными типами полей:" - -msgid "" -"tarantool> box.space.K:insert{1,nil,true,'A B C',12345,1.2345}\n" -"---\n" -"- [1, null, true, 'A B C', 12345, 1.2345]\n" -"...\n" -"tarantool> box.space.K:insert{2,{['a']=5,['b']=6}}\n" -"---\n" -"- [2, {'a': 5, 'b': 6}]\n" -"...\n" -"tarantool> box.space.K:insert{3,{1,2,3,4,5}}\n" -"---\n" -"- [3, [1, 2, 3, 4, 5]]\n" -"..." -msgstr "" -"tarantool> box.space.K:insert{1,nil,true,'A B C',12345,1.2345}\n" -"---\n" -"- [1, null, true, 'A B C', 12345, 1.2345]\n" -"...\n" -"tarantool> box.space.K:insert{2,{['a']=5,['b']=6}}\n" -"---\n" -"- [2, {'a': 5, 'b': 6}]\n" -"...\n" -"tarantool> box.space.K:insert{3,{1,2,3,4,5}}\n" -"---\n" -"- [3, [1, 2, 3, 4, 5]]\n" -"..." - -msgid "Indexed field types" -msgstr "Типы индексированных полей" - -msgid "" -"Indexes restrict values that Tarantool can store with MsgPack. This is why, " -"for example, ``'unsigned'`` and ``'integer'`` are different field types, " -"although in MsgPack they are both stored as integer values. An " -"``'unsigned'`` index contains only *non-negative* integer values, while an " -"``‘integer’`` index contains *any* integer values." -msgstr "" -"Индексы ограничивают значения, которые Tarantool может хранить в формате " -"MsgPack. Вот почему, например, есть отдельные типы полей ``'unsigned'`` " -"(число без знака) и ``'integer'`` (целое число), хотя в MsgPack они оба " -"хранятся как целочисленные значения. Индекс типа ``'unsigned'`` содержит " -"только *неотрицательные* целочисленные значения, а индекс типа ``'integer'``" -" содержит *любые* целочисленные значения." - -msgid "" -"Here again are the field types described in :ref:`Field Type Details " -"`, and the index types they can fit in. The " -"default field type is ``'unsigned'`` and the default index type is TREE. " -"Although ``'nil'`` is not a legal indexed field type, indexes may contain " -"`nil` :ref:`as a non-default option `. Full " -"information is in section :ref:`Details about index field types " -"`." -msgstr "" -"Здесь снова приводятся типы полей, описанные в :ref:`Описании типов полей " -"`, а также типы индексов, где их можно " -"использовать. По умолчанию, тип поля — ``'unsigned'``, тип индекса — TREE. " -"Хотя в качестве типа индексированого поля ``'nil'`` использовать нельзя, " -"индексы могут содержать `nil` как :ref:`опцию, которая не используется по " -"умолчанию `. Более подробную информацию см. в разделе" -" :ref:`Описание типов индексированных полей " -"`." - -msgid "Field type name string" -msgstr "Имя типа поля" - -msgid "Field type |br|" -msgstr "Тип поля |br|" - -msgid "Index type" -msgstr "Тип индекса" - -msgid "``'boolean'``" -msgstr "``'boolean'``" - -msgid ":ref:`boolean `" -msgstr ":ref:`boolean `" - -msgid ":ref:`TREE or HASH `" -msgstr ":ref:`TREE или HASH `" - -msgid "``'integer'`` (may also be called ``‘int’``)" -msgstr "``'integer'`` (также может называться ``‘int’``)" - -msgid ":ref:`integer `, which may include unsigned values" -msgstr "" -":ref:`integer `, может включать в себя значения unsigned " -"(без знака)" - -msgid "TREE or HASH" -msgstr "TREE или HASH" - -msgid "" -"``'unsigned'`` (may also be called ``'uint'`` or ``'num'``, but ``'num'`` is" -" deprecated)" -msgstr "" -"``'unsigned'`` (без знака, также может называться ``'uint'`` или ``'num'``, " -"но ``'num'`` объявлен устаревшим)" - -msgid ":ref:`unsigned `" -msgstr ":ref:`unsigned `" - -msgid "TREE, BITSET, or HASH" -msgstr "TREE, BITSET или HASH" - -msgid "``'double'``" -msgstr "``'double'``" - -msgid ":ref:`double `" -msgstr ":ref:`double `" - -msgid "``'number'``" -msgstr "``'number'``" - -msgid "" -":ref:`number `, which may include :ref:`integer `, :ref:`double `, or :ref:`decimal ` values" -msgstr "" -":ref:`number `, может включать в себя значения типа " -":ref:`integer `, :ref:`double ` или :ref:`decimal `" - -msgid "``'decimal'``" -msgstr "``'decimal'``" - -msgid ":ref:`decimal `" -msgstr ":ref:`decimal `" - -msgid "``'string'`` (may also be called ``'str'``)" -msgstr "``'string'`` (строка, также может называться ``'str'``)" - -msgid ":ref:`string `" -msgstr ":ref:`string `" - -msgid "``'varbinary'``" -msgstr "``'varbinary'``" - -msgid ":ref:`varbinary `" -msgstr ":ref:`varbinary `" - -msgid "TREE, HASH, or BITSET (since version 2.7)" -msgstr "TREE, HASH или BITSET (с версии 2.7)" - -msgid "``'uuid'``" -msgstr "``'uuid'``" - -msgid ":ref:`uuid `" -msgstr ":ref:`uuid `" - -msgid "``'array'``" -msgstr "``'array'``" - -msgid ":ref:`array `" -msgstr ":ref:`array `" - -msgid ":ref:`RTREE `" -msgstr ":ref:`RTREE `" - -msgid "``'scalar'``" -msgstr "``'scalar'``" - -msgid "" -"may include :ref:`nil `, :ref:`boolean `, " -":ref:`integer `, :ref:`unsigned `, " -":ref:`number `, :ref:`decimal `, " -":ref:`string `, :ref:`varbinary `, or " -":ref:`uuid ` values" -msgstr "" -"может содержать значения :ref:`nil `, :ref:`boolean `, :ref:`integer `, :ref:`unsigned `, :ref:`number `, :ref:`decimal `, :ref:`string ` или :ref:`varbinary `" - -msgid "" -"When a scalar field contains values of different underlying types, the key " -"order is: nils, then booleans, then numbers, then strings, then varbinaries," -" then uuids." -msgstr "" -"Когда поле типа scalar содержит значения различных базовых типов, то порядок" -" ключей следующий: nil, затем boolean, затем number, затем string, затем " -"varbinary, затем uuid." - -msgid "Collations" -msgstr "Сортировка" - -msgid "" -"By default, when Tarantool compares strings, it uses the so-called **binary " -"collation**. It only considers the numeric value of each byte in a string. " -"For example, the encoding of ``'A'`` (what used to be called the \"ASCII " -"value\") is 65, the encoding of ``'B'`` is 66, and the encoding of ``'a'`` " -"is 98. Therefore, if the string is encoded with ASCII or UTF-8, then ``'A' <" -" 'B' < 'a'``." -msgstr "" -"Когда Tarantool сравнивает строки, по умолчанию он использует **двоичные " -"параметры сортировки** (**binary collation**). При этом он учитывает только " -"числовое значение каждого байта в строке. Например, код символа ``'A'`` " -"(раньше называлась \"значение ASCII\") — число 65, код ``'B'`` — число 66, а" -" код ``'a'`` -- число 98. Поэтому ``'A' < 'B' < 'a'``, если строка " -"закодирована в ASCII или UTF-8." - -msgid "" -"Binary collation is the best choice for fast deterministic simple " -"maintenance and searching with Tarantool indexes." -msgstr "" -"Двоичная сортировка — лучший выбор для быстрого детерминированного простого " -"обслуживания и поиска с использованием индексов Tarantool." - -msgid "" -"But if you want the ordering that you see in phone books and dictionaries, " -"then you need Tarantool's optional collations, such as ``unicode`` and " -"``unicode_ci``, which allow for ``'a' < 'A' < 'B'`` and ``'a' == 'A' < 'B'``" -" respectively." -msgstr "" -"Но если вы хотите такое упорядочение, как в телефонных справочниках и " -"словарях, то вам нужна одна из дополнительных сортировок Tarantool: " -"``unicode`` или ``unicode_ci``. Они обеспечивают ``'a' < 'A' < 'B'`` и ``'a'" -" == 'A' < 'B'`` соответственно." - -msgid "" -"**The unicode and unicode_ci optional collations** use the ordering " -"according to the `Default Unicode Collation Element Table (DUCET) " -"`_" -" and the rules described in `Unicode® Technical Standard #10 Unicode " -"Collation Algorithm (UTS #10 UCA) `_. The " -"only difference between the two collations is about `weights " -"`_:" -msgstr "" -"Дополнительные виды сортировки **unicode и unicode_ci** обеспечивают " -"упорядочение в соответствии с `Таблицей сортировки символов Юникода по " -"умолчанию (DUCET) " -"`_" -" и правилами, указанными в `Техническом стандарте Юникода №10 -- Алгоритм " -"сортировки по Юникоду (Unicode® Technical Standard #10 Unicode Collation " -"Algorithm (UTS #10 UCA)) `_. Единственное " -"отличие между двумя видами сортировки — `вес " -"`_:" - -msgid "" -"``unicode`` collation observes L1, L2, and L3 weights (strength = " -"'tertiary');" -msgstr "" -"сортировка ``unicode`` принимает во внимание уровни веса L1, L2 и L3 " -"(уровень = 'tertiary', третичный);" - -msgid "" -"``unicode_ci`` collation observes only L1 weights (strength = 'primary'), so" -" for example ``'a' == 'A' == 'á' == 'Á'``." -msgstr "" -"сортировка ``unicode_ci`` принимает во внимание только вес L1 (уровень = " -"'primary', первичный), поэтому, например, ``'a' == 'A' == 'á' == 'Á'``." - -msgid "As an example, take some Russian words:" -msgstr "Для примера возьмем некоторые русские слова:" - -msgid "" -"'ЕЛЕ'\n" -"'елейный'\n" -"'ёлка'\n" -"'еловый'\n" -"'елозить'\n" -"'Ёлочка'\n" -"'ёлочный'\n" -"'ЕЛь'\n" -"'ель'" -msgstr "" -"'ЕЛЕ'\n" -"'елейный'\n" -"'ёлка'\n" -"'еловый'\n" -"'елозить'\n" -"'Ёлочка'\n" -"'ёлочный'\n" -"'ЕЛь'\n" -"'ель'" - -msgid "...and show the difference in ordering and selecting by index:" -msgstr "...и покажем разницу в упорядочении и выборке по индексу:" - -msgid "with ``unicode`` collation:" -msgstr "с сортировкой по ``unicode``:" - -msgid "" -"tarantool> box.space.T:create_index('I', {parts = {{field = 1, type = 'str', collation='unicode'}}})\n" -"...\n" -"tarantool> box.space.T.index.I:select()\n" -"---\n" -"- - ['ЕЛЕ']\n" -" - ['елейный']\n" -" - ['ёлка']\n" -" - ['еловый']\n" -" - ['елозить']\n" -" - ['Ёлочка']\n" -" - ['ёлочный']\n" -" - ['ель']\n" -" - ['ЕЛь']\n" -"...\n" -"tarantool> box.space.T.index.I:select{'ЁлКа'}\n" -"---\n" -"- []\n" -"..." -msgstr "" -"tarantool> box.space.T:create_index('I', {parts = {{field = 1, type = 'str', collation='unicode'}}})\n" -"...\n" -"tarantool> box.space.T.index.I:select()\n" -"---\n" -"- - ['ЕЛЕ']\n" -" - ['елейный']\n" -" - ['ёлка']\n" -" - ['еловый']\n" -" - ['елозить']\n" -" - ['Ёлочка']\n" -" - ['ёлочный']\n" -" - ['ель']\n" -" - ['ЕЛь']\n" -"...\n" -"tarantool> box.space.T.index.I:select{'ЁлКа'}\n" -"---\n" -"- []\n" -"..." - -msgid "with ``unicode_ci`` collation:" -msgstr "с сортировкой по ``unicode_ci``:" - -msgid "" -"tarantool> box.space.T:create_index('I', {parts = {{field = 1, type ='str', collation='unicode_ci'}}})\n" -"...\n" -"tarantool> box.space.T.index.I:select()\n" -"---\n" -"- - ['ЕЛЕ']\n" -" - ['елейный']\n" -" - ['ёлка']\n" -" - ['еловый']\n" -" - ['елозить']\n" -" - ['Ёлочка']\n" -" - ['ёлочный']\n" -" - ['ЕЛь']\n" -"...\n" -"tarantool> box.space.T.index.I:select{'ЁлКа'}\n" -"---\n" -"- - ['ёлка']\n" -"..." -msgstr "" -"tarantool> box.space.T:create_index('I', {parts = {{field = 1, type ='str', collation='unicode_ci'}}})\n" -"...\n" -"tarantool> box.space.T.index.I:select()\n" -"---\n" -"- - ['ЕЛЕ']\n" -" - ['елейный']\n" -" - ['ёлка']\n" -" - ['еловый']\n" -" - ['елозить']\n" -" - ['Ёлочка']\n" -" - ['ёлочный']\n" -" - ['ЕЛь']\n" -"...\n" -"tarantool> box.space.T.index.I:select{'ЁлКа'}\n" -"---\n" -"- - ['ёлка']\n" -"..." - -msgid "" -"In all, collation involves much more than these simple examples of upper " -"case / lower case and accented / unaccented equivalence in alphabets. We " -"also consider variations of the same character, non-alphabetic writing " -"systems, and special rules that apply for combinations of characters." -msgstr "" -"Сортировка включает в себя ещё множество аспектов, кроме показанного в этом " -"примере сопоставления букв верхнего и нижнего регистра, с диакритическими " -"знаками и без них, и с учётом алфавита. Учитываются также вариации одного и " -"того же символа, системы неалфавитного письма и применяются специальные " -"правила для комбинаций символов." - -msgid "" -"For English, Russian, and most other languages and use cases, use the " -"\"unicode\" and \"unicode_ci\" collations. If you need Cyrillic letters 'Е' " -"and 'Ё' to have the same level-1 weights, try the Kyrgyz collation." -msgstr "" -"Для английского, русского и большинства других языков используйте " -"\"unicode\" и \"unicode_ci\". Если вам нужно, чтобы у кириллических букв 'Е'" -" и 'Ё' веса 1 уровня были одинаковыми, попробуйте киргизскую сортировку." - -msgid "" -"**The tailored optional collations**: for other languages, Tarantool " -"supplies tailored collations for every modern language that has more than a " -"million native speakers, and for specialized situations such as the " -"difference between dictionary order and telephone book order. Run " -"``box.space._collation:select()`` to see the complete list." -msgstr "" -"**Специализированные дополнительные виды сортировки**: Для других языков " -"Tarantool предлагает специализированные виды сортировки для любого " -"современного языка, на котором говорят более миллиона человек. Кроме того, " -"специализированные дополнительные виды сортировки возможны для особых " -"случаев, когда слова в словаре упорядочиваются не так, как в телефонном " -"справочнике. Чтобы увидеть полный список, выполните команду " -"``box.space._collation:select()``." - -msgid "" -"The tailored collation names have the form ``unicode_[language " -"code]_[strength]``, where language code is a standard 2-character or " -"3-character language abbreviation, and strength is ``s1`` for \"primary " -"strength\" (level-1 weights), ``s2`` for \"secondary\", ``s3`` for " -"\"tertiary\". Tarantool uses the same language codes as the ones in the " -"\"list of tailorable locales\" on man pages of `Ubuntu " -"`_" -" and `Fedora " -"`_." -" Charts explaining the precise differences from DUCET order are in the " -"`Common Language Data Repository " -"`_." -msgstr "" -"Названия специализированных видов сортировки имеют вид ``unicode_[language " -"code]_[strength]``], где language code — это стандартный код языка из 2 или " -"3 символов, а значение strength может быть ``s1`` для уровня \"primary\" " -"(вес уровня 1), ``s2`` для уровня \"secondary\", ``s3`` для уровня " -"\"tertiary\". Tarantool использует те же коды языков, что указаны в списке " -"специализированных вариантов языковых настроек на страницах руководств по " -"`Ubuntu " -"`_" -" и `Fedora " -"`_." -" Схемы, в деталях объясняющие отличия от упорядочения по DUCET, можно найти " -"в `Общем репозитории языковых данных (Common Language Data Repository) " -"`_." - -msgid "Sequences" -msgstr "Последовательности" - -msgid "A **sequence** is a generator of ordered integer values." -msgstr "" -"**Последовательность** -- это генератор упорядоченных значений целых чисел." - -msgid "" -"As with spaces and indexes, you should specify the sequence **name** and let" -" Tarantool generate a unique numeric identifier (sequence ID)." -msgstr "" -"Как и для спейсов и индексов, для последовательности вы должны указать " -"**имя**, а Tarantool создаст уникальный для неё числовой идентификатор (\"ID" -" последовательности)." - -msgid "" -"As well, you can specify several options when creating a new sequence. The " -"options determine what value will be generated whenever the sequence is " -"used." -msgstr "" -"Кроме того, можно указать несколько параметров при создании новой " -"последовательности. Параметры определяют, какое значение будет " -"генерироваться при использовании последовательности." - -msgid "Options for box.schema.sequence.create()" -msgstr "Параметры для box.schema.sequence.create()" - -msgid "Option name" -msgstr "Имя параметра" - -msgid "Type and meaning" -msgstr "Тип и значение" - -msgid "Default" -msgstr "Значение по умолчанию" - -msgid "Examples" -msgstr "Примеры" - -msgid "**start**" -msgstr "**start**" - -msgid "Integer. The value to generate the first time a sequence is used" -msgstr "" -"Integer. Значение генерируется, когда последовательность используется " -"впервые" - -msgid "1" -msgstr "1" - -msgid "start=0" -msgstr "start=0" - -msgid "**min**" -msgstr "**min**" - -msgid "Integer. Values smaller than this cannot be generated" -msgstr "Integer. Значения, ниже указанного, генерироваться не могут" - -msgid "min=-1000" -msgstr "min=-1000" - -msgid "**max**" -msgstr "**max**" - -msgid "Integer. Values larger than this cannot be generated" -msgstr "Integer. Значения, выше указанного, генерироваться не могут" - -msgid "9223372036854775807" -msgstr "9223372036854775807" - -msgid "max=0" -msgstr "max=0" - -msgid "**cycle**" -msgstr "**cycle**" - -msgid "Boolean. Whether to start again when values cannot be generated" -msgstr "" -"Логическое значение. Если значения не могут быть сгенерированы, начинать ли " -"заново" - -msgid "false" -msgstr "false" - -msgid "cycle=true" -msgstr "cycle=true" - -msgid "**cache**" -msgstr "**cache**" - -msgid "Integer. The number of values to store in a cache" -msgstr "Integer. Количество значений, которые будут храниться в кэше" - -msgid "0" -msgstr "0" - -msgid "cache=0" -msgstr "cache=0" - -msgid "**step**" -msgstr "**step**" - -msgid "" -"Integer. What to add to the previous generated value, when generating a new " -"value" -msgstr "" -"Integer. Что добавить к предыдущему сгенерированному значению, когда " -"генерируется новое значение" - -msgid "step=-1" -msgstr "step=-1" - -msgid "**if_not_exists**" -msgstr "**if_not_exists** (если отсутствует)" - -msgid "" -"Boolean. If this is true and a sequence with this name exists already, " -"ignore other options and use the existing values" -msgstr "" -"Логическое значение. Если выставлено в true (истина) и существует " -"последовательность с таким именем, то игнорировать другие опции и " -"использовать текущие значения" - -msgid "if_not_exists=true" -msgstr "if_not_exists=true" - -msgid "" -"Once a sequence exists, it can be altered, dropped, reset, forced to " -"generate the next value, or associated with an index." -msgstr "" -"Существующую последовательность можно изменять, удалять, сбрасывать, " -"заставить сгенерировать новое значение или ассоциировать с индексом." - -msgid "For an initial example, we generate a sequence named 'S'." -msgstr "" -"Для первоначального примера сгенерируем последовательность под названием " -"'S'." - -msgid "" -"tarantool> box.schema.sequence.create('S',{min=5, start=5})\n" -"---\n" -"- step: 1\n" -" id: 5\n" -" min: 5\n" -" cache: 0\n" -" uid: 1\n" -" max: 9223372036854775807\n" -" cycle: false\n" -" name: S\n" -" start: 5\n" -"..." -msgstr "" -"tarantool> box.schema.sequence.create('S',{min=5, start=5})\n" -"---\n" -"- step: 1\n" -" id: 5\n" -" min: 5\n" -" cache: 0\n" -" uid: 1\n" -" max: 9223372036854775807\n" -" cycle: false\n" -" name: S\n" -" start: 5\n" -"..." - -msgid "" -"The result shows that the new sequence has all default values, except for " -"the two that were specified, ``min`` and ``start``." -msgstr "" -"В результате видим, что в новой последовательность есть все значения по " -"умолчанию, за исключением указанных ``min`` и ``start``." - -msgid "Then we get the next value, with the ``next()`` function." -msgstr "Затем получаем следующее значение с помощью функции ``next()``." - -msgid "" -"tarantool> box.sequence.S:next()\n" -"---\n" -"- 5\n" -"..." -msgstr "" -"tarantool> box.sequence.S:next()\n" -"---\n" -"- 5\n" -"..." - -msgid "" -"The result is the same as the start value. If we called ``next()`` again, we" -" would get 6 (because the previous value plus the step value is 6), and so " -"on." -msgstr "" -"Результат точно такой же, как и начальное значение. Если мы снова вызовем " -"``next()``, то получим 6 (потому что предыдущее значение плюс значение шага " -"составит 6) и так далее." - -msgid "" -"Then we create a new table and specify that its primary key should be " -"generated from the sequence." -msgstr "" -"Затем мы создаём новую таблицу и определяем, что ее первичный ключ должен " -"быть получен из последовательности." - -msgid "" -"tarantool> s=box.schema.space.create('T')\n" -"---\n" -"...\n" -"tarantool> s:create_index('I',{sequence='S'})\n" -"---\n" -"- parts:\n" -" - type: unsigned\n" -" is_nullable: false\n" -" fieldno: 1\n" -" sequence_id: 1\n" -" id: 0\n" -" space_id: 520\n" -" unique: true\n" -" type: TREE\n" -" sequence_fieldno: 1\n" -" name: I\n" -"...\n" -"---\n" -"..." -msgstr "" -"tarantool> s=box.schema.space.create('T')\n" -"---\n" -"...\n" -"tarantool> s:create_index('I',{sequence='S'})\n" -"---\n" -"- parts:\n" -" - type: unsigned\n" -" is_nullable: false\n" -" fieldno: 1\n" -" sequence_id: 1\n" -" id: 0\n" -" space_id: 520\n" -" unique: true\n" -" type: TREE\n" -" sequence_fieldno: 1\n" -" name: I\n" -"...\n" -"---\n" -"..." - -msgid "Then we insert a tuple without specifying a value for the primary key." -msgstr "Затем вставляем кортеж, не указывая значение первичного ключа." - -msgid "" -"tarantool> box.space.T:insert{nil,'other stuff'}\n" -"---\n" -"- [6, 'other stuff']\n" -"..." -msgstr "" -"tarantool> box.space.T:insert{nil,'other stuff'}\n" -"---\n" -"- [6, 'other stuff']\n" -"..." - -msgid "" -"The result is a new tuple where the first field has a value of 6. This " -"arrangement, where the system automatically generates the values for a " -"primary key, is sometimes called \"auto-incrementing\" or \"identity\"." -msgstr "" -"В результате имеем новый кортеж со значением 6 в первом поле. Такой способ " -"организации данных, когда система автоматически генерирует значения для " -"первичного ключа, иногда называется \"автоинкрементным\" (т.е. с " -"автоматическим увеличением) или \"по идентификатору\"." - -msgid "" -"For syntax and implementation details, see the reference for " -":doc:`box.schema.sequence `." -msgstr "" -"Для получения подробной информации о синтаксисе и методах реализации см. " -"справочник по :doc:`box.schema.sequence " -"`." - -msgid "Persistence" -msgstr "Персистентность" - -msgid "" -"To ensure data persistence, Tarantool records updates to the database in the" -" so-called :ref:`write-ahead log (WAL) ` files. When a power " -"outage occurs or the Tarantool instance is killed incidentally, the in-" -"memory database is lost. In such case, Tarantool restores the data from WAL " -"files by reading them and redoing the requests. This is called the " -"\"recovery process\". You can change the timing of the WAL writer or turn it" -" off by setting the :ref:`wal_mode `." -msgstr "" -"Чтобы обеспечить персистентность данных, Tarantool записывает обновления " -"базы данных в так называемые :ref:`файлы журнала упреждающей записи (write-" -"ahead log, WAL) `. При отключении электроэнергии или " -"случайном завершении работы экземпляра Tarantool данные в оперативной памяти" -" теряются. В таком случае Tarantool восстанавливает данные из WAL-файлов, " -"повторно выполняя запросы, записанные в них. Это называется \"процесс " -"восстановления\". Можно настроить, как часто данные записываются в WAL-" -"файлы, или отключить запись совсем с помощью :ref:`wal_mode " -"`." - -msgid "" -"Tarantool also maintains a set of :ref:`snapshot files `. These files contain an on-disk copy of the entire data set for a" -" given moment. Instead of reading every WAL file since the databases were " -"created, the recovery process can load the latest snapshot file and then " -"read the WAL files, produced after the snapshot file was made. After " -"creating a new snapshot, the earlier WAL files can be removed to free up " -"space." -msgstr "" -"Tarantool также сохраняет набор файлов со статическими снимками данных " -"(:ref:`snapshots `). Файл со снимком — это дисковая " -"копия всех данных в базе на какой-то момент. Вместо того, чтобы перечитывать" -" все WAL-файлы с момента создания базы, Tarantool в процессе восстановления " -"может загрузить самый свежий снимок и затем прочитать только те WAL-файлы, " -"которые были созданы начиная с момента сохранения снимка. После создания " -"новых снимков более ранние WAL-файлы могут быть удалены, чтобы освободить " -"место на диске." - -msgid "" -"To force immediate creation of a snapshot file, use the :doc:`box.snapshot()" -" ` function. To enable the automatic " -"creation of snapshot files, use Tarantool's :ref:`checkpoint daemon " -"`. The checkpoint daemon sets intervals for " -"forced checkpoints. It makes sure that the states of both memtx and vinyl " -"storage engines are synchronized and saved to disk, and automatically " -"removes earlier WAL files." -msgstr "" -"Чтобы принудительно создать файл снимка, используйте в Tarantool функцию " -":doc:`box.snapshot() `. Чтобы " -"включить автоматическое создание файлов снимков, используйте :ref:`демон " -"создания контрольных точек (checkpoint daemon) `" -" Tarantool. Этот демон определяет интервалы для принудительного создания " -"контрольных точек. Он обеспечивает синхронизацию и сохранение на диск " -"образов движков базы данных (как memtx, так и vinyl), а также автоматически " -"удаляет более ранние WAL-файлы." - -msgid "Snapshot files can be created even if there is no WAL file." -msgstr "Файлы со снимками можно создавать, даже если WAL-файлы отсутствуют." - -msgid "" -"The memtx engine makes only regular checkpoints with the interval set in " -":ref:`checkpoint daemon ` configuration." -msgstr "" -"Движок memtx регулярно создает контрольные точки с интервалом, указанным в " -"настройках :ref:`демона создания контрольных точек " -"`." - -msgid "The vinyl engine runs checkpointing in the background at all times." -msgstr "" -"Движок vinyl постоянно сохраняет состояние в контрольной точке в фоновом " -"режиме." - -msgid "" -"See the :ref:`Internals ` section for more " -"details about the WAL writer and the recovery process." -msgstr "" -"Для получения более подробной информации о методе записи WAL-файлов и " -"процессе восстановления см. раздел :ref:`Внутренняя реализация `." - -msgid "Operations" -msgstr "Операции" - -msgid "Data operations" -msgstr "Операции с данными" - -msgid "The basic data operations supported in Tarantool are:" -msgstr "Tarantool поддерживает следующие основные операции с данными:" - -msgid "" -"five data-manipulation operations (INSERT, UPDATE, UPSERT, DELETE, REPLACE)," -" and" -msgstr "" -"пять операций по изменению данных (INSERT, UPDATE, UPSERT, DELETE, REPLACE) " -"и" - -msgid "one data-retrieval operation (SELECT)." -msgstr "одну операцию по выборке данных (SELECT)." - -msgid "" -"All of them are implemented as functions in :ref:`box.space ` " -"submodule." -msgstr "" -"Все они реализованы в виде функций во вложенном модуле :ref:`box.space " -"`." - -msgid "**Examples:**" -msgstr "**Примеры:**" - -msgid ":ref:`INSERT `: Add a new tuple to space 'tester'." -msgstr "" -":ref:`INSERT `: добавить новый кортеж к спейсу 'tester'." - -msgid "The first field, field[1], will be 999 (MsgPack type is `integer`)." -msgstr "" -"Первое поле, field[1], будет 999 (тип MsgPack -- `integer`, целое число)." - -msgid "" -"The second field, field[2], will be 'Taranto' (MsgPack type is `string`)." -msgstr "" -"Второе поле, field[2], будет 'Taranto' (тип MsgPack -- `string`, строка)." - -msgid "tarantool> box.space.tester:insert{999, 'Taranto'}" -msgstr "tarantool> box.space.tester:insert{999, 'Taranto'}" - -msgid "" -":ref:`UPDATE `: Update the tuple, changing field field[2]." -msgstr "" -":ref:`UPDATE `: обновить кортеж, изменяя поле field[2]." - -msgid "" -"The clause \"{999}\", which has the value to look up in the index of the " -"tuple's primary-key field, is mandatory, because ``update()`` requests must " -"always have a clause that specifies a unique key, which in this case is " -"field[1]." -msgstr "" -"Оператор \"{999}\" со значением, которое используется для поиска поля, " -"соответствующего ключу в первичном индексе, является обязательным, поскольку" -" в запросе ``update()`` должен быть оператор, который указывает уникальный " -"ключ, в данном случае -- field[1]." - -msgid "" -"The clause \"{{'=', 2, 'Tarantino'}}\" specifies that assignment will happen" -" to field[2] with the new value." -msgstr "" -"Оператор \"{{'=', 2, 'Tarantino'}}\" указывает, что назначение нового " -"значения относится к field[2]." - -msgid "tarantool> box.space.tester:update({999}, {{'=', 2, 'Tarantino'}})" -msgstr "tarantool> box.space.tester:update({999}, {{'=', 2, 'Tarantino'}})" - -msgid "" -":ref:`UPSERT `: Upsert the tuple, changing field field[2] " -"again." -msgstr "" -":ref:`UPSERT `: обновить или вставить кортеж, снова " -"изменяя поле field[2]." - -msgid "" -"The syntax of ``upsert()`` is similar to the syntax of ``update()``. " -"However, the execution logic of these two requests is different. UPSERT is " -"either UPDATE or INSERT, depending on the database's state. Also, UPSERT " -"execution is postponed until after transaction commit, so, unlike " -"``update()``, ``upsert()`` doesn't return data back." -msgstr "" -"Синтаксис ``upsert()`` похож на синтаксис ``update()``. Однако логика " -"выполнения двух запросов отличается. UPSERT означает UPDATE или INSERT, в " -"зависимости от состояния базы данных. Кроме того, выполнение UPSERT " -"откладывается до коммита транзакции, поэтому в отличие от ``update()``, " -"``upsert()`` не возвращает данные." - -msgid "" -"tarantool> box.space.tester:upsert({999, 'Taranted'}, {{'=', 2, " -"'Tarantism'}})" -msgstr "" -"tarantool> box.space.tester:upsert({999, 'Taranted'}, {{'=', 2, " -"'Tarantism'}})" - -msgid "" -":ref:`REPLACE `: Replace the tuple, adding a new field." -msgstr "" -":ref:`REPLACE `: заменить кортеж, добавляя новое поле." - -msgid "" -"This is also possible with the ``update()`` request, but the ``update()`` " -"request is usually more complicated." -msgstr "" -"Это действие также можно выполнить с помощью запроса ``update()``, но обычно" -" запрос ``update()`` более сложен." - -msgid "tarantool> box.space.tester:replace{999, 'Tarantella', 'Tarantula'}" -msgstr "tarantool> box.space.tester:replace{999, 'Tarantella', 'Tarantula'}" - -msgid ":ref:`SELECT `: Retrieve the tuple." -msgstr ":ref:`SELECT `: провести выборку кортежа." - -msgid "" -"The clause \"{999}\" is still mandatory, although it does not have to " -"mention the primary key." -msgstr "" -"Оператор \"{999}\" все еще обязателен, хотя в нем не должен упоминаться " -"первичный ключ." - -msgid "tarantool> box.space.tester:select{999}" -msgstr "tarantool> box.space.tester:select{999}" - -msgid ":ref:`DELETE `: Delete the tuple." -msgstr ":ref:`DELETE `: удалить кортеж." - -msgid "In this example, we identify the primary-key field." -msgstr "" -"В этом примере мы определяем поле, соответствующее ключу в первичном " -"индексе." - -msgid "tarantool> box.space.tester:delete{999}" -msgstr "tarantool> box.space.tester:delete{999}" - -msgid "Summarizing the examples:" -msgstr "Подводя итоги по примерам:" - -msgid "" -"Functions ``insert`` and ``replace`` accept a tuple (where a primary key " -"comes as part of the tuple)." -msgstr "" -"Функции ``insert`` и ``replace`` принимают кортеж (где первичный ключ -- это" -" часть кортежа)." - -msgid "" -"Function ``upsert`` accepts a tuple (where a primary key comes as part of " -"the tuple), and also the update operations to execute." -msgstr "" -"Функция ``upsert`` принимает кортеж (где первичный ключ -- это часть " -"кортежа), а также операции по обновлению." - -msgid "" -"Function ``delete`` accepts a full key of any unique index (primary or " -"secondary)." -msgstr "" -"Функция ``delete`` принимает полный ключ любого уникального индекса " -"(первичный или вторичный)." - -msgid "" -"Function ``update`` accepts a full key of any unique index (primary or " -"secondary), and also the operations to execute." -msgstr "" -"Функция ``update`` принимает полный ключ любого уникального индекса " -"(первичный или вторичный), а также операции к выполнению." - -msgid "" -"Function ``select`` accepts any key: primary/secondary, unique/non-unique, " -"full/partial." -msgstr "" -"Функция ``select`` принимает любой ключ: первичный/вторичный, " -"уникальный/неуникальный, полный/часть." - -msgid "" -"See reference on ``box.space`` for more :ref:`details on using data " -"operations `." -msgstr "" -"Для получения более :ref:`подробной информации по использованию операций с " -"данными ` см. справочник по " -"``box.space``." - -msgid "" -"Besides Lua, you can use :ref:`Perl, PHP, Python or other programming " -"language connectors `. The client server protocol is " -"open and documented. See this :ref:`annotated BNF `." -msgstr "" -"Помимо Lua можно использовать :ref:`коннекторы к Perl, PHP, Python или " -"другому языку программирования `. Клиент-серверный " -"протокол открыт и задокументирован. См. :ref:`БНФ с комментариями " -"`." - -msgid "Complexity factors" -msgstr "Факторы сложности" - -msgid "" -"In reference for :ref:`box.space ` and " -":doc:`/reference/reference_lua/box_index` submodules, there are notes about " -"which complexity factors might affect the resource usage of each function." -msgstr "" -"Во вложенных модулях :ref:`box.space ` и " -":doc:`/reference/reference_lua/box_index` содержится информация о том, как " -"факторы сложности могут повлиять на использование каждой функции." - -msgid "Complexity factor" -msgstr "Фактор сложности" - -msgid "Effect" -msgstr "Эффект" - -msgid "Index size" -msgstr "Размер индекса" - -msgid "" -"The number of index keys is the same as the number of tuples in the data " -"set. For a TREE index, if there are more keys, then the lookup time will be " -"greater, although, of course, the effect is not linear. For a HASH index, if" -" there are more keys, then there is more RAM used, but the number of low-" -"level steps tends to remain constant." -msgstr "" -"Количество ключей в индексе равно количеству кортежей в наборе данных. Для " -"TREE-индекса: чем больше ключей, тем больше время поиска, хотя зависимость " -"здесь, конечно же, нелинейная. Для HASH-индекса: чем больше ключей, тем " -"больше нужно оперативной памяти, но количество низкоуровневых шагов остается" -" примерно тем же." - -msgid "" -"Typically, a HASH index is faster than a TREE index if the number of tuples " -"in the space is greater than one." -msgstr "" -"Как правило, поиск по HASH-индексу работает быстрее, чем по TREE-индексу, " -"если в спейсе более одного кортежа." - -msgid "Number of indexes accessed" -msgstr "Количество обращений к индексам" - -msgid "" -"Ordinarily, only one index is accessed to retrieve one tuple. But to update " -"the tuple, there must be N accesses if the space has N different indexes." -msgstr "" -"Обычно для выборки значений одного кортежа используется только один индекс. " -"Но при обновлении значений в кортеже требуется N обращений, если в спейсе N " -"индексов." - -msgid "" -"Note regarding storage engine: Vinyl optimizes away such accesses if " -"secondary index fields are unchanged by the update. So, this complexity " -"factor applies only to memtx, since it always makes a full-tuple copy on " -"every update." -msgstr "" -"Примечание по движку базы данных: если обновление не затрагивает поля " -"вторичного индекса, vinyl не производит эти обращения. Таким образом, этот " -"фактор сложности влияет только на memtx, который создает копию всего кортежа" -" при каждом обновлении." - -msgid "Number of tuples accessed" -msgstr "Количество обращений к кортежам" - -msgid "" -"A few requests, for example, SELECT, can retrieve multiple tuples. This " -"factor is usually less important than the others." -msgstr "" -"Некоторые запросы, например SELECT, могут возвращать несколько кортежей. " -"Обычно этот фактор менее важен, чем другие." - -msgid "WAL settings" -msgstr "Настройки WAL" - -msgid "" -"The important setting for the write-ahead log is :ref:`wal_mode " -"`. If the setting causes no writing " -"or delayed writing, this factor is unimportant. If the setting causes every " -"data-change request to wait for writing to finish on a slow device, this " -"factor is more important than all the others." -msgstr "" -"Важным параметром для записи в WAL является :ref:`wal_mode " -"`. Если запись в WAL отключена или " -"задана запись с задержкой, но этот фактор не так важен. Если же запись в " -"WAL производится при каждом запросе на изменение данных, то при каждом таком" -" запросе приходится ждать, пока отработает обращение к более медленному " -"диску, и данный фактор становится важнее всех остальных." - -msgid "Data schema description" -msgstr "Описание схемы данных" - -msgid "In Tarantool, the use of a data schema is optional." -msgstr "В Tarantool использование схемы данных опционально." - -msgid "" -"When creating a :term:`space `, you do not have to define a data " -"schema. In this case, the tuples store random data. This rule does not apply" -" to indexed fields. Such fields must contain data of the same type." -msgstr "" -"При создании :term:`спейса ` схему можно не задавать и тогда в " -"кортежах могут лежать произвольные данные. Это правило не распространяется " -"на поля, по которым построены индексы. У таких полей данные должны быть " -"одного типа." - -msgid "" -"You can define a data schema when creating a space. Read more in the " -"description of the :doc:`/reference/reference_lua/box_schema/space_create` " -"function. If you have already created a space without specifying a data " -"schema, you can do it later using " -":doc:`/reference/reference_lua/box_space/format`." -msgstr "" -"Схему можно задать при создании спейса. Читайте подробнее в описании функции" -" :doc:`/reference/reference_lua/box_schema/space_create`. Если вы создали " -"спейс без схемы, ее можно добавить позже с помощью метода " -":doc:`/reference/reference_lua/box_space/format`." - -msgid "" -"After the data schema is defined, all the data is validated by type. Before " -"any insert or update, you will get an error if the data types do not match." -msgstr "" -"После указания схемы данные начинают валидироваться по типам. Перед каждой " -"операцией вставки или обновления они проверяются, и в случае несоответствия " -"типов вы получите ошибку." - -msgid "We recommend using a data schema because it helps avoid mistakes." -msgstr "" -"Мы рекомендуем использовать подход со схемой, потому что он помогает " -"избежать ошибок." - -msgid "In Tarantool, you can define a data schema in two different ways." -msgstr "Схему в Tarantool можно задавать двумя разными способами." - -msgid "Data schema description in a code file" -msgstr "Описание схемы в файле с кодом" - -msgid "" -"The code file is usually called ``init.lua`` and contains the following " -"schema description:" -msgstr "" -"Обычно файл с кодом называется ``init.lua`` и имеет следующее описание " -"схемы:" - -msgid "" -"box.cfg()\n" -"\n" -"users = box.schema.create_space('users', { if_not_exists = true })\n" -"users:format({{ name = 'user_id', type = 'number'}, { name = 'fullname', type = 'string'}})\n" -"\n" -"users:create_index('pk', { parts = { { field = 'user_id', type = 'number'}}})" -msgstr "" -"box.cfg()\n" -"\n" -"users = box.schema.create_space('users', { if_not_exists = true })\n" -"users:format({{ name = 'user_id', type = 'number'}, { name = 'fullname', type = 'string'}})\n" -"\n" -"users:create_index('pk', { parts = { { field = 'user_id', type = 'number'}}})" - -msgid "" -"This is quite simple: when you run tarantool, it executes this code and " -"creates a data schema. To run this file, use:" -msgstr "" -"Этот подход довольно простой. Когда вы запустите tarantool, этот код " -"исполнится и создаст схему. Чтобы запустить файл, используйте следующую " -"команду:" - -msgid "tarantool init.lua" -msgstr "tarantool init.lua" - -msgid "" -"However, it may seem complicated if you do not plan to dive deep into the " -"Lua language and its syntax." -msgstr "" -"Но это может показаться слишком сложным, если вы не собираетесь глубоко " -"разбираться с языком Lua и его синтаксисом." - -msgid "" -"Possible difficulty: the snippet above has a function call with a colon: " -"``users:format``. It is used to pass the ``users`` variable as the first " -"argument of the ``format`` function. This is similar to ``self`` in object-" -"based languages." -msgstr "" -"Пример возможной сложности: в фрагменте выше есть вызов функций с " -"двоеточием: ``users:format``. Он используется, чтобы передать переменную " -"``users`` в качестве первого аргумента функции ``format``. Это аналог " -"``self`` в объектно-ориентированных языках." - -msgid "" -"So it might be more convenient for you to describe the data schema with " -"YAML." -msgstr "Поэтому вам может быть удобно описать схему через YAML." - -msgid "Data schema description using the DDL module" -msgstr "Описание через модуль DDL" - -msgid "" -"The `DDL module `_ allows you to describe " -"a data schema in the YAML format in a declarative way." -msgstr "" -"`Модуль DDL `_ позволяет декларативно " -"описывать схему данных в YAML формате." - -msgid "The schema would look something like this:" -msgstr "Схема будет выглядеть примерно вот так:" - -msgid "" -"spaces:\n" -" users:\n" -" engine: memtx\n" -" is_local: false\n" -" temporary: false\n" -" format:\n" -" - {name: user_id, type: uuid, is_nullable: false}\n" -" - {name: fullname, type: string, is_nullable: false}\n" -" indexes:\n" -" - name: user_id\n" -" unique: true\n" -" parts: [{path: user_id, type: uuid, is_nullable: false}]\n" -" type: HASH" -msgstr "" -"spaces:\n" -" users:\n" -" engine: memtx\n" -" is_local: false\n" -" temporary: false\n" -" format:\n" -" - {name: user_id, type: uuid, is_nullable: false}\n" -" - {name: fullname, type: string, is_nullable: false}\n" -" indexes:\n" -" - name: user_id\n" -" unique: true\n" -" parts: [{path: user_id, type: uuid, is_nullable: false}]\n" -" type: HASH" - -msgid "" -"This alternative is simpler to use, and you do not have to dive deep into " -"Lua." -msgstr "" -"Этот вариант проще для старта: его проще использовать и не нужно вникать в " -"язык Lua." - -msgid "" -"``DDL`` is a built-in :doc:`Cartridge ` module. " -"Cartridge is a cluster solution for Tarantool. In its WebUI, there is a " -"separate tab called \"Schema\". On this tab, you can define the schema, " -"check its correctness, and apply it to the whole cluster." -msgstr "" -"Модуль ``DDL`` встроен по умолчанию в :doc:`Cartridge `.\n" -"Cartridge — это кластерное решение для Tarantool. В его веб-интерфейсе есть\n" -"отдельная вкладка \"Schema\". Там можно написать схему, проверить ее корректность и применить на всем кластере." - -msgid "" -"If you do not use Cartridge, you can still use the DDL module: put the " -"following Lua code into the file that you use to run Tarantool. This file is" -" usually called ``init.lua``." -msgstr "" -"Если вы не используете Cartridge, то чтобы использовать модуль DDL, нужно " -"вставить нижеприведенный код на Lua в файл, с которым вы запускаете " -"Tarantool. Обычно это ``init.lua``." - -msgid "" -"local yaml = require('yaml')\n" -"local ddl = require('ddl')\n" -"\n" -"box.cfg{}\n" -"\n" -"local fh = io.open('ddl.yml', 'r')\n" -"local schema = yaml.decode(fh:read('*all'))\n" -"fh:close()\n" -"local ok, err = ddl.check_schema(schema)\n" -"if not ok then\n" -" print(err)\n" -"end\n" -"local ok, err = ddl.set_schema(schema)\n" -"if not ok then\n" -" print(err)\n" -"end" -msgstr "" -"local yaml = require('yaml')\n" -"local ddl = require('ddl')\n" -"\n" -"box.cfg{}\n" -"\n" -"local fh = io.open('ddl.yml', 'r')\n" -"local schema = yaml.decode(fh:read('*all'))\n" -"fh:close()\n" -"local ok, err = ddl.check_schema(schema)\n" -"if not ok then\n" -" print(err)\n" -"end\n" -"local ok, err = ddl.set_schema(schema)\n" -"if not ok then\n" -" print(err)\n" -"end" - -msgid "" -"It is forbidden to modify the data schema in DDL after it has been applied. " -"For migration, there are different scenarios described below." -msgstr "" -"Менять схему в самом DDL после ее применения нельзя. Для миграций есть " -"несколько подходов — они описаны ниже." - -msgid "Migrations" -msgstr "Миграции" - -msgid "" -"**Migration** refers to any change in a data schema: adding/removing a " -"field, creating/dropping an index, changing a field format, etc." -msgstr "" -"**Миграцией** называется любое изменение схемы данных: добавление/удаление " -"поля, добавление/удаление индекса, изменение формата поля и т. д." - -msgid "" -"In Tarantool, there are two types of schema migration that do not require " -"data migration:" -msgstr "" -"В Tarantool есть только два вида миграции схемы, при которых не нужно " -"мигрировать данные:" - -msgid "adding a field to the end of a space" -msgstr "добавление поля в конец спейса" - -msgid "creating an index" -msgstr "добавление индекса" - -msgid "Adding a field to the end of a space" -msgstr "Добавление поля в конец спейса" - -msgid "You can add a field as follows:" -msgstr "Добавление поля происходит следующим образом:" - -msgid "" -"local users = box.space.users\n" -"local fmt = users:format()\n" -"\n" -"table.insert(fmt, { name = 'age', type = 'number', is_nullable = true })\n" -"users:format(fmt)" -msgstr "" -"local users = box.space.users\n" -"local fmt = users:format()\n" -"\n" -"table.insert(fmt, { name = 'age', type = 'number', is_nullable = true })\n" -"users:format(fmt)" - -msgid "" -"Note that the field must have the ``is_nullable`` parameter. Otherwise, an " -"error will occur." -msgstr "" -"Обратите внимание: поле обязательно должно иметь параметр ``is_nullable``. " -"Иначе произойдет ошибка." - -msgid "" -"After creating a new field, you probably want to fill it with data. The " -"`tarantool/moonwalker `_ module is " -"useful for this task. The README file describes how to work with this " -"module." -msgstr "" -"После создания нового поля, вы, вероятно, захотите заполнить его данными.\n" -"Для этой задачи удобно использовать модуль `tarantool/moonwalker `_. В README есть описание того, как начать его использовать." - -msgid "Creating an index" -msgstr "Добавление индекса" - -msgid "" -"Index creation is described in the " -":doc:`/reference/reference_lua/box_space/create_index` method." -msgstr "" -"Про добавление индекса рассказывается в описании метода " -":doc:`/reference/reference_lua/box_space/create_index`." - -msgid "Other types of migrations" -msgstr "Остальные виды миграций" - -msgid "" -"Other types of migrations are also allowed, but it would be more difficult " -"to maintain data consistency." -msgstr "" -"Остальные виды миграций также возможны, однако поддерживать консистентность " -"данных при этом сложнее." - -msgid "Migrations are possible in two cases:" -msgstr "Миграции можно выполнять в двух случаях:" - -msgid "When Tarantool starts, and no client uses the database yet" -msgstr "при старте Tarantool, пока ни один клиент еще не использует БД" - -msgid "" -"During request processing, when active clients are already using the " -"database" -msgstr "в процессе обработки запросов, когда у БД уже есть активные клиенты" - -msgid "" -"For the first case, it is enough to write and test the migration code. The " -"most difficult task is to migrate data when there are active clients. You " -"should keep it in mind when you initially design the data schema." -msgstr "" -"Для первого случая достаточно кода миграции, который будет написан и " -"оттестирован. Самая сложная задача — это провести миграцию данных при " -"наличии активных клиентов. Это необходимо иметь в виду при начальном " -"проектировании схемы данных." - -msgid "We identify the following problems if there are active clients:" -msgstr "Мы выделяем следующие проблемы при наличии активных клиентов:" - -msgid "Associated data can change atomically." -msgstr "Связанные данные могут атомарно изменяться." - -msgid "" -"The system should be able to transfer data using both the new schema and the" -" old one." -msgstr "Нужно уметь отдавать данные как по новой схеме, так и по старой." - -msgid "" -"When data is being transferred to a new space, data access should consider " -"that the data might be in one space or another." -msgstr "" -"Когда данные перемещают в новый спейс, доступ к данным должен учитывать, что" -" данные могут быть как в одном спейсе, так и в другом." - -msgid "" -"Write requests must not interfere with the migration. A common approach is " -"to write according to the new data schema." -msgstr "" -"Запросы на запись не должны мешать корректной миграции. Типичный подход: " -"всегда писать по новой схеме." - -msgid "" -"These issues may or may not be relevant depending on your application and " -"its availability requirements." -msgstr "" -"Эти проблемы могут быть или не быть релевантными в зависимости от вашего " -"приложения и требований к его доступности." - -msgid "What you need to know when writing complex migrations" -msgstr "Что нужно знать при написании сложных миграций" - -msgid "" -"Tarantool has a transaction mechanism. It is useful when writing a " -"migration, because it allows you to work with the data atomically. But " -"before using the transaction mechanism, you should explore its limitations." -msgstr "" -"В Tarantool есть механизм транзакций. Он полезен при написании миграции, так" -" как позволяет атомарно работать с данными. Но перед использованием " -"механизма транзакций нужно знать об ограничениях." - -msgid "" -"For details, see the section about :doc:`transactions `." -msgstr "" -"Подробнее о них описано в разделе про :doc:`транзакции `." - -msgid "How you can apply migration" -msgstr "Как применять миграции" - -msgid "" -"The migration code is executed on a running Tarantool instance. Important: " -"no method guarantees you transactional application of migrations on the " -"whole cluster." -msgstr "" -"Код миграций исполняется на запущенном инстансе Tarantool. Важно: ни один " -"способ не гарантирует вам транзакционное применение миграций на всем " -"кластере." - -msgid "**Method 1**: include migrations in the application code" -msgstr "**Способ 1**: написать миграции в коде основного приложения" - -msgid "" -"This is quite simple: when you reload the code, the data is migrated at the " -"right moment, and the database schema is updated. However, this method may " -"not work for everyone. You may not be able to restart Tarantool or update " -"the code using the hot-reload mechanism." -msgstr "" -"Это довольно просто: когда вы перезагружаете код, в нужный момент происходит" -" миграция данных и схема базы данных обновляется. Однако такой способ может " -"подойти не всем. У вас может не быть возможности перезапустить Tarantool или" -" обновить код через механизм горячей перезагрузки (hot reload)." - -msgid "" -"**Method 2**: tarantool/migrations (only for a Tarantool Cartridge cluster)" -msgstr "" -"**Способ 2**: tarantool/migrations (только для кластера на Tarantool " -"Cartridge)" - -msgid "" -"This method is described in the README file of the `tarantool/migrations " -"`_ module." -msgstr "" -"Про этот способ подробнее написано в README самого модуля " -"`tarantool/migrations `_." - -msgid "" -"There are also two other methods that we **do not recommend**, but you may " -"find them useful for one reason or another." -msgstr "" -"Есть также два способа, которые мы **не рекомендуем использовать**, но вы " -"можете найти их полезными по тем или иным причинам." - -msgid "**Method 3**: the ``tarantoolctl`` utility" -msgstr "**Cпособ 3**: утилита ``tarantoolctl``" - -msgid "" -"The ``tarantoolctl`` utility ships with Tarantool. Connect to the necessary " -"instance using ``tarantoolctl connect``." -msgstr "" -"Утилита ``tarantoolctl`` поставляется вместе с Tarantool. Подключитесь к " -"нужному инстансу через команду ``tarantoolctl connect``." - -msgid "$ tarantoolctl connect admin:password@localhost:3301" -msgstr "$ tarantoolctl connect admin:password@localhost:3301" - -msgid "" -"If your migration is written in a Lua file, you can execute it using " -"``dofile()``. Call this function and specify the path to the migration file " -"as the first argument. It looks like this:" -msgstr "" -"Если ваша миграция написана в Lua файле, вы можете исполнить его с помощью " -"функции ``dofile()``. Вызовите ее и первым аргументом укажите путь до файла " -"с миграцией. Выглядит это вот так:" - -msgid "" -"tarantool> dofile('0001-delete-space.lua')\n" -"---\n" -"..." -msgstr "" -"tarantool> dofile('0001-delete-space.lua')\n" -"---\n" -"..." - -msgid "" -"(or) Copy the migration script code, paste it into the console, and run it." -msgstr "" -"(или) можно скопировать код скрипта миграции, вставить его в консоль и " -"применить." - -msgid "**Method 4**: applying migration with Ansible" -msgstr "**Способ 4**: применение миграции с помощью Ansible" - -msgid "" -"If you use the `Ansible role `_ to deploy a Tarantool cluster, you can use ``eval``. You can " -"find more information about it `in the Ansible role documentation " -"`_." -msgstr "" -"Если вы используете `Ansible-роль для развёртывания кластера Tarantool " -"`_, то вы можете применить " -"``eval``. Прочитать подробнее про ``eval`` можно `в документации по Ansible-" -"роли `_." diff --git a/locale/ru/LC_MESSAGES/book/replication/repl_add_instances.po b/locale/ru/LC_MESSAGES/book/replication/repl_add_instances.po deleted file mode 100644 index 965140422b..0000000000 --- a/locale/ru/LC_MESSAGES/book/replication/repl_add_instances.po +++ /dev/null @@ -1,815 +0,0 @@ - -msgid "Adding instances" -msgstr "Добавление экземпляров" - -msgid "Adding a replica" -msgstr "Добавление реплики" - -msgid "" -"To add a second **replica** instance to the **master-replica** set from our " -":ref:`bootstrapping example `, we need" -" an analog of the instance file that we created for the first replica in " -"that set:" -msgstr "" -"Чтобы добавить вторую **реплику** в набор реплик с конфигурацией **мастер-" -"реплика** из нашего :ref:`примера настройки `, необходим аналог файла экземпляра, который мы " -"создали для первой реплики в этом наборе:" - -msgid "" -"-- instance file for replica #2\n" -"box.cfg{\n" -" listen = 3301,\n" -" replication = {'replicator:password@192.168.0.101:3301', -- master URI\n" -" 'replicator:password@192.168.0.102:3301', -- replica #1 URI\n" -" 'replicator:password@192.168.0.103:3301'}, -- replica #2 URI\n" -" read_only = true\n" -"}\n" -"box.once(\"schema\", function()\n" -" box.schema.user.create('replicator', {password = 'password'})\n" -" box.schema.user.grant('replicator', 'replication') -- grant replication role\n" -" box.schema.space.create(\"test\")\n" -" box.space.test:create_index(\"primary\")\n" -" print('box.once executed on replica #2')\n" -"end)" -msgstr "" -"-- файл экземпляра для реплики №2\n" -"box.cfg{\n" -" listen = 3301,\n" -" replication = {'replicator:password@192.168.0.101:3301', -- URI мастера\n" -" 'replicator:password@192.168.0.102:3301', -- URI реплики №1\n" -" 'replicator:password@192.168.0.103:3301'}, -- URI реплики №2\n" -" read_only = true\n" -"}\n" -"box.once(\"schema\", function()\n" -" box.schema.user.create('replicator', {password = 'password'})\n" -" box.schema.user.grant('replicator', 'replication') -- предоставить роль для репликации\n" -" box.schema.space.create(\"test\")\n" -" box.space.test:create_index(\"primary\")\n" -" print('box.once executed on replica #2')\n" -"end)" - -msgid "" -"Here we add the URI of replica #2 to the :ref:`replication ` parameter, so now it contains three URIs." -msgstr "" -"Здесь мы добавляем URI реплики №2 в параметр :ref:`replication " -"`, так что теперь он содержит три URI." - -msgid "" -"After we launch the new replica instance, it gets connected to the master " -"instance and retrieves the master's write-ahead-log and snapshot files:" -msgstr "" -"После запуска новая реплика подключается к мастер-серверу и получает от него" -" журнал упреждающей записи и файлы снимков:" - -msgid "" -"$ # launching replica #2\n" -"$ tarantool replica2.lua\n" -"2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> version 1.7.4-52-g980d30092\n" -"2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> log level 5\n" -"2017-06-14 14:54:33.928 [46945] main/101/replica2.lua I> mapping 268435456 bytes for tuple arena...\n" -"2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301\n" -"2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> authenticated\n" -"2017-06-14 14:54:33.930 [46945] main/101/replica2.lua I> bootstrapping replica from 192.168.0.101:3301\n" -"2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> initial data received\n" -"2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> final data received\n" -"2017-06-14 14:54:33.934 [46945] snapshot/101/main I> saving snapshot `/var/lib/tarantool/replica2/00000000000000000010.snap.inprogress'\n" -"2017-06-14 14:54:33.934 [46945] snapshot/101/main I> done\n" -"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> vinyl checkpoint done\n" -"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> ready to accept requests\n" -"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> set 'read_only' configuration option to true\n" -"2017-06-14 14:54:33.936 [46945] main C> entering the event loop" -msgstr "" -"$ # запуск реплики №2\n" -"$ tarantool replica2.lua\n" -"2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> version 1.7.4-52-g980d30092\n" -"2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> log level 5\n" -"2017-06-14 14:54:33.928 [46945] main/101/replica2.lua I> mapping 268435456 bytes for tuple arena...\n" -"2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301\n" -"2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> authenticated\n" -"2017-06-14 14:54:33.930 [46945] main/101/replica2.lua I> bootstrapping replica from 192.168.0.101:3301\n" -"2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> initial data received\n" -"2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> final data received\n" -"2017-06-14 14:54:33.934 [46945] snapshot/101/main I> saving snapshot `/var/lib/tarantool/replica2/00000000000000000010.snap.inprogress'\n" -"2017-06-14 14:54:33.934 [46945] snapshot/101/main I> done\n" -"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> vinyl checkpoint done\n" -"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> ready to accept requests\n" -"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> set 'read_only' configuration option to true\n" -"2017-06-14 14:54:33.936 [46945] main C> entering the event loop" - -msgid "" -"Since we are adding a read-only instance, there is no need to dynamically " -"update the ``replication`` parameter on the other running instances. This " -"update would be required if we :ref:`added a master instance `." -msgstr "" -"Поскольку мы добавляем экземпляр только для чтения (read-only), нет " -"необходимости в динамическом обновлении параметра ``replication`` на других " -"работающих экземплярах. Такое обновление необходимо, если бы мы " -":ref:`добавляли мастера `." - -msgid "" -"However, we recommend specifying the URI of replica #3 in all instance files" -" of the replica set. This will keep all the files consistent with each other" -" and with the current replication topology, and so will help to avoid " -"configuration errors in case of further configuration updates and replica " -"set restart." -msgstr "" -"Тем не менее, рекомендуем указать URI реплики №3 во всех файлах экземпляра в" -" наборе реплик. Это поможет сохранить единообразие файлов и согласовать их с" -" текущей топологией репликации, а также не допустить ошибок конфигурации в " -"случае последующего обновления конфигурации и перезапуска набора реплик." - -msgid "Adding a master" -msgstr "Добавление мастера" - -msgid "" -"To add a third master instance to the **master-master** set from our " -":ref:`bootstrapping example `, we need " -"an analog of the instance files that we created to bootstrap the other " -"master instances in that set:" -msgstr "" -"Чтобы добавить третьего мастера в набор реплик с конфигурацией **мастер-" -"мастер** из нашего :ref:`примера настройки `, необходим аналог файлов экземпляров, которые мы " -"создали для настройки других мастеров в этом наборе:" - -msgid "" -"-- instance file for master #3\n" -"box.cfg{\n" -" listen = 3301,\n" -" replication = {'replicator:password@192.168.0.101:3301', -- master#1 URI\n" -" 'replicator:password@192.168.0.102:3301', -- master#2 URI\n" -" 'replicator:password@192.168.0.103:3301'}, -- master#3 URI\n" -" read_only = true, -- temporarily read-only\n" -"}\n" -"box.once(\"schema\", function()\n" -" box.schema.user.create('replicator', {password = 'password'})\n" -" box.schema.user.grant('replicator', 'replication') -- grant replication role\n" -" box.schema.space.create(\"test\")\n" -" box.space.test:create_index(\"primary\")\n" -"end)" -msgstr "" -"-- файл экземпляра для мастера №3\n" -"box.cfg{\n" -" listen = 3301,\n" -" replication = {'replicator:password@192.168.0.101:3301', -- URI мастера №1\n" -" 'replicator:password@192.168.0.102:3301', -- URI мастера №2\n" -" 'replicator:password@192.168.0.103:3301'}, -- URI мастера №3\n" -" read_only = true, -- временно только для чтения\n" -"}\n" -"box.once(\"schema\", function()\n" -" box.schema.user.create('replicator', {password = 'password'})\n" -" box.schema.user.grant('replicator', 'replication') -- выдача роли для репликации\n" -" box.schema.space.create(\"test\")\n" -" box.space.test:create_index(\"primary\")\n" -"end)" - -msgid "Here we make the following changes:" -msgstr "Здесь мы вносим следующие изменения:" - -msgid "" -"Add the URI of master #3 to the :ref:`replication ` parameter." -msgstr "" -"Добавить URI мастера №3 в параметр :ref:`replication `." - -msgid "" -"Temporarily specify :ref:`read_only=true ` to disable " -"data-change operations on the instance. After launch, master #3 will act as " -"a replica until it retrieves all data from the other masters in the replica " -"set." -msgstr "" -"Временно укажите :ref:`read_only=true `, чтобы " -"отключить операции по изменению данных на этом экземпляре. После запуска " -"мастер №3 будет работать в качестве реплики, пока не получит все данные от " -"других мастеров в наборе реплик." - -msgid "" -"After we launch master #3, it gets connected to the other master instances " -"and retrieves their write-ahead-log and snapshot files:" -msgstr "" -"После запуска мастер №3 подключается к другим мастер-экземплярам и получает " -"от них файлы журнала упреждающей записи и файлы снимков:" - -msgid "" -"$ # launching master #3\n" -"$ tarantool master3.lua\n" -"2017-06-14 17:10:00.556 [47121] main/101/master3.lua C> version 1.7.4-52-g980d30092\n" -"2017-06-14 17:10:00.557 [47121] main/101/master3.lua C> log level 5\n" -"2017-06-14 17:10:00.557 [47121] main/101/master3.lua I> mapping 268435456 bytes for tuple arena...\n" -"2017-06-14 17:10:00.559 [47121] iproto/101/main I> binary: bound to [::]:3301\n" -"2017-06-14 17:10:00.559 [47121] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301\n" -"2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.102:3301\n" -"2017-06-14 17:10:00.559 [47121] main/106/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.103:3301\n" -"2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> authenticated\n" -"2017-06-14 17:10:00.559 [47121] main/101/master3.lua I> bootstrapping replica from 192.168.0.102:3301\n" -"2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> initial data received\n" -"2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> final data received\n" -"2017-06-14 17:10:00.562 [47121] snapshot/101/main I> saving snapshot `/Users/e.shebunyaeva/work/tarantool-test-repl/master3_dir/00000000000000000009.snap.inprogress'\n" -"2017-06-14 17:10:00.562 [47121] snapshot/101/main I> done\n" -"2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> vinyl checkpoint done\n" -"2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> ready to accept requests\n" -"2017-06-14 17:10:00.565 [47121] main/101/master3.lua I> set 'read_only' configuration option to true\n" -"2017-06-14 17:10:00.565 [47121] main C> entering the event loop\n" -"2017-06-14 17:10:00.565 [47121] main/104/applier/replicator@192.168.0.10 I> authenticated" -msgstr "" -"$ # запуск мастера №3\n" -"$ tarantool master3.lua\n" -"2017-06-14 17:10:00.556 [47121] main/101/master3.lua C> version 1.7.4-52-g980d30092\n" -"2017-06-14 17:10:00.557 [47121] main/101/master3.lua C> log level 5\n" -"2017-06-14 17:10:00.557 [47121] main/101/master3.lua I> mapping 268435456 bytes for tuple arena...\n" -"2017-06-14 17:10:00.559 [47121] iproto/101/main I> binary: bound to [::]:3301\n" -"2017-06-14 17:10:00.559 [47121] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301\n" -"2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.102:3301\n" -"2017-06-14 17:10:00.559 [47121] main/106/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.103:3301\n" -"2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> authenticated\n" -"2017-06-14 17:10:00.559 [47121] main/101/master3.lua I> bootstrapping replica from 192.168.0.102:3301\n" -"2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> initial data received\n" -"2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> final data received\n" -"2017-06-14 17:10:00.562 [47121] snapshot/101/main I> saving snapshot `/Users/e.shebunyaeva/work/tarantool-test-repl/master3_dir/00000000000000000009.snap.inprogress'\n" -"2017-06-14 17:10:00.562 [47121] snapshot/101/main I> done\n" -"2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> vinyl checkpoint done\n" -"2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> ready to accept requests\n" -"2017-06-14 17:10:00.565 [47121] main/101/master3.lua I> set 'read_only' configuration option to true\n" -"2017-06-14 17:10:00.565 [47121] main C> entering the event loop\n" -"2017-06-14 17:10:00.565 [47121] main/104/applier/replicator@192.168.0.10 I> authenticated" - -msgid "" -"Next, we add the URI of master #3 to the ``replication`` parameter on the " -"existing two masters. Replication-related parameters are dynamic, so we only" -" need to make a ``box.cfg{}`` request on each of the running instances:" -msgstr "" -"Затем добавляем URI мастера №3 в параметр ``replication`` на существующих " -"мастерах. В конфигурации репликации используются динамические параметры, " -"поэтому необходимо только выполнить запрос ``box.cfg{}`` на каждом " -"работающем экземпляре:" - -msgid "" -"# adding master #3 URI to replication sources\n" -"tarantool> box.cfg{replication =\n" -" > {'replicator:password@192.168.0.101:3301',\n" -" > 'replicator:password@192.168.0.102:3301',\n" -" > 'replicator:password@192.168.0.103:3301'}}\n" -"---\n" -"..." -msgstr "" -"# добавление URI мастера №3 в источники репликации\n" -"tarantool> box.cfg{replication =\n" -" > {'replicator:password@192.168.0.101:3301',\n" -" > 'replicator:password@192.168.0.102:3301',\n" -" > 'replicator:password@192.168.0.103:3301'}}\n" -"---\n" -"..." - -msgid "" -"When master #3 catches up with the other masters' state, we can disable " -"read-only mode for this instance:" -msgstr "" -"Когда мастер №3 получает все необходимые изменения от других мастеров, можно" -" отключить режим только для чтения:" - -msgid "" -"# making master #3 a real master\n" -"tarantool> box.cfg{read_only=false}\n" -"---\n" -"..." -msgstr "" -"# назначение мастера №3 настоящим мастером\n" -"tarantool> box.cfg{read_only=false}\n" -"---\n" -"..." - -msgid "" -"We also recommend to specify master #3 URI in all instance files in order to" -" keep all the files consistent with each other and with the current " -"replication topology." -msgstr "" -"Также рекомендуется указать URI мастера №3 во всех файлах экземпляра, чтобы " -"сохранить единообразие файлов и согласовать их с текущей топологией " -"репликации." - -msgid "Orphan status" -msgstr "Статус orphan (одиночный)" - -msgid "" -"Starting with Tarantool version 1.9, there is a change to the procedure when" -" an instance joins a replica set. During ``box.cfg()`` the instance will try" -" to join all masters listed in :ref:`box.cfg.replication `. If the instance does not succeed with at least the number of " -"masters specified in :ref:`replication_connect_quorum `, then it will switch to **orphan status**. " -"While an instance is in orphan status, it is read-only." -msgstr "" -"Начиная с версии Tarantool 1.9, процедура подключения реплики к набору " -"реплик изменяется. Во время ``box.cfg()`` экземпляр попытается подключиться " -"ко всем мастерам, указанным в :ref:`box.cfg.replication `. Если не было успешно выполнено подключение к количеству " -"мастеров, указанному в :ref:`replication_connect_quorum `, экземпляр переходит в **статус orphan** " -"(одиночный). Когда экземпляр находится в статусе orphan, он доступен только " -"для чтения." - -msgid "" -"To \"join\" a master, a replica instance must \"connect\" to the master node" -" and then \"sync\"." -msgstr "" -"Чтобы \"подключиться\" к мастеру, реплика должна \"установить соединение\" с" -" узлом мастера, а затем \"выполнить синхронизацию\"." - -msgid "" -"\"Connect\" means contact the master over the physical network and receive " -"acknowledgment. If there is no acknowledgment after " -":ref:`box.replication_connect_timeout ` seconds (usually 4 seconds), and retries fail," -" then the connect step fails." -msgstr "" -"\"Установка соединения\" означает контакт с мастером по физической сети и " -"получение подтверждения. Если нет подтверждения соединения через " -":ref:`box.replication_connect_timeout ` секунд (обычно 4 секунды), и повторные попытки" -" подключения не сработали, то соединение не установлено." - -msgid "" -"\"Sync\" means receive updates from the master in order to make a local " -"database copy. Syncing is complete when the replica has received all the " -"updates, or at least has received enough updates that the replica's lag (see" -" :ref:`replication.upstream.lag ` in " -"``box.info()``) is less than or equal to the number of seconds specified in " -":ref:`box.cfg.replication_sync_lag `. " -"If ``replication_sync_lag`` is unset (nil) or set to TIMEOUT_INFINITY, then " -"the replica skips the \"sync\" state and switches to \"follow\" immediately." -msgstr "" -"\"Синхронизация\" означает получение обновлений от мастера для создания " -"локальной копии базы данных. Синхронизация завершена, когда реплика получила" -" все обновления или хотя бы получила достаточное количество обновлений, " -"чтобы отставание реплики (см. :ref:`replication.upstream.lag " -"` в ``box.info()``) было меньше или равно" -" количеству секунд, указанному в :ref:`box.cfg.replication_sync_lag " -"`. Если значение " -"``replication_sync_lag`` не задано (nil) или указано как " -"\"TIMEOUT_INFINITY\", то реплика пропускает шаг \"синхронизация\" и сразу же" -" переходит на \"отслеживание\"." - -msgid "" -"In order to leave orphan mode you need to sync with a sufficient number " -"(:ref:`replication_connect_quorum `) of instances. To do so, you may either:" -msgstr "" -"Чтобы вывести узел из одиночного статуса, нужно синхронизировать его с " -"достаточным (т.е. равным :ref:`replication_connect_quorum `) количеством других узлов. Этого можно " -"добиться, выполнив любое из следующих действий:" - -msgid "" -"Set :ref:`replication_connect_quorum ` to a lower value." -msgstr "" -"Уменьшить значение :ref:`replication_connect_quorum `." - -msgid "" -"Reset ``box.cfg.replication`` to exclude instances that cannot be reached or" -" synced with." -msgstr "" -"Убрать из списка ``box.cfg.replication`` недоступные и прочие узлы, с " -"которыми нельзя синхронизироваться." - -msgid "Set ``box.cfg.replication`` to ``\"\"`` (empty string)." -msgstr "" -"Вообще задать ``\"\"`` (пустую строку) в качестве значения " -"``box.cfg.replication``." - -msgid "The following situations are possible." -msgstr "Возможны следующие ситуации." - -msgid "**Situation 1: bootstrap**" -msgstr "**Ситуация 1: настройка**" - -msgid "" -"Here ``box.cfg{}`` is being called for the first time. A replica is joining " -"but no replica set exists yet." -msgstr "" -"Здесь впервые происходит вызов ``box.cfg{}``. Реплика подключается, но " -"набора реплик пока нет." - -msgid "Set status to 'orphan'." -msgstr "Установка статуса 'orphan' (одиночный)." - -msgid "" -"Try to connect to all nodes from ``box.cfg.replication``, or to the number " -"of nodes required by :ref:`replication_connect_quorum `. Retrying up to 3 times in 30 seconds is " -"possible because this is bootstrap, :ref:`replication_connect_timeout " -"` is overridden." -msgstr "" -"Попытка установить соединение со всеми узлами из ``box.cfg.replication`` или" -" с количеством узлов, указанным в параметре :ref:`replication_connect_quorum" -" `. Допускаются три повторные " -"попытки за 30 секунд, поскольку идет стадия настройки, параметр " -":ref:`replication_connect_timeout ` не учитывается." - -msgid "" -"Abort and throw an error if not connected to all nodes in " -"``box.cfg.replication`` or :ref:`replication_connect_quorum " -"`." -msgstr "" -"Прекращение работы и выдача ошибки в случае отсутствия соединения со всеми " -"узлами в ``box.cfg.replication`` или :ref:`replication_connect_quorum " -"`." - -msgid "" -"This instance might be elected as the replica set 'leader'. Criteria for " -"electing a leader include vclock value (largest is best), and whether it is " -"read-only or read-write (read-write is best unless there is no other " -"choice). The leader is the master that other instances must join. The leader" -" is the master that executes :doc:`box.once() " -"` functions." -msgstr "" -"Экземпляр может быть выбран в качестве лидера 'leader' в наборе реплик. " -"Критерии выбора лидера включают в себя значение vclock (чем больше, тем " -"лучше), а также доступность только для чтения или для чтения и записи (лучше" -" всего для чтения и записи, кроме случаев, когда других вариантов нет). " -"Лидер является мастером, к которому должны подключиться другие экземпляры. " -"Лидер является мастером, который выполняет функции :doc:`box.once() " -"`." - -msgid "" -"If this instance is elected as the replica set leader, then perform an " -"\"automatic bootstrap\":" -msgstr "" -"Если данный экземпляр выбран лидером набора реплик, выполняется " -"\"самонастройка\":" - -msgid "Set status to 'running'." -msgstr "Установка статуса 'running' (запущен)." - -msgid "Return from ``box.cfg{}``." -msgstr "Возврат из ``box.cfg{}``." - -msgid "" -"Otherwise this instance will be a replica joining an existing replica set, " -"so:" -msgstr "" -"В противном случае, данный экземпляр будет репликой, которая подключается к " -"существующему набору реплик, поэтому:" - -msgid "" -"Bootstrap from the leader. See examples in section :ref:`Bootstrapping a " -"replica set `." -msgstr "" -"Настройка от лидера. См. примеры в разделе :ref:`Настройка набора реплик " -"`." - -msgid "In background, sync with all the other nodes in the replication set." -msgstr "" -"Синхронизация со всеми остальными узлами в наборе реплик в фоновом режиме." - -msgid "**Situation 2: recovery**" -msgstr "**Ситуация 2: восстановление**" - -msgid "" -"Here ``box.cfg{}`` is not being called for the first time. It is being " -"called again in order to perform recovery." -msgstr "" -"Здесь вызов ``box.cfg{}`` происходит не впервые, а повторно для " -"осуществления восстановления." - -msgid "" -"Perform :ref:`recovery ` from the last local " -"snapshot and the WAL files." -msgstr "" -"Проведение :ref:`восстановления ` из последнего " -"локального снимка и WAL-файлов." - -msgid "" -"Connect to at least :ref:`replication_connect_quorum ` nodes. If failed -- set status to 'orphan'. " -"(Attempts to sync will continue in the background and when/if they succeed " -"then 'orphan' will be changed to 'connected'.)" -msgstr "" -"Установить соединение с количеством узлов не меньшим, чем " -":ref:`replication_connect_quorum `. Если не получается -- установить статус " -"'orphan'. (Попытки синхронизации будут повторяться в фоновом режиме, и " -"когда/если они окажутся успешными, статус 'orphan' сменится на 'connected'.)" - -msgid "" -"If connected - sync with all connected nodes, until the difference is not " -"more than :ref:`replication_sync_lag `" -" seconds." -msgstr "" -"Если соединение установлено - осуществлять синхронизацию со всеми " -"подключенными узлами до тех пор, пока отличия не будут более " -":ref:`replication_sync_lag ` секунд." - -msgid "**Situation 3: configuration update**" -msgstr "**Ситуация 3: обновление конфигурации**" - -msgid "" -"Here ``box.cfg{}`` is not being called for the first time. It is being " -"called again because some replication parameter or something in the replica " -"set has changed." -msgstr "" -"Здесь вызов ``box.cfg{}`` происходит не впервые, а повторно, поскольку " -"изменились некоторые параметры репликации или что-то в наборе реплик." - -msgid "" -"Try to connect to all nodes from ``box.cfg.replication``, or to the number " -"of nodes required by :ref:`replication_connect_quorum `, within the time period specified in " -":ref:`replication_connect_timeout `." -msgstr "" -"Попытка установить соединение со всеми узлами из ``box.cfg.replication`` или" -" с количеством узлов, указанным в параметре :ref:`replication_connect_quorum" -" ` в течение периода времени, " -"указанного в :ref:`replication_connect_timeout `." - -msgid "" -"Try to sync with the connected nodes, within the time period specified in " -":ref:`replication_sync_timeout `." -msgstr "" -"Попытка синхронизации со всеми подключенными узлами в течение периода " -"времени, указанного в :ref:`replication_sync_timeout `." - -msgid "" -"If earlier steps fail, change status to 'orphan'. (Attempts to sync will " -"continue in the background and when/if they succeed then 'orphan' status " -"will end.)" -msgstr "" -"Если предыдущие шаги не выполнены, статус изменяется на 'orphan' " -"(одиночный). (Попытки синхронизации будут продолжаться в фоновом режиме, и " -"когда/если они будут успешны, статус 'orphan' отключится.)" - -msgid "" -"If earlier steps succeed, set status to 'running' (master) or 'follow' " -"(replica)." -msgstr "" -"Если предыдущие шаги выполнены, статус изменяется на 'running' (мастер) или " -"'follow' (реплика)." - -msgid "**Situation 4: rebootstrap**" -msgstr "**Ситуация 4: повторная настройка**" - -msgid "" -"Here ``box.cfg{}`` is not being called. The replica connected successfully " -"at some point in the past, and is now ready for an update from the master. " -"But the master cannot provide an update. This can happen by accident, or " -"more likely can happen because the replica is slow (its :ref:`lag " -"` is large), and the WAL (.xlog) files" -" containing the updates have been deleted. This is not crippling. The " -"replica can discard what it received earlier, and then ask for the master's " -"latest snapshot (.snap) file contents. Since it is effectively going through" -" the bootstrap process a second time, this is called \"rebootstrapping\". " -"However, there has to be one difference from an ordinary bootstrap -- the " -"replica's :ref:`replica id ` will remain the same. " -"If it changed, then the master would think that the replica is a new " -"addition to the cluster, and would maintain a record of an instance ID of a " -"replica that has ceased to exist. Rebootstrapping was introduced in " -"Tarantool version 1.10.2 and is completely automatic." -msgstr "" -"Здесь не происходит вызов ``box.cfg{}``. В определенный момент в прошлом " -"реплика успешно установила соединение и в настоящий момент ожидает " -"обновления от мастера. Однако мастер не может передать обновления, что может" -" произойти случайно, или же если реплика работает слишком медленно (большое " -"значение :ref:`lag `), а WAL-файлы " -"(.xlog) с обновлениями были удалены. Такая ситуация не является критической " -"-- реплика может сбросить ранее полученные данные, а затем запросить " -"содержание последнего файла снимка (.snap) мастера. Поскольку фактически в " -"таком случае повторно проводится процесс настройки, это называется " -"\"повторная настройка\". Тем не менее, есть отличие от обычной настройки -- " -":ref:`идентификатор реплики ` останется прежним. " -"Если он изменится, то мастер посчитает, что в кластер добавляется новая " -"реплика, и сохранит идентификатор экземпляра реплики, которой уже не " -"существует. Полностью автоматизированный процесс повторной настройки " -"появился в версии Tarantool 1.10.2." - -msgid "Server startup with replication" -msgstr "Запуск сервера с репликацией" - -msgid "" -"In addition to the recovery process described in the section :ref:`Recovery " -"process `, the server must take additional steps" -" and precautions if :ref:`replication ` is enabled." -msgstr "" -"Помимо процесса восстановления, описанного в разделе :ref:`Процесс " -"восстановления `, сервер должен предпринять " -"дополнительные шаги и меры предосторожности, если включена :ref:`репликация " -"`." - -msgid "" -"Once again the startup procedure is initiated by the ``box.cfg{}`` request. " -"One of the ``box.cfg`` parameters may be :ref:`replication ` which specifies replication source(-s). We will refer to this " -"replica, which is starting up due to ``box.cfg``, as the \"local\" replica " -"to distinguish it from the other replicas in a replica set, which we will " -"refer to as \"distant\" replicas." -msgstr "" -"И снова процедура запуска начинается с запроса ``box.cfg{}``. Одним из " -"параметров запроса ``box.cfg`` может быть :ref:`replication " -"`, в котором указываются источники репликации. " -"Реплику, которая запускается сейчас с помощью ``box.cfg``, мы будем называть" -" локальной, чтобы отличать ее от других реплик в наборе реплик, которые мы " -"будем называть удаленными." - -msgid "" -"*If there is no snapshot .snap file and the* ``replication`` *parameter is " -"empty and* ``cfg.read_only=false``: |br| then the local replica assumes it " -"is an unreplicated \"standalone\" instance, or is the first replica of a new" -" replica set. It will generate new UUIDs for itself and for the replica set." -" The replica UUID is stored in the ``_cluster`` space; the replica set UUID " -"is stored in the ``_schema`` space. Since a snapshot contains all the data " -"in all the spaces, that means the local replica's snapshot will contain the " -"replica UUID and the replica set UUID. Therefore, when the local replica " -"restarts on later occasions, it will be able to recover these UUIDs when it " -"reads the .snap file." -msgstr "" -"*Если нет файла снимка .snap и не указано значение параметра* " -"``replication`` *и* ``cfg.read_only=false``: |br| то локальная реплика " -"предполагает, что является нереплицируемым обособленным экземпляром или же " -"первой репликой в новом наборе реплик. Она сгенерирует новые UUID для себя и" -" для набора реплик. UUID реплики хранится в спейсе ``_cluster``; UUID набора" -" реплик хранится в спейсе ``_schema``. Поскольку снимок содержит все данные " -"во всех спейсах, это означает, что снимок локальной реплики будет содержать " -"UUID реплики и UUID набора реплик. Таким образом, когда локальная реплика " -"будет позднее перезапускаться, она сможет восстановить эти UUID после " -"прочтения файла снимка .snap." - -msgid "" -"*If there is no snapshot .snap file and the* ``replication`` *parameter is " -"empty and* ``cfg.read_only=true``: |br| it cannot be the first replica of a " -"new replica set because the first replica must be a master. Therefore an " -"error message will occur: ER_BOOTSTRAP_READONLY. To avoid this, change the " -"setting for this (local) instance to ``read_only = false``, or ensure that " -"another (distant) instance starts first and has the local instance's UUID in" -" its ``_cluster`` space. In the latter case, if ER_BOOTSTRAP_READONLY still " -"occurs, set the local instance's :ref:`box.replication_connect_timeout " -"` to a larger value." -msgstr "" -"*Если нет файла снимка .snap, не указано значение параметра* ``replication``" -" *и* ``cfg.read_only=true``:|br| такая реплика не может быть первой, потому " -"что первая реплика должна быть мастером. Поэтому выдастся ошибка: " -"ER_BOOTSTRAP_READONLY. Чтобы этого избежать, измените в настройке локального" -" экземпляра ``read_only`` на ``false``, или убедитесь, что удаленный " -"экземпляр запускается первым и имеет UUID локального экземпляра в спейсе " -"``_cluster``. Во втором случае, если произойдет ER_BOOTSTRAP_READONLY, " -"выставите на локальном экземпляре :ref:`box.replication_connect_timeout " -"` на большее значение." - -msgid "" -"*If there is no snapshot .snap file and the* ``replication`` *parameter is " -"not empty and the* ``_cluster`` *space contains no other replica UUIDs*: " -"|br| then the local replica assumes it is not a standalone instance, but is " -"not yet part of a replica set. It must now join the replica set. It will " -"send its replica UUID to the first distant replica which is listed in " -"``replication`` and which will act as a master. This is called the \"join " -"request\". When a distant replica receives a join request, it will send " -"back:" -msgstr "" -"*Если нет файла снимка .snap, указано значение параметра* ``replication``, " -"*а в спейсе* ``_cluster`` *отсутствуют UUID других реплик*: |br| то " -"локальная реплика предполагает, что не является обособленным экземпляром, но" -" еще не входит в набор реплик. Сейчас она должна подключиться в набор " -"реплик. Она отправит свой UUID реплики первой удаленной реплике, указанной в" -" параметре ``replication``, которая будет выступать в качестве мастера. Это " -"называется \"запрос на подключение\". Когда удаленная реплика получает " -"запрос на подключение, она отправляет в ответ:" - -msgid "the distant replica's replica set UUID," -msgstr "UUID набора реплик, в который входит удаленная реплика" - -msgid "" -"the contents of the distant replica's .snap file. |br| When the local " -"replica receives this information, it puts the replica set UUID in its " -"``_schema`` space, puts the distant replica's UUID and connection " -"information in its ``_cluster`` space, and makes a snapshot containing all " -"the data sent by the distant replica. Then, if the local replica has data in" -" its WAL .xlog files, it sends that data to the distant replica. The distant" -" replica will receive this and update its own copy of the data, and add the " -"local replica's UUID to its ``_cluster`` space." -msgstr "" -"содержимое файла снимка .snap удаленной реплики. |br| Когда локальная " -"реплика получает эту информацию, она размещает UUID набора реплики в своем " -"спейсе ``_schema``, UUID удаленной реплики и информацию о подключении в " -"своем спейсе ``_cluster``, а затем создает снимок, который содержит все " -"данные, отправленные удаленной репликой. Затем, если в WAL-файлах .xlog " -"локальной реплики содержатся данные, они отправляются на удаленную реплику. " -"Удаленная реплика получается данные и обновляет свою копию данных, а затем " -"добавляет UUID локальной реплики в свой спейс ``_cluster``." - -msgid "" -"*If there is no snapshot .snap file and the* ``replication`` *parameter is " -"not empty and the* ``_cluster`` *space contains other replica UUIDs*: |br| " -"then the local replica assumes it is not a standalone instance, and is " -"already part of a replica set. It will send its replica UUID and replica set" -" UUID to all the distant replicas which are listed in ``replication``. This " -"is called the \"on-connect handshake\". When a distant replica receives an " -"on-connect handshake: |br|" -msgstr "" -"*Если нет файла снимка .snap, указано значение параметра* ``replication``, " -"*а в спейсе* ``_cluster`` *есть UUID других реплик*: |br| то локальная " -"реплика предполагает, что не является обособленным экземпляром, и уже входит" -" в набор реплик. Она отправит свой UUID реплики и UUID набора реплик всем " -"удаленным репликам, указанным в параметре ``replication``. Это называется " -"\"подтверждение связи при подключении\". Когда удаленная реплика получает " -"подтверждение связи при подключении: |br|" - -msgid "" -"the distant replica compares its own copy of the replica set UUID to the one" -" in the on-connect handshake. If there is no match, then the handshake fails" -" and the local replica will display an error." -msgstr "" -"удаленная реплика сопоставляет свою версию UUID набора реплик с UUID, " -"переданным в ходе подтверждения связи при подключении. Если они не " -"совпадают, связь не устанавливается, и локальная реплика отобразит ошибку." - -msgid "" -"the distant replica looks for a record of the connecting instance in its " -"``_cluster`` space. If there is none, then the handshake fails. |br| " -"Otherwise the handshake is successful. The distant replica will read any new" -" information from its own .snap and .xlog files, and send the new requests " -"to the local replica." -msgstr "" -"удаленная реплика ищет запись о подключающемся экземпляре в своем спейсе " -"``_cluster``. Если такой записи нет, связь не устанавливается. |br| Если " -"есть, связь подтверждается. Удаленная реплика выполняет чтение любой новой " -"информации из своих файлов .snap и .xlog и отправляет новые запросы на " -"локальную реплику." - -msgid "" -"In the end, the local replica knows what replica set it belongs to, the " -"distant replica knows that the local replica is a member of the replica set," -" and both replicas have the same database contents." -msgstr "" -"Наконец, локальная реплика понимает, к какому набору реплик относится, " -"удаленная реплика понимает, что локальная реплика входит в набор реплик, и у" -" двух реплик одинаковое содержимое базы данных." - -msgid "" -"*If there is a snapshot file and replication source is not empty*: |br| " -"first the local replica goes through the recovery process described in the " -"previous section, using its own .snap and .xlog files. Then it sends a " -"\"subscribe\" request to all the other replicas of the replica set. The " -"subscribe request contains the server vector clock. The vector clock has a " -"collection of pairs 'server id, lsn' for every replica in the ``_cluster`` " -"system space. Each distant replica, upon receiving a subscribe request, will" -" read its .xlog files' requests and send them to the local replica if (lsn " -"of .xlog file request) is greater than (lsn of the vector clock in the " -"subscribe request). After all the other replicas of the replica set have " -"responded to the local replica's subscribe request, the replica startup is " -"complete." -msgstr "" -"*Если есть файл снимка и указан источник репликации*: |br| сначала локальная" -" реплика проходит процесс восстановления, описанный в предыдущем разделе, " -"используя свои собственные файлы .snap и .xlog. Затем она отправляет запрос " -"подписки всем репликам в наборе реплик. Запрос подписки содержит векторные " -"часы сервера. Векторные часы включают набор пар 'идентификатор сервера, LSN'" -" для каждой реплики в системном спейсе ``_cluster``. Каждая удаленная " -"реплика, получив запрос подписки, выполняет чтение запросов из файла .xlog и" -" отправляет их на локальную реплику, если LSN из запроса файла .xlog больше," -" чем LSN векторных часов из запроса подписки. После того, как все реплики из" -" набора реплик отправили ответ на запрос подписки локальной реплики, запуск " -"реплики завершен." - -msgid "" -"The following temporary limitations applied for Tarantool versions earlier " -"than 1.7.7:" -msgstr "" -"Следующие временные ограничения применимы к версиям Tarantool ниже 1.7.7:" - -msgid "" -"The URIs in the ``replication`` parameter should all be in the same order on" -" all replicas. This is not mandatory but is an aid to consistency." -msgstr "" -"URI в параметре ``replication`` должны быть указаны в одинаковом порядке на " -"всех репликах. Это необязательно, но помогает соблюдать консистентность." - -msgid "" -"The replicas of a replica set should be started up at slightly different " -"times. This is not mandatory but prevents a situation where each replica is " -"waiting for the other replica to be ready." -msgstr "" -"Реплики в наборе реплик должны запускаться не одновременно. Это " -"необязательно, но помогает избежать ситуации, когда все реплики ждут " -"готовности друг друга." - -msgid "" -"The following limitation still applies for the current Tarantool version:" -msgstr "Следующее ограничение всё еще применимо к текущей версии Tarantool:" - -msgid "" -"The maximum number of entries in the ``_cluster`` space is :ref:`32 " -"`. Tuples for out-of-date replicas are not " -"automatically re-used, so if this 32-replica limit is reached, users may " -"have to reorganize the ``_cluster`` space manually." -msgstr "" -"Максимальное количество записей в спейсе ``_cluster`` -- :ref:`32 " -"`. Кортежи для устаревших реплик не переиспользуются " -"автоматически, поэтому по достижении предела в 32 реплики, может " -"понадобиться реорганизация спейса ``_cluster`` вручную." diff --git a/locale/ru/LC_MESSAGES/book/replication/repl_leader_elect.po b/locale/ru/LC_MESSAGES/book/replication/repl_leader_elect.po deleted file mode 100644 index 58b1de41bc..0000000000 --- a/locale/ru/LC_MESSAGES/book/replication/repl_leader_elect.po +++ /dev/null @@ -1,379 +0,0 @@ - -msgid "Automated leader election" -msgstr "Автоматические выборы лидера" - -msgid "" -"Starting from version :doc:`2.6.1 `, Tarantool has the " -"built-in functionality managing automated *leader election* in a replica " -"set. This functionality increases the fault tolerance of the systems built " -"on the base of Tarantool and decreases dependency on the external tools for " -"replica set management." -msgstr "" -"В Tarantool, начиная с версии :doc:`2.6.1 `, есть встроенная" -" функциональность для управления автоматическими *выборами лидера* " -"(automated leader election) в наборе реплик (replica set). Эта " -"функциональность повышает отказоустойчивость систем на базе Tarantool и " -"снижает зависимость от внешних инструментов для управления набором реплик." - -msgid "The following topics are described below:" -msgstr "Ниже описаны следующие темы:" - -msgid "Leader election and synchronous replication" -msgstr "Выборы лидера и синхронная репликация" - -msgid "" -"Leader election and synchronous replication are implemented in Tarantool as " -"a modification of the `Raft " -"`__ algorithm. Raft " -"is an algorithm of synchronous replication and automatic leader election. " -"Its complete description can be found in the `corresponding document " -"`_." -msgstr "" -"В Tarantool используется модификация `Raft " -"`__ — алгоритма " -"синхронной репликации и автоматических выборов лидера. Полное описание " -"алгоритма Raft можно прочитать `в соответствующем документе " -"`_." - -msgid "" -"In Tarantool, :ref:`synchronous replication ` and leader election" -" are supported as two separate subsystems. So it is possible to get " -"synchronous replication but use an alternative algorithm for leader " -"election. And vice versa -- elect a leader in the cluster but don't use " -"synchronous spaces at all. Synchronous replication has a separate " -":ref:`documentation section `. Leader election is described " -"below." -msgstr "" -":ref:`Синхронная репликация ` и выборы лидера в Tarantool " -"реализованы как две независимые подсистемы. Это означает, что можно " -"настроить синхронную репликацию, а для выборов лидера использовать " -"альтернативный алгоритм. Встроенный механизм выборов лидера, в свою очередь," -" не требует использования синхронных спейсов. Синхронной репликации посвящен" -" :ref:`этот раздел документации `. Процесс выборов лидера описан " -"ниже." - -msgid "Leader election process" -msgstr "Процесс выборов лидера" - -msgid "" -"Automated leader election in Tarantool helps guarantee that there is at most" -" one leader at any given moment of time in a replica set. A *leader* is a " -"writable node, and all other nodes are non-writable -- they accept read-only" -" requests exclusively." -msgstr "" -"Автоматические выборы лидера в Tarantool гарантируют, что в каждый момент " -"времени в наборе реплик будет максимум один *лидер* — узел, доступный для " -"записи. Все остальные узлы будут принимать исключительно запросы на чтение." - -msgid "" -"When :ref:`the election is enabled `, the life " -"cycle of a replica set is divided into so-called *terms*. Each term is " -"described by a monotonically growing number. After the first boot, each node" -" has its term equal to 1. When a node sees that it is not a leader and there" -" is no leader available for some time in the replica set, it increases the " -"term and starts a new leader election round." -msgstr "" -"Когда :ref:`функция выборов включена `, жизненный " -"цикл набора реплик разделен на так называемые *термы* (term). Каждый терм " -"описывается монотонно растущим числом. После первой загрузки узла значение " -"его терма равно 1. Когда узел обнаруживает, что не является лидером и при " -"этом лидера в наборе реплик уже какое-то время нет, он увеличивает значение " -"своего терма и начинает новый тур выборов." - -msgid "" -"Leader election happens via votes. The node which started the election votes" -" for itself and sends vote requests to other nodes. Upon receiving vote " -"requests, a node votes for the first of them, and then cannot do anything in" -" the same term but wait for a leader being elected." -msgstr "" -"Выборы лидера происходят посредством голосования. Узел, начинающий выборы, " -"голосует сам за себя и отправляет другим запросы на голос. Каждый экземпляр " -"голосует за первый узел, от которого пришел такой запрос, и далее в течение " -"всего терма ожидает избрания лидера, не выполняя никаких действий." - -msgid "" -"The node that collected a :ref:`quorum of votes ` " -"becomes the leader and notifies other nodes about that. Also, a split vote " -"can happen when no nodes received a quorum of votes. In this case, after a " -":ref:`random timeout `, each node increases its " -"term and starts a new election round if no new vote request with a greater " -"term arrives during this time period. Eventually, a leader is elected." -msgstr "" -"Узел, собравший :ref:`кворум голосов `, становится" -" лидером и оповещает об этом другие узлы. Голоса могут разделиться, если ни " -"один узел не получит кворума. В этом случае спустя :ref:`случайное время " -"` происходят перевыборы: каждый узел увеличивает " -"значение терма и начинает новый тур, если за период ожидания не получил " -"запроса на голос от узла, чей терм больше. В итоге определяется лидер " -"кластера." - -msgid "" -"All the non-leader nodes are called *followers*. The nodes that start a new " -"election round are called *candidates*. The elected leader sends heartbeats " -"to the non-leader nodes to let them know it is alive. So if there are no " -"heartbeats for a period set by the :ref:`replication_timeout " -"` option, a new election starts. Terms " -"and votes are persisted by each instance in order to preserve certain Raft " -"guarantees." -msgstr "" -"Узлы, не являющиеся лидерами, называются *последователями* (followers). " -"Узлы, которые начинают новый тур выборов, называются *кандидатами* " -"(candidates). Избранный лидер отправляет остальным узлам контрольные сигналы" -" (heartbeats), оповещая о том, что он работает (alive). Если контрольные " -"сигналы не приходят в течение времени, заданного параметром " -":ref:`replication_timeout `, начинаются" -" новые выборы. Чтобы алгоритм Raft гарантированно выполнялся, термы и голоса" -" сохраняются на каждом экземпляре." - -msgid "" -"During the election, the nodes prefer to vote for those ones that have the " -"newest data. So as if an old leader managed to send something before its " -"death to a quorum of replicas, that data wouldn't be lost." -msgstr "" -"При голосовании узлы отдают предпочтение экземплярам, где сохранены самые " -"новые данные. Поэтому, если прежний лидер перед тем, как стать недоступным, " -"отправит кворуму реплик какую-либо информацию, она не будет потеряна." - -msgid "" -"When :ref:`election is enabled `, there must be " -"connections between each node pair so as it would be the full mesh topology." -" This is needed because election messages for voting and other internal " -"things need direct connection between the nodes." -msgstr "" -"Необходимо, чтобы все узлы, :ref:`включенные в процесс выборов " -"`, были соединены попарно и образовывали полную " -"ячеистую топологию (full mesh). Для передачи запросов, связанных с " -"голосованием, и других внутренних сообщений требуется прямая связь между " -"узлами." - -msgid "" -"Also, if election is enabled on the node, it won't replicate from any nodes " -"except the newest leader. This is done to avoid the issue when a new leader " -"is elected, but the old leader has somehow survived and tries to send more " -"changes to the other nodes." -msgstr "" -"Любой узел, участвующий в процессе выборов, реплицирует данные только с " -"последнего избранного лидера. Это позволяет избежать ситуации, в которой " -"прежний лидер после выборов нового все еще пытается отправлять изменения на " -"реплики." - -msgid "" -"Term numbers also work as a kind of a filter. For example, you can be sure " -"that if election is enabled on two nodes and ``node1`` has the term number " -"less than ``node2``, then ``node2`` won't accept any transactions from " -"``node1``." -msgstr "" -"Числовые значения термов также выполняют функцию своеобразного фильтра. " -"Например, если на двух узлах включена функция выборов и значение терма " -"``node1`` меньше значения терма ``node2``, то узел ``node2`` не будет " -"принимать транзакций от узла ``node1``." - -msgid "Configuration" -msgstr "Настройка" - -msgid "" -"box.cfg({\n" -" election_mode = ,\n" -" election_timeout = ,\n" -" replication_timeout = ,\n" -" replication_synchro_quorum = ,\n" -"})" -msgstr "" -"box.cfg({\n" -" election_mode = ,\n" -" election_timeout = ,\n" -" replication_timeout = ,\n" -" replication_synchro_quorum = ,\n" -"})" - -msgid "" -"``election_mode`` -- specifies the role of a node in the leader election " -"process. For the details, refer to the :ref:`option description " -"` in the configuration reference." -msgstr "" -"``election_mode`` — определяет роль узла в процессе выборов лидера. " -"Подробное :ref:`описание параметра ` " -"приводится в справочнике по настройке." - -msgid "" -"``election_timeout`` -- specifies the timeout between election rounds if the" -" previous round ended up with a split vote. For the details, refer to the " -":ref:`option description ` in the " -"configuration reference." -msgstr "" -"``election_timeout`` — задает промежуток времени между турами в случае " -"разделения голосов и последующих перевыборов. Подробное :ref:`описание " -"параметра ` приводится в справочнике по " -"настройке." - -msgid "" -"``replication_timeout`` -- reuse of the :ref:`replication_timeout " -"` configuration option for the purpose " -"of the leader election process. Heartbeats sent by an active leader have a " -"timeout after which a new election starts. Heartbeats are sent once per " -" seconds. Default value is ``1``. The leader is " -"considered dead if it hasn't sent any heartbeats for the period of " -"`` * 4``." -msgstr "" -"``replication_timeout`` — параметр репликации :ref:`replication_timeout " -"`, используемый для выборов лидера. " -"Активный лидер отправляет сообщения контрольного сигнала каждые " -" секунд. Значение параметра по умолчанию — ``1``. Если " -"лидер не отправляет сообщений контрольного сигнала в течение " -"`` * 4`` секунд, он считается недоступным (dead) и " -"начинаются новые выборы." - -msgid "" -"``replication_synchro_quorum`` -- reuse of the " -":ref:`replication_synchro_quorum ` option for the purpose of configuring the " -"election quorum. The default value is ``1``, meaning that each node becomes " -"a leader immediately after voting for itself. It is the best to set up this " -"option value to the ``( / 2) + 1``. Otherwise, there is no " -"guarantee that there is only one leader at a time." -msgstr "" -"``replication_synchro_quorum`` — параметр репликации " -":ref:`replication_synchro_quorum `, используемый для настройки кворума. Значение " -"по умолчанию — ``1``, то есть каждый узел, проголосовав за себя, немедленно " -"становится лидером. Лучше всего задать этому параметру значение ``(<размер " -"кластера> / 2) + 1``. В противном случае нет гарантий, что в каждый момент " -"времени в кластере будет только один лидер." - -msgid "" -"Besides, it is important to know that being a leader is not the only " -"requirement for a node to be writable. A leader node should have its " -":ref:`read_only ` option set to ``false`` " -"(``box.cfg{read_only = false}``), and its :ref:`connectivity quorum " -"` should be satisfied " -"(``box.cfg{replication_connect_quorum = }``) or disabled " -"(``box.cfg{replication_connect_quorum = 0}``)." -msgstr "" -"Важно также понимать, что статус лидера — не единственное, что требуется " -"узлу, чтобы быть доступным для записи. Параметр :ref:`read_only ` на узле-лидере должен иметь значение ``false`` " -"(``box.cfg{read_only = false}``). Необходимо также, чтобы выполнялось " -"условие, заданное параметром :ref:`replication_connect_quorum " -"` " -"(``box.cfg{replication_connect_quorum = }``), или же этот параметр " -"должен быть отключен (``box.cfg{replication_connect_quorum = 0}``)." - -msgid "" -"Nothing prevents from setting the ``read_only`` option to ``true``, but the " -"leader just won't be writable then. The option doesn't affect the election " -"process itself, so a read-only instance can still vote and become a leader." -msgstr "" -"Ничто не мешает задать для параметра ``read_only`` значение ``true``, но это" -" сделает лидера недоступным для записи. На сам процесс выборов параметр " -"никак не влияет, поэтому голосовать и быть лидером может даже экземпляр, " -"доступный только для чтения." - -msgid "Monitoring" -msgstr "Мониторинг" - -msgid "" -"To monitor the current state of a node regarding the leader election, you " -"can use the ``box.info.election`` function. For details, refer to the " -":doc:`function description `." -msgstr "" -"Чтобы отслеживать текущий статус узла в выборах лидера, можно использовать " -"функцию ``box.info.election``. Подробные сведения читайте в :doc:`описании " -"функции `." - -msgid "**Example:**" -msgstr "**Пример:**" - -msgid "" -"tarantool> box.info.election\n" -"---\n" -"- state: follower\n" -" vote: 0\n" -" leader: 0\n" -" term: 1\n" -"..." -msgstr "" -"tarantool> box.info.election\n" -"---\n" -"- state: follower\n" -" vote: 0\n" -" leader: 0\n" -" term: 1\n" -"..." - -msgid "" -"The Raft-based election implementation logs all its actions with the " -"``RAFT:`` prefix. The actions are new Raft message handling, node state " -"changing, voting, term bumping, and so on." -msgstr "" -"Журнальные записи о выборах на основе алгоритма Raft отмечаются префиксом " -"``RAFT:``. В журнал вносятся такие события, как обработка новых сообщений " -"Raft, изменение статуса узла, голосование, увеличение значения терма и пр." - -msgid "Important notes" -msgstr "Важные замечания" - -msgid "" -"Leader election won't work correctly if the election quorum is set to less " -"or equal than `` / 2`` because in that case, a split vote can " -"lead to a state when two leaders are elected at once." -msgstr "" -"Механизм выборов лидера не будет корректно работать, если кворум меньше " -"``<размер кластера> / 2`` или равен этому значению, поскольку в этом случае " -"два лидера могут быть избраны одновременно." - -msgid "" -"For example, let's assume there are five nodes. When quorum is set to ``2``," -" ``node1`` and ``node2`` can both vote for ``node1``. ``node3`` and " -"``node4`` can both vote for ``node5``. In this case, ``node1`` and ``node5``" -" both win the election. When the quorum is set to the cluster majority, that" -" is ``( / 2) + 1`` or bigger, the split vote is not possible." -msgstr "" -"Допустим, есть пять узлов. Если значение кворума — ``2``, то ``node1`` и " -"``node2`` оба могут проголосовать за ``node1``. При этом ``node3`` и " -"``node4`` оба могут проголосовать за ``node5``. Тогда выборы выиграют и " -"``node1``, и ``node5``. Но если в качестве значения кворума установлено " -"большинство, то есть ``(<размер кластера> / 2) + 1`` или больше, то " -"разделение голосов поровну невозможно." - -msgid "" -"That should be considered when adding new nodes. If the majority value is " -"changing, it's better to update the quorum on all the existing nodes before " -"adding a new one." -msgstr "" -"Это особенно актуально при добавлении узлов в кластер. Прежде чем вводить " -"новый узел, рекомендуется обновить значение кворума на всех существующих " -"экземплярах." - -msgid "" -"Also, the automated leader election won't bring many benefits in terms of " -"data safety when used *without* :ref:`synchronous replication `. " -"If the replication is asynchronous and a new leader gets elected, the old " -"leader is still active and considers itself the leader. In such case, " -"nothing stops it from accepting requests from clients and making " -"transactions. Non-synchronous transactions will be successfully committed " -"because they won't be checked against the quorum of replicas. Synchronous " -"transactions will fail because they won't be able to collect the quorum -- " -"most of the replicas will reject these old leader's transactions since it is" -" not a leader anymore." -msgstr "" -"Если использовать автоматические выборы лидера *без* :ref:`синхронной " -"репликации `, может наступить рассогласование данных. При " -"асинхронной репликации успешные выборы нового лидера не означают, что " -"прежний лидер немедленно сложит с себя полномочия. Он по-прежнему будет " -"считать себя активным лидером, принимать запросы от клиентов и совершать " -"транзакции. Асинхронные транзакции, минуя кворум реплик, будут успешно " -"проходить коммиты. При этом синхронные транзакции будут приводить к ошибке, " -"поскольку для их коммита не удастся собрать кворум: большинство реплик будут" -" отвергать транзакции, передаваемые прежним лидером, поскольку уже был " -"избран новый." - -msgid "" -"Another point to keep in mind is that when a new leader is elected, it won't" -" automatically finalize synchronous transactions left from the previous " -"leader. This must be done manually using the :ref:`box.ctl.promote ` function. In the future, it is going to be done automatically." -msgstr "" -"Кроме того, синхронные транзакции, оставшиеся от прежнего лидера, не " -"финализируются автоматически при выборах нового. Финализацию следует " -"выполнять вручную с помощью функции :ref:`box.ctl.promote `. В будущих релизах финализация станет автоматической." diff --git a/locale/ru/LC_MESSAGES/book/replication/repl_sync.po b/locale/ru/LC_MESSAGES/book/replication/repl_sync.po deleted file mode 100644 index 8ae18b506f..0000000000 --- a/locale/ru/LC_MESSAGES/book/replication/repl_sync.po +++ /dev/null @@ -1,311 +0,0 @@ - -msgid "Synchronous replication" -msgstr "Синхронная репликация" - -msgid "Overview" -msgstr "Общие сведения" - -msgid "" -"By default, replication in Tarantool is **asynchronous**: if a transaction " -"is committed locally on a master node, it does not mean it is replicated " -"onto any replicas. If a master responds success to a client and then dies, " -"after failover to a replica, from the client's point of view the transaction" -" will disappear." -msgstr "" -"По умолчанию репликация в Tarantool **асинхронная**: локальный коммит " -"транзакции на мастере не означает, что эта транзакция будет сразу же " -"выполнена на репликах. Если мастер сообщит клиенту об успешном выполнении " -"операции, а потом прекратит работу и после отказа восстановится на реплике, " -"то с точки зрения клиента транзакция пропадет." - -msgid "" -"**Synchronous** replication exists to solve this problem. Synchronous " -"transactions are not considered committed and are not responded to a client " -"until they are replicated onto some number of replicas." -msgstr "" -"Эту проблему решает **синхронная** репликация. Каждая синхронная транзакция " -"проходит коммит лишь после репликации на некотором количестве экземпляров, и" -" только тогда клиенту приходит ответ о завершении транзакции." - -msgid "Usage" -msgstr "Использование" - -msgid "" -"Since version :doc:`2.5.1 `, synchronous replication can be " -"enabled per-space by using the ``is_sync`` option:" -msgstr "" -"Начиная с версии Tarantool :doc:`2.5.1 `, синхронную " -"репликацию можно включать для отдельных спейсов, используя параметр " -"``is_sync``:" - -msgid "box.schema.create_space('test1', {is_sync = true})" -msgstr "box.schema.create_space('test1', {is_sync = true})" - -msgid "" -"Any transaction doing a DML request on this space becomes synchronous. " -"Notice that DDL on this space (including truncation) is **not** synchronous." -msgstr "" -"Все транзакции, где выполняются DML-запросы к такому спейсу, становятся " -"синхронными. Обратите внимание, что транзакции, где содержатся DDL-операции," -" в том числе запросы на очистку (truncate), синхронными **не будут**." - -msgid "" -"To control the behavior of synchronous transactions, there exist global " -"``box.cfg`` :ref:`options `:" -msgstr "" -"Управлять поведением синхронных транзакций можно с помощью глобальных " -":ref:`параметров ` ``box.cfg``:" - -msgid "box.cfg{replication_synchro_quorum = }" -msgstr "box.cfg{replication_synchro_quorum = <количество экземпляров>}" - -msgid "" -"This option tells how many replicas should confirm the receipt of a " -"synchronous transaction before it is committed. Since version :doc:`2.10.0 `, " -"this option does not account for anonymous replicas. As a usage example, consider " -"this:" -msgstr "" -"Параметр указывает, сколько реплик должно подтвердить получение синхронной " -"транзакции, прежде чем она пройдет коммит. Начиная с версии :doc:`2.10.0 `, " -"анонимные реплики не учитываются. Пример:" - -msgid "" -"-- Instance 1\n" -"box.cfg{\n" -" listen = 3313,\n" -" replication_synchro_quorum = 2,\n" -"}\n" -"box.schema.user.grant('guest', 'super')\n" -"_ = box.schema.space.create('sync', {is_sync=true})\n" -"_ = _:create_index('pk')" -msgstr "" -"-- Экземпляр 1\n" -"box.cfg{\n" -" listen = 3313,\n" -" replication_synchro_quorum = 2,\n" -"}\n" -"box.schema.user.grant('guest', 'super')\n" -"_ = box.schema.space.create('sync', {is_sync=true})\n" -"_ = _:create_index('pk')" - -msgid "" -"-- Instance 2\n" -"box.cfg{\n" -" listen = 3314,\n" -" replication = 'localhost:3313'\n" -"}" -msgstr "" -"-- Экземпляр 2\n" -"box.cfg{\n" -" listen = 3314,\n" -" replication = 'localhost:3313'\n" -"}" - -msgid "" -"-- Instance 1\n" -"box.space.sync:replace{1}" -msgstr "" -"-- Экземпляр 1\n" -"box.space.sync:replace{1}" - -msgid "" -"When the first instance makes ``replace()``, it won't finish until the " -"second instance confirms its receipt and successful appliance. Note that the" -" quorum is set to 2, but the transaction was still committed even though " -"there is only one replica. This is because the master instance itself also " -"participates in the quorum." -msgstr "" -"Операция ``replace()``, вызванная на первом экземпляре, не будет " -"завершена, пока второй экземпляр не подтвердит получение и успешное " -"применение транзакции. Обратите внимание, что кворум равен 2, а реплика " -"одна, но транзакция все же успешно проходит коммит. Это происходит " -"потому, что мастер также участвует в кворуме." - -msgid "" -"Now, if the second instance is down, the first one won't be able to commit " -"any synchronous change." -msgstr "" -"Если второй экземпляр прекратит работу, первый не сможет выполнять коммиты " -"для синхронных изменений." - -msgid "" -"-- Instance 2\n" -"Ctrl+D" -msgstr "" -"-- Экземпляр 2\n" -"Ctrl+D" - -msgid "" -"-- Instance 1\n" -"tarantool> box.space.sync:replace{2}\n" -"---\n" -"- error: Quorum collection for a synchronous transaction is timed out\n" -"..." -msgstr "" -"-- Экземпляр 1\n" -"tarantool> box.space.sync:replace{2}\n" -"---\n" -"- error: Quorum collection for a synchronous transaction is timed out\n" -"..." - -msgid "" -"The transaction wasn't committed because it failed to achieve the quorum in " -"the given time. The time is a second configuration option:" -msgstr "" -"Транзакция не прошла коммит, поскольку за определенное время не был набран " -"кворум. Время — ещё один параметр конфигурации:" - -msgid "" -"box.cfg{replication_synchro_timeout = }" -msgstr "" -"box.cfg{replication_synchro_timeout = <время в секундах; может иметь тип " -"float>}" - -msgid "" -"It tells how many seconds to wait for a synchronous transaction quorum " -"replication until it is declared failed and is rolled back." -msgstr "" -"Параметр указывает, сколько секунд синхронная транзакция будет ожидать " -"репликации на кворуме. По истечении этого времени транзакция будет отменена." - -msgid "" -"A successful synchronous transaction commit is persisted in the WAL as a " -"special CONFIRM record. The rollbacks are similarly persisted with a " -"ROLLBACK record." -msgstr "" -"Успешные коммиты синхронных транзакций персистентно сохраняются в журнал " -"упреждающей записи (WAL) в виде особых записей CONFIRM. Сообщения об отмене " -"транзакций сохраняются аналогичным образом в виде записей ROLLBACK." - -msgid "" -"The ``timeout`` and ``quorum`` options are not used on replicas. It means if" -" the master dies, the pending synchronous transactions will be kept waiting " -"on the replicas until a new master is elected." -msgstr "" -"Параметры ``timeout`` и ``quorum`` на репликах не используются. Если мастер " -"прекратит работу, синхронные транзакции, которые находятся в обработке на " -"репликах, будут ожидать выборов нового мастера." - -msgid "Synchronous and asynchronous transactions" -msgstr "Синхронные и асинхронные транзакции" - -msgid "" -"A killer feature of Tarantool's synchronous replication is its being *per-" -"space*. So, if you need it only rarely for some critical data changes, you " -"won't pay for it in performance terms." -msgstr "" -"В Tarantool синхронную репликацию можно настроить для отдельных спейсов. Эта" -" удобная функция позволит вам не потерять в производительности, если " -"синхронная репликация нужна вам лишь изредка для изменения критически важных" -" данных." - -msgid "" -"When there is more than one synchronous transaction, they all wait for being" -" replicated. Moreover, if an asynchronous transaction appears, it will also " -"be blocked by the existing synchronous transactions. This behavior is very " -"similar to a regular queue of asynchronous transactions because all the " -"transactions are committed in the same order as they make the " -"``box.commit()`` call. So, here comes **the commit rule**: transactions are " -"committed in the same order as they make the ``box.commit()`` " -"call—regardless of being synchronous or asynchronous." -msgstr "" -"Если наряду с несколькими синхронными транзакциями, ожидающими репликации, " -"совершается асинхронная транзакция, она блокируется синхронными. Коммиты при" -" этом выполняются в той последовательности, в которой для каждой из " -"транзакций вызывается метод ``box.commit()``. Похожим образом работает " -"обычная очередь асинхронных транзакций. Можно сформулировать **правило " -"коммитов**: порядок коммитов соответствует порядку вызова ``box.commit()`` " -"для каждой из транзакций, независимо от того, синхронные транзакции или " -"асинхронные." - -msgid "" -"If one of the waiting synchronous transactions times out and is rolled back," -" it will first roll back all the newer pending transactions. Again, just " -"like how asynchronous transactions are rolled back when WAL write fails. So," -" here comes **the rollback rule:** transactions are always rolled back in " -"the order reversed from the one they make the ``box.commit()`` " -"call—regardless of being synchronous or asynchronous." -msgstr "" -"Если для одной из синхронных транзакций истечет время ожидания, эта " -"транзакция будет отменена, а вместе с ней и все последующие транзакции в " -"очереди на репликацию. Похожим образом отменяются и асинхронные транзакции " -"при ошибке записи в WAL. Действует **правило отмены**: транзакции отменяются" -" в порядке, обратном порядку вызова ``box.commit()`` для каждой из них, " -"независимо от того, синхронные транзакции или асинхронные." - -msgid "" -"One more important thing is that if an asynchronous transaction is blocked " -"by a synchronous transaction, it does not become synchronous as well. This " -"just means it will wait for the synchronous transaction to be committed. But" -" once it is done, the asynchronous transaction will be committed " -"immediately—it won't wait for being replicated itself." -msgstr "" -"Асинхронная транзакция, заблокированная синхронной, не становится сама " -"синхронной, а просто ожидает коммита синхронной транзакции. Как только это " -"произойдет, асинхронная транзакция сразу сможет пройти коммит, не ожидая " -"репликации." - -msgid "Limitations and known problems" -msgstr "Ограничения и известные проблемы" - -msgid "" -"Until version :doc:`2.5.2 `, there was no way to enable " -"synchronous replication for existing spaces, but since 2.5.2 it can be " -"enabled by :ref:`space_object:alter({is_sync = true}) `." -msgstr "" -"До версии :doc:`2.5.2 ` способа настроить синхронную " -"репликацию для существующих спейсов не было. Однако, начиная с версии 2.5.2," -" ее можно включить, вызвав метод :ref:`space_object:alter({is_sync = true}) " -"`." - -msgid "" -"Synchronous transactions work only for master-slave topology. You can have " -"multiple replicas, anonymous replicas, but only one node can make " -"synchronous transactions." -msgstr "" -"Синхронные транзакции работают исключительно в топологии \"мастер-реплика\"." -" В кластере может быть несколько реплик, в том числе анонимных, однако " -"синхронные транзакции должен совершать только один узел." - -msgid "" -"Since Tarantool :doc:`2.10.0 `, anonymous replicas " -"do not participate in the quorum." -msgstr "" -"Начиная с версии Tarantool :doc:`2.10.0 `, анонимные реплики не участвуют в кворуме." - -msgid "Leader election" -msgstr "Выборы лидера" - -msgid "" -"Starting from version :doc:`2.6.1 `, Tarantool has the " -"built-in functionality managing automated leader election in a replica set. " -"For more information, refer to the :ref:`corresponding chapter " -"`." -msgstr "" -"В Tarantool, начиная с версии :doc:`2.6.1 `, есть встроенная" -" функциональность для управления автоматическими выборами лидера (automated " -"leader election) в наборе реплик. Подробности можно найти в " -":ref:`соответствующей главе `." - -msgid "Tips and tricks" -msgstr "Полезные советы" - -msgid "" -"If a transaction is rolled back, it does not mean the ROLLBACK message " -"reached the replicas. It still can happen that the master node suddenly " -"dies, so the transaction will be committed by the new master. Your " -"application logic should be ready for that." -msgstr "" -"Если транзакция была отменена, это не обязательно значит, что реплики " -"получили сообщение ROLLBACK. Может возникнуть ситуация, когда мастер " -"внезапно прекратит работу, а после этого коммит транзакции будет выполнен " -"новым мастером. Учитывайте это в логике вашего приложения." - -msgid "" -"Synchronous transactions are better to use with full mesh. Then the replicas" -" can talk to each other in case of the master node's death and still confirm" -" some pending transactions." -msgstr "" -"Синхронные транзакции лучше всего использовать в кластерах с полноячеистой " -"топологией (full mesh). В этом случае реплики смогут общаться друг с другом " -"и подтверждать некоторые транзакции, даже если откажет мастер." diff --git a/locale/ru/LC_MESSAGES/book/box/atomic.po b/locale/ru/LC_MESSAGES/concepts/atomic.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/box/atomic.po rename to locale/ru/LC_MESSAGES/concepts/atomic.po diff --git a/locale/ru/LC_MESSAGES/concepts/data_model/index.po b/locale/ru/LC_MESSAGES/concepts/data_model/index.po new file mode 100644 index 0000000000..e5f625bae9 --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/data_model/index.po @@ -0,0 +1,12 @@ + +msgid "Data model" +msgstr "Модель данных" + +msgid "" +"If you tried to create a database as suggested in our :ref:`basic " +"tutorial `, then your test database now looks" +" like this:" +msgstr "" +"Если вы пробовали создать базу данных, как предлагается в упражнениях в " +":ref:`базовом практическом руководстве `, то ваша тестовая" +" база данных выглядит следующим образом:" diff --git a/locale/ru/LC_MESSAGES/book/box/indexes.po b/locale/ru/LC_MESSAGES/concepts/data_model/indexes.po similarity index 61% rename from locale/ru/LC_MESSAGES/book/box/indexes.po rename to locale/ru/LC_MESSAGES/concepts/data_model/indexes.po index d965034ef3..7a923d7112 100644 --- a/locale/ru/LC_MESSAGES/book/box/indexes.po +++ b/locale/ru/LC_MESSAGES/concepts/data_model/indexes.po @@ -2,6 +2,13 @@ msgid "Indexes" msgstr "Индексы" +msgid "" +"Read the full information about indexes on page :doc:`Indexes " +"`." +msgstr "" +"Всю информацию про индексы можно найти на странице :doc:`Индексы " +"`." + msgid "" "An **index** is a special data structure that stores a group of key values " "and pointers. It is used for efficient manipulations with data." @@ -11,21 +18,36 @@ msgstr "" "управления данными." msgid "" -"As with spaces, you should specify the index **name**, and let Tarantool " -"come up with a unique **numeric identifier** (\"index id\")." +"As with spaces, you should specify the index **name** and let Tarantool come" +" up with a unique **numeric identifier** (\"index id\")." +msgstr "" +"Как и для спейсов, для индексов следует указать **имена**, а Tarantool " +"определит уникальный **числовой идентификатор** (\"ID индекса\")." + +msgid "" +"An index always has a **type**. The default index type is :ref:`TREE " +"`. TREE indexes are provided by all Tarantool engines, can " +"index unique and non-unique values, support partial key searches, " +"comparisons, and ordered results. Additionally, the memtx engine supports " +":ref:`HASH `, :ref:`RTREE ` and :ref:`BITSET " +"` indexes." msgstr "" -"Как и для спейсов, индексам следует указать **имена**, а Tarantool определит" -" уникальный **числовой идентификатор** (\"ID индекса\")." +"У индекса всегда есть определенный **тип**. Тип индекса по умолчанию — " +":ref:`TREE `. TREE-индексы поддерживаются обоими движками " +"Tarantool, могут индексировать уникальные и неуникальные значения, " +"поддерживают поиск по компонентам ключа, сравнение ключей и упорядочивание " +"результатов. Движок memtx поддерживает и другие типы индексов: :ref:`HASH " +"`, :ref:`RTREE ` и :ref:`BITSET `." msgid "" "An index may be **multi-part**, that is, you can declare that an index key " "value is composed of two or more fields in the tuple, in any order. For " "example, for an ordinary TREE index, the maximum number of parts is 255." msgstr "" -"Индекс может быть **составным** (multi-part), то есть можно объявить, что " -"ключ индекса состоит из двух или более полей в кортеже в любом порядке. " -"Например, для обычного TREE-индекса максимальное количество частей равно " -"255." +"Индекс может быть **многокомпонентным**, то есть можно объявить, что ключ " +"индекса состоит из двух или более полей в кортеже в любом порядке. Например," +" для обычного TREE-индекса максимальное количество частей равно 255." msgid "" "An index may be **unique**, that is, you can declare that it would be " @@ -39,10 +61,9 @@ msgid "" "it must be unique. All other indexes are called **secondary indexes**, and " "they may be non-unique." msgstr "" -"Первый индекс, определенный для спейса, называется **первичный индекс** " -"(primary key). Он должен быть уникальным. Все остальные индексы называются " -"**вторичными индексами** (secondary), они могут строиться по неуникальным " -"значениям." +"Первый индекс, определенный для спейса, называется **первичный индекс**. Он " +"должен быть уникальным. Все остальные индексы называются **вторичными " +"индексами**, они могут строиться по неуникальным значениям." msgid "" "Indexes have certain limitations. See details on page :doc:`Limitations " @@ -51,409 +72,175 @@ msgstr "" "На индексы распространяются определенные ограничения. Более подробную " "информацию см. на странице :doc:`Ограничения `." -msgid "Creating an index" -msgstr "Создание индекса" +msgid "Indexed field types" +msgstr "Типы индексированных полей" msgid "" -"It is mandatory to create an index for a space before trying to insert " -"tuples into the space, or select tuples from the space." +"Not to be confused with :ref:`index types ` -- the types of the data structure that is an index. " +"See more about index types :ref:`below `." msgstr "" -"Перед тем, как вставлять кортежи в спейс или выбирать из него кортежи, нужно" -" обязательно создать индекс для этого спейса." +"Типы полей не следует путать с :ref:`типами индексов ` как структур данных. " +"О типах индексов можно прочитать :ref:`ниже `." msgid "" -"The simple :doc:`index-creation " -"` operation is:" +"Indexes restrict values that Tarantool can store with MsgPack. This is why, " +"for example, ``'unsigned'`` and ``'integer'`` are different field types, " +"although in MsgPack they are both stored as integer values. An " +"``'unsigned'`` index contains only *non-negative* integer values, while an " +"``‘integer’`` index contains *any* integer values." msgstr "" -"Простая операция по :doc:`созданию индекса " -"` выглядит следующим " -"образом:" +"Индексы ограничивают значения, которые Tarantool может хранить в формате " +"MsgPack. Вот почему, например, есть отдельные типы полей ``'unsigned'`` " +"(число без знака) и ``'integer'`` (целое число), хотя в MsgPack они оба " +"хранятся как целочисленные значения. Индекс типа ``'unsigned'`` содержит " +"только *неотрицательные* целочисленные значения, а индекс типа ``'integer'``" +" содержит *любые* целочисленные значения." msgid "" -":extsamp:`box.space.{**{space-name}**}:create_index('{*{index-name}*}')`" +"The default field type is ``'unsigned'`` and the default index type is TREE. " +"Although ``'nil'`` is not a legal indexed field type, indexes may contain " +"`nil` :ref:`as a non-default option `." msgstr "" -":extsamp:`box.space.{**{space-name}**}:create_index('{*{index-name}*}')`" +"По умолчанию тип поля — ``'unsigned'``, тип индекса — TREE. " +"Хотя в качестве типа индексированого поля ``'nil'`` использовать нельзя, " +"индексы могут содержать `nil` как :ref:`опцию, которая не используется по " +"умолчанию `." msgid "" -"This creates a unique :ref:`TREE ` index on the first field of" -" all tuples (often called \"Field#1\"), which is assumed to be numeric." +"To learn more about field types, check the " +":ref:`Field type details ` section and the more elaborate" +" :ref:`Details about index field types ` in the reference." msgstr "" -"При этом создается уникальный :ref:`TREE-индекс ` по первому " -"полю всех кортежей (обычно его называют \"Field#1\"). Предполагается, что " -"индексируемое поле является числовым." +"Подробную информацию см. на странице :ref:`Описание типов полей `, " +"а также в более развернутом :ref:`Описании типов индексированных полей " +"` в справочнике." -msgid "" -"A recommended design pattern for a data model is to base primary keys on the" -" first fields of a tuple. This speeds up tuple comparison due to the " -"specifics of data storage and the way comparisons are arranged in Tarantool." -msgstr "" -"Рекомендуется проектировать модель данных так, чтобы первичные ключи были " -"первыми полями в кортеже. Это позволяет быстрее сравнивать кортежи, учитывая" -" специфику хранения данных и способ организации сравнений в Tarantool." +msgid "Field type name string" +msgstr "Имя типа поля" -msgid "" -"The simple :doc:`SELECT ` request" -" is:" -msgstr "" -"Вот простой запрос :doc:`SELECT " -"`:" +msgid "Field type |br|" +msgstr "Тип поля |br|" -msgid ":extsamp:`box.space.{**{space-name}**}:select({*{value}*})`" -msgstr ":extsamp:`box.space.{**{space-name}**}:select({*{value}*})`" +msgid "Index type" +msgstr "Тип индекса" -msgid "" -"This looks for a single tuple via the first index. Since the first index is " -"always unique, the maximum number of returned tuples will be 1. You can call" -" ``select()`` without arguments, and it will return all tuples. Be careful! " -"Using ``select()`` for huge spaces hangs your instance." -msgstr "" -"Такой запрос ищет отдельный кортеж, используя первичный индекс. Поскольку " -"первичный индекс всегда уникален, то данный запрос вернет не более одного " -"кортежа. Можно также вызвать ``select()`` без аргументов, чтобы вернуть все " -"кортежи. Осторожно! Если вызвать ``select()`` без аргументов в огромном " -"спейсе, ваш экземпляр зависнет." +msgid "``'boolean'``" +msgstr "``'boolean'``" -msgid "" -"An index definition may also include identifiers of tuple fields and their " -"expected **types**. See allowed indexed field types in section :ref:`Details" -" about indexed field types `:" -msgstr "" -"Определение индекса может также содержать идентификаторы полей кортежа и их " -"предполагаемые **типы**. См. допустимые типы полей в разделе :ref:`Описание " -"типов индексируемых полей `:" +msgid ":ref:`boolean `" +msgstr ":ref:`boolean `" -msgid "" -":extsamp:`box.space.{**{space-name}**}:create_index({**{index-name}**}, " -"{type = 'tree', parts = {{field = 1, type = 'unsigned'}}}`" -msgstr "" -":extsamp:`box.space.{**{space-name}**}:create_index({**{index-name}**}, " -"{type = 'tree', parts = {{field = 1, type = 'unsigned'}}}`" +msgid ":ref:`TREE or HASH `" +msgstr ":ref:`TREE или HASH `" -msgid "" -"Space definitions and index definitions are stored permanently in " -"Tarantool's system spaces :ref:`_space ` and :ref:`_index " -"`." -msgstr "" -"Определения спейса и определения индексов хранятся в системных спейсах " -"Tarantool :ref:`_space ` и :ref:`_index ` " -"соответственно." +msgid "``'integer'`` (may also be called ``‘int’``)" +msgstr "``'integer'`` (также может называться ``‘int’``)" -msgid "Tip" -msgstr "Примечание" - -msgid "" -"See full information about creating indexes, such as how to create a " -"multikey index, an index using the ``path`` option, or how to create a " -"functional index in our reference for " -":doc:`/reference/reference_lua/box_space/create_index`." +msgid ":ref:`integer `, which may include unsigned values" msgstr "" -"Полную информацию о создании индексов, например о создании индексов по " -"массиву (multikey), индексов с использованием пути ``path`` или " -"функциональных индексов см. в справочнике " -":doc:`/reference/reference_lua/box_space/create_index`." +":ref:`integer `, может включать в себя значения unsigned " +"(без знака)" -msgid "Index operations" -msgstr "Операции с индексами" +msgid "TREE or HASH" +msgstr "TREE или HASH" msgid "" -"Index operations are automatic: if a data manipulation request changes a " -"tuple, then it also changes the index keys defined for the tuple." +"``'unsigned'`` (may also be called ``'uint'`` or ``'num'``, but ``'num'`` is" +" deprecated)" msgstr "" -"Операции с индексами производятся автоматически. Если запрос на изменение " -"данных меняет данные в кортеже, то изменятся и ключи индекса для данного " -"кортежа." +"``'unsigned'`` (без знака, также может называться ``'uint'`` или ``'num'``, " +"но ``'num'`` объявлен устаревшим)" -msgid "" -"For further demonstrations let's create a sample space named ``tester`` and " -"put it in a variable ``my_space``:" -msgstr "" -"Для примера создадим спейс с именем ``tester`` и поместим его в переменную " -"``my_space``:" +msgid ":ref:`unsigned `" +msgstr ":ref:`unsigned `" -msgid "tarantool> my_space = box.schema.space.create('tester')" -msgstr "tarantool> my_space = box.schema.space.create('tester')" +msgid "TREE, BITSET, or HASH" +msgstr "TREE, BITSET или HASH" -msgid "Format the created space by specifying field names and types:" -msgstr "Отформатируем созданный спейс, указав имена и типы полей:" +msgid "``'double'``" +msgstr "``'double'``" -msgid "" -"tarantool> my_space:format({\n" -" > {name = 'id', type = 'unsigned'},\n" -" > {name = 'band_name', type = 'string'},\n" -" > {name = 'year', type = 'unsigned'},\n" -" > {name = 'rate', type = 'unsigned', is_nullable = true}})" -msgstr "" -"tarantool> my_space:format({\n" -" > {name = 'id', type = 'unsigned'},\n" -" > {name = 'band_name', type = 'string'},\n" -" > {name = 'year', type = 'unsigned'},\n" -" > {name = 'rate', type = 'unsigned', is_nullable = true}})" +msgid ":ref:`double `" +msgstr ":ref:`double `" -msgid "Create the **primary** index (named ``primary``):" -msgstr "Создадим **первичный** индекс с именем ``primary``:" +msgid "``'number'``" +msgstr "``'number'``" msgid "" -"tarantool> my_space:create_index('primary', {\n" -" > type = 'tree',\n" -" > parts = {'id'}\n" -" > })" +":ref:`number `, which may include :ref:`integer `, :ref:`double `, or :ref:`decimal ` values" msgstr "" -"tarantool> my_space:create_index('primary', {\n" -" > type = 'tree',\n" -" > parts = {'id'}\n" -" > })" +":ref:`number `, может включать в себя значения типа " +":ref:`integer `, :ref:`double ` или :ref:`decimal `" -msgid "This is a primary index based on the ``id`` field of each tuple." -msgstr "Это первичный индекс по полю ``id`` в каждом кортеже." +msgid "``'decimal'``" +msgstr "``'decimal'``" -msgid "Insert some :ref:`tuples ` into the space:" -msgstr "Вставим несколько :ref:`кортежей ` в спейс:" +msgid ":ref:`decimal `" +msgstr ":ref:`decimal `" -msgid "" -"tarantool> my_space:insert{1, 'Roxette', 1986, 1}\n" -"tarantool> my_space:insert{2, 'Scorpions', 2015, 4}\n" -"tarantool> my_space:insert{3, 'Ace of Base', 1993}\n" -"tarantool> my_space:insert{4, 'Roxette', 2016, 3}" -msgstr "" -"tarantool> my_space:insert{1, 'Roxette', 1986, 1}\n" -"tarantool> my_space:insert{2, 'Scorpions', 2015, 4}\n" -"tarantool> my_space:insert{3, 'Ace of Base', 1993}\n" -"tarantool> my_space:insert{4, 'Roxette', 2016, 3}" +msgid "``'string'`` (may also be called ``'str'``)" +msgstr "``'string'`` (строка, также может называться ``'str'``)" -msgid "Create a **secondary index**:" -msgstr "Создадим **вторичный индекс**:" +msgid ":ref:`string `" +msgstr ":ref:`string `" -msgid "" -"tarantool> box.space.tester:create_index('secondary', {parts = {{field=3, type='unsigned'}}})\n" -"---\n" -"- unique: true\n" -" parts:\n" -" - type: unsigned\n" -" is_nullable: false\n" -" fieldno: 3\n" -" id: 2\n" -" space_id: 512\n" -" type: TREE\n" -" name: secondary\n" -"..." -msgstr "" -"tarantool> box.space.tester:create_index('secondary', {parts = {{field=3, type='unsigned'}}})\n" -"---\n" -"- unique: true\n" -" parts:\n" -" - type: unsigned\n" -" is_nullable: false\n" -" fieldno: 3\n" -" id: 2\n" -" space_id: 512\n" -" type: TREE\n" -" name: secondary\n" -"..." +msgid "``'varbinary'``" +msgstr "``'varbinary'``" -msgid "Create a **multi-part index** with three parts:" -msgstr "Создадим **составной индекс** (multi-part) из трех частей:" +msgid ":ref:`varbinary `" +msgstr ":ref:`varbinary `" -msgid "" -"tarantool> box.space.tester:create_index('thrine', {parts = {\n" -" > {field = 2, type = 'string'},\n" -" > {field = 3, type = 'unsigned'},\n" -" > {field = 4, type = 'unsigned'}\n" -" > }})\n" -"---\n" -"- unique: true\n" -" parts:\n" -" - type: string\n" -" is_nullable: false\n" -" fieldno: 2\n" -" - type: unsigned\n" -" is_nullable: false\n" -" fieldno: 3\n" -" - type: unsigned\n" -" is_nullable: true\n" -" fieldno: 4\n" -" id: 6\n" -" space_id: 513\n" -" type: TREE\n" -" name: thrine\n" -"..." -msgstr "" -"tarantool> box.space.tester:create_index('thrine', {parts = {\n" -" > {field = 2, type = 'string'},\n" -" > {field = 3, type = 'unsigned'},\n" -" > {field = 4, type = 'unsigned'}\n" -" > }})\n" -"---\n" -"- unique: true\n" -" parts:\n" -" - type: string\n" -" is_nullable: false\n" -" fieldno: 2\n" -" - type: unsigned\n" -" is_nullable: false\n" -" fieldno: 3\n" -" - type: unsigned\n" -" is_nullable: true\n" -" fieldno: 4\n" -" id: 6\n" -" space_id: 513\n" -" type: TREE\n" -" name: thrine\n" -"..." +msgid "TREE, HASH, or BITSET (since version 2.7)" +msgstr "TREE, HASH или BITSET (с версии 2.7)" -msgid "**There are the following SELECT variations:**" -msgstr "**Можно использовать такие варианты SELECT:**" +msgid "``'uuid'``" +msgstr "``'uuid'``" -msgid "The search can use **comparisons** other than equality:" -msgstr "" -"Помимо условия равенства, при поиске могут использоваться и другие **условия" -" сравнения**:" +msgid ":ref:`uuid `" +msgstr ":ref:`uuid `" -msgid "" -"tarantool> box.space.tester:select(1, {iterator = 'GT'})\n" -"---\n" -"- - [2, 'Scorpions', 2015, 4]\n" -" - [3, 'Ace of Base', 1993]\n" -" - [4, 'Roxette', 2016, 3]\n" -"..." -msgstr "" -"tarantool> box.space.tester:select(1, {iterator = 'GT'})\n" -"---\n" -"- - [2, 'Scorpions', 2015, 4]\n" -" - [3, 'Ace of Base', 1993]\n" -" - [4, 'Roxette', 2016, 3]\n" -"..." +msgid "``'array'``" +msgstr "``'array'``" -msgid "The :ref:`comparison operators ` are:" -msgstr "Есть такие :ref:`операторы сравнения `:" +msgid ":ref:`array `" +msgstr ":ref:`array `" -msgid "``LT`` for \"less than\"" -msgstr "``LT`` — \"меньше\"" +msgid ":ref:`RTREE `" +msgstr ":ref:`RTREE `" -msgid "``LE`` for \"less than or equal\"" -msgstr "``LE`` — \"меньше или равно\"" - -msgid "``GT`` for \"greater\"" -msgstr "``GT`` — \"больше\"" - -msgid "``GE`` for \"greater than or equal\" ." -msgstr "``GE`` — \"больше или равно\"" - -msgid "``EQ`` for \"equal\"," -msgstr "``EQ`` — \"равно\"," - -msgid "``REQ`` for \"reversed equal\"" -msgstr "``REQ`` — \"равно, результаты отсортированы в порядке убывания по ключу\"" - -msgid "" -"Value comparisons make sense if and only if the index type is TREE. The " -"iterator types for other types of indexes are slightly different and work " -"differently. See details in section :ref:`Iterator types `." -msgstr "" -"Только для TREE-индексов есть смысл в сравнении значений. Итераторы для " -"других типов индексов немного отличаются и работают по-другому. Более " -"подробную информацию см. в разделе :ref:`Типы итераторов `." - -msgid "" -"Note that we don't use the name of the index, which means we use primary " -"index here." -msgstr "" -"Обратите внимание, что мы не используем имя индекса — значит, здесь мы " -"используем первичный индекс." - -msgid "" -"This type of search may return more than one tuple. The tuples will be " -"sorted in descending order by key if the comparison operator is LT or LE or " -"REQ. Otherwise they will be sorted in ascending order." -msgstr "" -"Этот вариант поиска может вернуть более одного кортежа. Если используется " -"оператор сравнения LT, LE или REQ, то кортежи будут отсортированы по ключу в" -" порядке убывания. Во всех остальных случаях — в порядке возрастания." - -msgid "The search can use a **secondary index**." -msgstr "Для поиска можно использовать **вторичный индекс**." - -msgid "" -"For a primary-key search, it is optional to specify an index name as was " -"demonstrated above. For a secondary-key search, it is mandatory." -msgstr "" -"При поиске по первичному ключу имя индекса можно не указывать, как показано " -"выше. При поиске же по вторичному ключу имя индекса нужно указать " -"обязательно." - -msgid "" -"tarantool> box.space.tester.index.secondary:select({1993})\n" -"---\n" -"- - [3, 'Ace of Base', 1993]\n" -"..." -msgstr "" -"tarantool> box.space.tester.index.secondary:select({1993})\n" -"---\n" -"- - [3, 'Ace of Base', 1993]\n" -"..." +msgid "``'scalar'``" +msgstr "``'scalar'``" msgid "" -"**Partial key search:** The search may be for some key parts starting with " -"the prefix of the key. Note that partial key searches are available only in " -"TREE indexes." +"may include :ref:`nil `, :ref:`boolean `, " +":ref:`integer `, :ref:`unsigned `, " +":ref:`number `, :ref:`decimal `, " +":ref:`string `, :ref:`varbinary `, or " +":ref:`uuid ` values" msgstr "" -"**Поиск по частям ключа:** Можно производить поиск по частям ключа, начиная " -"с префикса ключа. Обратите внимание, что поиск по части ключа доступен " -"только в TREE-индексах." +"может содержать значения :ref:`nil `, :ref:`boolean `, :ref:`integer `, :ref:`unsigned `, :ref:`number `, :ref:`decimal `, :ref:`string ` или :ref:`varbinary `" msgid "" -"tarantool> box.space.tester.index.thrine:select({'Scorpions', 2015})\n" -"---\n" -"- - [2, 'Scorpions', 2015, 4]\n" -"..." -msgstr "" -"tarantool> box.space.tester.index.thrine:select({'Scorpions', 2015})\n" -"---\n" -"- - [2, 'Scorpions', 2015, 4]\n" -"..." - -msgid "The search can be for all fields, using a table as the value:" -msgstr "Поиск можно производить по всем полям через запись в виде таблицы:" - -msgid "" -"tarantool> box.space.tester.index.thrine:select({'Roxette', 2016, 3})\n" -"---\n" -"- - [4, 'Roxette', 2016, 3]\n" -"..." -msgstr "" -"tarantool> box.space.tester.index.thrine:select({'Roxette', 2016, 3})\n" -"---\n" -"- - [4, 'Roxette', 2016, 3]\n" -"..." - -msgid "or the search can be for one field, using a table or a scalar:" +"When a scalar field contains values of different underlying types, the key " +"order is: nils, then booleans, then numbers, then strings, then varbinaries," +" then uuids." msgstr "" -"либо же по одному полю, в этом случае используется таблица или скалярное " -"значение:" +"Когда поле типа scalar содержит значения различных базовых типов, то порядок" +" ключей следующий: nil, затем boolean, затем number, затем string, затем " +"varbinary, затем uuid." msgid "" -"tarantool> box.space.tester.index.thrine:select({'Roxette'})\n" -"---\n" -"- - [1, 'Roxette', 1986, 5]\n" -" - [4, 'Roxette', 2016, 3]\n" -"..." +"To create a generator for indexes, you can use a sequence object. " +"Learn how to do it in the :ref:`tutorial `." msgstr "" -"tarantool> box.space.tester.index.thrine:select({'Roxette'})\n" -"---\n" -"- - [1, 'Roxette', 1986, 5]\n" -" - [4, 'Roxette', 2016, 3]\n" -"..." +"Можно создать генератор индексов, используя последовательность (sequence). " +"Чтобы узнать подробности, обратитесь к :ref:`практическому руководству `." -msgid "" -"You can also add, drop, or alter the definitions at runtime, with some " -"restrictions. Read more about index operations in reference for " -":doc:`box.index submodule `." -msgstr "" -"С некоторыми ограничениями можно добавлять, удалять или изменять определения" -" во время исполнения кода. Более подробную информацию об операциях с " -"индексами см. в справочнике по :doc:`вложенному модулю box.index " -"`." msgid "Index types" msgstr "Типы индексов" diff --git a/locale/ru/LC_MESSAGES/concepts/data_model/migrations.po b/locale/ru/LC_MESSAGES/concepts/data_model/migrations.po new file mode 100644 index 0000000000..16f539fa94 --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/data_model/migrations.po @@ -0,0 +1,246 @@ + +msgid "Migrations" +msgstr "Миграции" + +msgid "" +"**Migration** refers to any change in a data schema: adding/removing a " +"field, creating/dropping an index, changing a field format, etc." +msgstr "" +"**Миграцией** называется любое изменение схемы данных: добавление/удаление " +"поля, добавление/удаление индекса, изменение формата поля и т. д." + +msgid "" +"In Tarantool, there are two types of schema migration that do not require " +"data migration:" +msgstr "" +"В Tarantool есть только два вида миграции схемы, при которых не нужно " +"мигрировать данные:" + +msgid "adding a field to the end of a space" +msgstr "добавление поля в конец спейса" + +msgid "creating an index" +msgstr "добавление индекса" + +msgid "Adding a field to the end of a space" +msgstr "Добавление поля в конец спейса" + +msgid "You can add a field as follows:" +msgstr "Добавление поля происходит следующим образом:" + +msgid "" +"local users = box.space.users\n" +"local fmt = users:format()\n" +"\n" +"table.insert(fmt, { name = 'age', type = 'number', is_nullable = true })\n" +"users:format(fmt)" +msgstr "" +"local users = box.space.users\n" +"local fmt = users:format()\n" +"\n" +"table.insert(fmt, { name = 'age', type = 'number', is_nullable = true })\n" +"users:format(fmt)" + +msgid "" +"Note that the field must have the ``is_nullable`` parameter. Otherwise, an " +"error will occur." +msgstr "" +"Обратите внимание: поле обязательно должно иметь параметр ``is_nullable``. " +"Иначе произойдет ошибка." + +msgid "" +"After creating a new field, you probably want to fill it with data. The " +"`tarantool/moonwalker `_ module is " +"useful for this task. The README file describes how to work with this " +"module." +msgstr "" +"После создания нового поля, вы, вероятно, захотите заполнить его данными.\n" +"Для этой задачи удобно использовать модуль `tarantool/moonwalker `_. В README есть описание того, как начать его использовать." + +msgid "Creating an index" +msgstr "Добавление индекса" + +msgid "" +"Index creation is described in the " +":doc:`/reference/reference_lua/box_space/create_index` method." +msgstr "" +"Про добавление индекса рассказывается в описании метода " +":doc:`/reference/reference_lua/box_space/create_index`." + +msgid "Other types of migrations" +msgstr "Остальные виды миграций" + +msgid "" +"Other types of migrations are also allowed, but it would be more difficult " +"to maintain data consistency." +msgstr "" +"Остальные виды миграций также возможны, однако поддерживать консистентность " +"данных при этом сложнее." + +msgid "Migrations are possible in two cases:" +msgstr "Миграции можно выполнять в двух случаях:" + +msgid "When Tarantool starts, and no client uses the database yet" +msgstr "при старте Tarantool, пока ни один клиент еще не использует БД" + +msgid "" +"During request processing, when active clients are already using the " +"database" +msgstr "в процессе обработки запросов, когда у БД уже есть активные клиенты" + +msgid "" +"For the first case, it is enough to write and test the migration code. The " +"most difficult task is to migrate data when there are active clients. You " +"should keep it in mind when you initially design the data schema." +msgstr "" +"Для первого случая достаточно кода миграции, который будет написан и " +"оттестирован. Самая сложная задача — это провести миграцию данных при " +"наличии активных клиентов. Это необходимо иметь в виду при начальном " +"проектировании схемы данных." + +msgid "We identify the following problems if there are active clients:" +msgstr "Мы выделяем следующие проблемы при наличии активных клиентов:" + +msgid "Associated data can change atomically." +msgstr "Связанные данные могут атомарно изменяться." + +msgid "" +"The system should be able to transfer data using both the new schema and the" +" old one." +msgstr "Нужно уметь отдавать данные как по новой схеме, так и по старой." + +msgid "" +"When data is being transferred to a new space, data access should consider " +"that the data might be in one space or another." +msgstr "" +"Когда данные перемещают в новый спейс, доступ к данным должен учитывать, что" +" данные могут быть как в одном спейсе, так и в другом." + +msgid "" +"Write requests must not interfere with the migration. A common approach is " +"to write according to the new data schema." +msgstr "" +"Запросы на запись не должны мешать корректной миграции. Типичный подход: " +"всегда писать по новой схеме." + +msgid "" +"These issues may or may not be relevant depending on your application and " +"its availability requirements." +msgstr "" +"Эти проблемы могут быть или не быть релевантными в зависимости от вашего " +"приложения и требований к его доступности." + +msgid "What you need to know when writing complex migrations" +msgstr "Что нужно знать при написании сложных миграций" + +msgid "" +"Tarantool has a transaction mechanism. It is useful when writing a " +"migration, because it allows you to work with the data atomically. But " +"before using the transaction mechanism, you should explore its limitations." +msgstr "" +"В Tarantool есть механизм транзакций. Он полезен при написании миграции, так" +" как позволяет атомарно работать с данными. Но перед использованием " +"механизма транзакций нужно знать об ограничениях." + +msgid "" +"For details, see the section about :doc:`transactions `." +msgstr "" +"Подробнее о них описано в разделе про :doc:`транзакции `." + +msgid "How you can apply migration" +msgstr "Как применять миграции" + +msgid "" +"The migration code is executed on a running Tarantool instance. Important: " +"no method guarantees you transactional application of migrations on the " +"whole cluster." +msgstr "" +"Код миграций исполняется на запущенном инстансе Tarantool. Важно: ни один " +"способ не гарантирует вам транзакционное применение миграций на всем " +"кластере." + +msgid "**Method 1**: include migrations in the application code" +msgstr "**Способ 1**: написать миграции в коде основного приложения" + +msgid "" +"This is quite simple: when you reload the code, the data is migrated at the " +"right moment, and the database schema is updated. However, this method may " +"not work for everyone. You may not be able to restart Tarantool or update " +"the code using the hot-reload mechanism." +msgstr "" +"Это довольно просто: когда вы перезагружаете код, в нужный момент происходит" +" миграция данных и схема базы данных обновляется. Однако такой способ может " +"подойти не всем. У вас может не быть возможности перезапустить Tarantool или" +" обновить код через механизм горячей перезагрузки (hot reload)." + +msgid "" +"**Method 2**: tarantool/migrations (only for a Tarantool Cartridge cluster)" +msgstr "" +"**Способ 2**: tarantool/migrations (только для кластера на Tarantool " +"Cartridge)" + +msgid "" +"This method is described in the README file of the `tarantool/migrations " +"`_ module." +msgstr "" +"Про этот способ подробнее написано в README самого модуля " +"`tarantool/migrations `_." + +msgid "" +"There are also two other methods that we **do not recommend**, but you may " +"find them useful for one reason or another." +msgstr "" +"Есть также два способа, которые мы **не рекомендуем использовать**, но вы " +"можете найти их полезными по тем или иным причинам." + +msgid "**Method 3**: the ``tarantoolctl`` utility" +msgstr "**Cпособ 3**: утилита ``tarantoolctl``" + +msgid "" +"The ``tarantoolctl`` utility ships with Tarantool. Connect to the necessary " +"instance using ``tarantoolctl connect``." +msgstr "" +"Утилита ``tarantoolctl`` поставляется вместе с Tarantool. Подключитесь к " +"нужному инстансу через команду ``tarantoolctl connect``." + +msgid "$ tarantoolctl connect admin:password@localhost:3301" +msgstr "$ tarantoolctl connect admin:password@localhost:3301" + +msgid "" +"If your migration is written in a Lua file, you can execute it using " +"``dofile()``. Call this function and specify the path to the migration file " +"as the first argument. It looks like this:" +msgstr "" +"Если ваша миграция написана в Lua файле, вы можете исполнить его с помощью " +"функции ``dofile()``. Вызовите ее и первым аргументом укажите путь до файла " +"с миграцией. Выглядит это вот так:" + +msgid "" +"tarantool> dofile('0001-delete-space.lua')\n" +"---\n" +"..." +msgstr "" +"tarantool> dofile('0001-delete-space.lua')\n" +"---\n" +"..." + +msgid "" +"(or) Copy the migration script code, paste it into the console, and run it." +msgstr "" +"(или) можно скопировать код скрипта миграции, вставить его в консоль и " +"применить." + +msgid "**Method 4**: applying migration with Ansible" +msgstr "**Способ 4**: применение миграции с помощью Ansible" + +msgid "" +"If you use the `Ansible role `_ to deploy a Tarantool cluster, you can use ``eval``. You can " +"find more information about it `in the Ansible role documentation " +"`_." +msgstr "" +"Если вы используете `Ansible-роль для развёртывания кластера Tarantool " +"`_, то вы можете применить " +"``eval``. Прочитать подробнее про ``eval`` можно `в документации по Ansible-" +"роли `_." diff --git a/locale/ru/LC_MESSAGES/concepts/data_model/operations.po b/locale/ru/LC_MESSAGES/concepts/data_model/operations.po new file mode 100644 index 0000000000..1a5a70431c --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/data_model/operations.po @@ -0,0 +1,284 @@ + +msgid "Operations" +msgstr "Операции" + +msgid "Data operations" +msgstr "Операции с данными" + +msgid "The basic data operations supported in Tarantool are:" +msgstr "Tarantool поддерживает следующие основные операции с данными:" + +msgid "" +"five data-manipulation operations (INSERT, UPDATE, UPSERT, DELETE, REPLACE)," +" and" +msgstr "" +"пять операций по изменению данных (INSERT, UPDATE, UPSERT, DELETE, REPLACE) " +"и" + +msgid "one data-retrieval operation (SELECT)." +msgstr "одну операцию по выборке данных (SELECT)." + +msgid "" +"All of them are implemented as functions in :ref:`box.space ` " +"submodule." +msgstr "" +"Все они реализованы в виде функций во вложенном модуле :ref:`box.space " +"`." + +msgid "**Examples:**" +msgstr "**Примеры:**" + +msgid ":ref:`INSERT `: Add a new tuple to space 'tester'." +msgstr "" +":ref:`INSERT `: добавить новый кортеж к спейсу 'tester'." + +msgid "The first field, field[1], will be 999 (MsgPack type is `integer`)." +msgstr "" +"Первое поле, field[1], будет 999 (тип MsgPack -- `integer`, целое число)." + +msgid "" +"The second field, field[2], will be 'Taranto' (MsgPack type is `string`)." +msgstr "" +"Второе поле, field[2], будет 'Taranto' (тип MsgPack -- `string`, строка)." + +msgid "tarantool> box.space.tester:insert{999, 'Taranto'}" +msgstr "tarantool> box.space.tester:insert{999, 'Taranto'}" + +msgid "" +":ref:`UPDATE `: Update the tuple, changing field field[2]." +msgstr "" +":ref:`UPDATE `: обновить кортеж, изменяя поле field[2]." + +msgid "" +"The clause \"{999}\", which has the value to look up in the index of the " +"tuple's primary-key field, is mandatory, because ``update()`` requests must " +"always have a clause that specifies a unique key, which in this case is " +"field[1]." +msgstr "" +"Оператор \"{999}\" со значением, которое используется для поиска поля, " +"соответствующего ключу в первичном индексе, является обязательным, поскольку" +" в запросе ``update()`` должен быть оператор, который указывает уникальный " +"ключ, в данном случае -- field[1]." + +msgid "" +"The clause \"{{'=', 2, 'Tarantino'}}\" specifies that assignment will happen" +" to field[2] with the new value." +msgstr "" +"Оператор \"{{'=', 2, 'Tarantino'}}\" указывает, что назначение нового " +"значения относится к field[2]." + +msgid "tarantool> box.space.tester:update({999}, {{'=', 2, 'Tarantino'}})" +msgstr "tarantool> box.space.tester:update({999}, {{'=', 2, 'Tarantino'}})" + +msgid "" +":ref:`UPSERT `: Upsert the tuple, changing field field[2] " +"again." +msgstr "" +":ref:`UPSERT `: обновить или вставить кортеж, снова " +"изменяя поле field[2]." + +msgid "" +"The syntax of ``upsert()`` is similar to the syntax of ``update()``. " +"However, the execution logic of these two requests is different. UPSERT is " +"either UPDATE or INSERT, depending on the database's state. Also, UPSERT " +"execution is postponed until after transaction commit, so, unlike " +"``update()``, ``upsert()`` doesn't return data back." +msgstr "" +"Синтаксис ``upsert()`` похож на синтаксис ``update()``. Однако логика " +"выполнения двух запросов отличается. UPSERT означает UPDATE или INSERT, в " +"зависимости от состояния базы данных. Кроме того, выполнение UPSERT " +"откладывается до коммита транзакции, поэтому в отличие от ``update()``, " +"``upsert()`` не возвращает данные." + +msgid "" +"tarantool> box.space.tester:upsert({999, 'Taranted'}, {{'=', 2, " +"'Tarantism'}})" +msgstr "" +"tarantool> box.space.tester:upsert({999, 'Taranted'}, {{'=', 2, " +"'Tarantism'}})" + +msgid "" +":ref:`REPLACE `: Replace the tuple, adding a new field." +msgstr "" +":ref:`REPLACE `: заменить кортеж, добавляя новое поле." + +msgid "" +"This is also possible with the ``update()`` request, but the ``update()`` " +"request is usually more complicated." +msgstr "" +"Это действие также можно выполнить с помощью запроса ``update()``, но обычно" +" запрос ``update()`` более сложен." + +msgid "tarantool> box.space.tester:replace{999, 'Tarantella', 'Tarantula'}" +msgstr "tarantool> box.space.tester:replace{999, 'Tarantella', 'Tarantula'}" + +msgid ":ref:`SELECT `: Retrieve the tuple." +msgstr ":ref:`SELECT `: провести выборку кортежа." + +msgid "" +"The clause \"{999}\" is still mandatory, although it does not have to " +"mention the primary key." +msgstr "" +"Оператор \"{999}\" все еще обязателен, хотя в нем не должен упоминаться " +"первичный ключ." + +msgid "tarantool> box.space.tester:select{999}" +msgstr "tarantool> box.space.tester:select{999}" + +msgid ":ref:`DELETE `: Delete the tuple." +msgstr ":ref:`DELETE `: удалить кортеж." + +msgid "In this example, we identify the primary-key field." +msgstr "" +"В этом примере мы определяем поле, соответствующее ключу в первичном " +"индексе." + +msgid "tarantool> box.space.tester:delete{999}" +msgstr "tarantool> box.space.tester:delete{999}" + +msgid "Summarizing the examples:" +msgstr "Подводя итоги по примерам:" + +msgid "" +"Functions ``insert`` and ``replace`` accept a tuple (where a primary key " +"comes as part of the tuple)." +msgstr "" +"Функции ``insert`` и ``replace`` принимают кортеж (где первичный ключ -- это" +" часть кортежа)." + +msgid "" +"Function ``upsert`` accepts a tuple (where a primary key comes as part of " +"the tuple), and also the update operations to execute." +msgstr "" +"Функция ``upsert`` принимает кортеж (где первичный ключ -- это часть " +"кортежа), а также операции по обновлению." + +msgid "" +"Function ``delete`` accepts a full key of any unique index (primary or " +"secondary)." +msgstr "" +"Функция ``delete`` принимает полный ключ любого уникального индекса " +"(первичный или вторичный)." + +msgid "" +"Function ``update`` accepts a full key of any unique index (primary or " +"secondary), and also the operations to execute." +msgstr "" +"Функция ``update`` принимает полный ключ любого уникального индекса " +"(первичный или вторичный), а также операции к выполнению." + +msgid "" +"Function ``select`` accepts any key: primary/secondary, unique/non-unique, " +"full/partial." +msgstr "" +"Функция ``select`` принимает любой ключ: первичный/вторичный, " +"уникальный/неуникальный, полный/часть." + +msgid "" +"See reference on ``box.space`` for more :ref:`details on using data " +"operations `." +msgstr "" +"Для получения более :ref:`подробной информации по использованию операций с " +"данными ` см. справочник по " +"``box.space``." + +msgid "" +"Besides Lua, you can use :ref:`Perl, PHP, Python or other programming " +"language connectors `. The client server protocol is " +"open and documented. See this :ref:`annotated BNF `." +msgstr "" +"Помимо Lua можно использовать :ref:`коннекторы к Perl, PHP, Python или " +"другому языку программирования `. Клиент-серверный " +"протокол открыт и задокументирован. См. :ref:`БНФ с комментариями " +"`." + +msgid "Complexity factors" +msgstr "Факторы сложности" + +msgid "" +"In reference for :ref:`box.space ` and " +":doc:`/reference/reference_lua/box_index` submodules, there are notes about " +"which complexity factors might affect the resource usage of each function." +msgstr "" +"Во вложенных модулях :ref:`box.space ` и " +":doc:`/reference/reference_lua/box_index` содержится информация о том, как " +"факторы сложности могут повлиять на использование каждой функции." + +msgid "Complexity factor" +msgstr "Фактор сложности" + +msgid "Effect" +msgstr "Эффект" + +msgid "Index size" +msgstr "Размер индекса" + +msgid "" +"The number of index keys is the same as the number of tuples in the data " +"set. For a TREE index, if there are more keys, then the lookup time will be " +"greater, although, of course, the effect is not linear. For a HASH index, if" +" there are more keys, then there is more RAM used, but the number of low-" +"level steps tends to remain constant." +msgstr "" +"Количество ключей в индексе равно количеству кортежей в наборе данных. Для " +"TREE-индекса: чем больше ключей, тем больше время поиска, хотя зависимость " +"здесь, конечно же, нелинейная. Для HASH-индекса: чем больше ключей, тем " +"больше нужно оперативной памяти, но количество низкоуровневых шагов остается" +" примерно тем же." + +msgid "" +"Typically, a HASH index is faster than a TREE index if the number of tuples " +"in the space is greater than one." +msgstr "" +"Как правило, поиск по HASH-индексу работает быстрее, чем по TREE-индексу, " +"если в спейсе более одного кортежа." + +msgid "Number of indexes accessed" +msgstr "Количество обращений к индексам" + +msgid "" +"Ordinarily, only one index is accessed to retrieve one tuple. But to update " +"the tuple, there must be N accesses if the space has N different indexes." +msgstr "" +"Обычно для выборки значений одного кортежа используется только один индекс. " +"Но при обновлении значений в кортеже требуется N обращений, если в спейсе N " +"индексов." + +msgid "" +"Note regarding storage engine: Vinyl optimizes away such accesses if " +"secondary index fields are unchanged by the update. So, this complexity " +"factor applies only to memtx, since it always makes a full-tuple copy on " +"every update." +msgstr "" +"Примечание по движку базы данных: если обновление не затрагивает поля " +"вторичного индекса, vinyl не производит эти обращения. Таким образом, этот " +"фактор сложности влияет только на memtx, который создает копию всего кортежа" +" при каждом обновлении." + +msgid "Number of tuples accessed" +msgstr "Количество обращений к кортежам" + +msgid "" +"A few requests, for example, SELECT, can retrieve multiple tuples. This " +"factor is usually less important than the others." +msgstr "" +"Некоторые запросы, например SELECT, могут возвращать несколько кортежей. " +"Обычно этот фактор менее важен, чем другие." + +msgid "WAL settings" +msgstr "Настройки WAL" + +msgid "" +"The important setting for the write-ahead log is :ref:`wal_mode " +"`. If the setting causes no writing " +"or delayed writing, this factor is unimportant. If the setting causes every " +"data-change request to wait for writing to finish on a slow device, this " +"factor is more important than all the others." +msgstr "" +"Важным параметром для записи в WAL является :ref:`wal_mode " +"`. Если запись в WAL отключена или " +"задана запись с задержкой, но этот фактор не так важен. Если же запись в " +"WAL производится при каждом запросе на изменение данных, то при каждом таком" +" запросе приходится ждать, пока отработает обращение к более медленному " +"диску, и данный фактор становится важнее всех остальных." diff --git a/locale/ru/LC_MESSAGES/concepts/data_model/persistence.po b/locale/ru/LC_MESSAGES/concepts/data_model/persistence.po new file mode 100644 index 0000000000..7142a3178d --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/data_model/persistence.po @@ -0,0 +1,82 @@ + +msgid "Persistence" +msgstr "Персистентность" + +msgid "" +"To ensure data persistence, Tarantool records updates to the database in the" +" so-called :ref:`write-ahead log (WAL) ` files. When a power " +"outage occurs or the Tarantool instance is killed incidentally, the in-" +"memory database is lost. In such case, Tarantool restores the data from WAL " +"files by reading them and redoing the requests. This is called the " +"\"recovery process\". You can change the timing of the WAL writer or turn it" +" off by setting the :ref:`wal_mode `." +msgstr "" +"Чтобы обеспечить персистентность данных, Tarantool записывает обновления " +"базы данных в так называемые :ref:`файлы журнала упреждающей записи (write-" +"ahead log, WAL) `. При отключении электроэнергии или " +"случайном завершении работы экземпляра Tarantool данные в оперативной памяти" +" теряются. В таком случае Tarantool восстанавливает данные из WAL-файлов, " +"повторно выполняя запросы, записанные в них. Это называется \"процесс " +"восстановления\". Можно настроить, как часто данные записываются в WAL-" +"файлы, или отключить запись совсем с помощью :ref:`wal_mode " +"`." + +msgid "" +"Tarantool also maintains a set of :ref:`snapshot files `. These files contain an on-disk copy of the entire data set for a" +" given moment. Instead of reading every WAL file since the databases were " +"created, the recovery process can load the latest snapshot file and then " +"read the WAL files, produced after the snapshot file was made. After " +"creating a new snapshot, the earlier WAL files can be removed to free up " +"space." +msgstr "" +"Tarantool также сохраняет набор файлов со статическими снимками данных " +"(:ref:`snapshots `). Файл со снимком — это дисковая " +"копия всех данных в базе на какой-то момент. Вместо того, чтобы перечитывать" +" все WAL-файлы с момента создания базы, Tarantool в процессе восстановления " +"может загрузить самый свежий снимок и затем прочитать только те WAL-файлы, " +"которые были созданы начиная с момента сохранения снимка. После создания " +"новых снимков более ранние WAL-файлы могут быть удалены, чтобы освободить " +"место на диске." + +msgid "" +"To force immediate creation of a snapshot file, use the :doc:`box.snapshot()" +" ` function. To enable the automatic " +"creation of snapshot files, use Tarantool's :ref:`checkpoint daemon " +"`. The checkpoint daemon sets intervals for " +"forced checkpoints. It makes sure that the states of both memtx and vinyl " +"storage engines are synchronized and saved to disk, and automatically " +"removes earlier WAL files." +msgstr "" +"Чтобы принудительно создать файл снимка, используйте в Tarantool функцию " +":doc:`box.snapshot() `. Чтобы " +"включить автоматическое создание файлов снимков, используйте :ref:`демон " +"создания контрольных точек (checkpoint daemon) `" +" Tarantool. Этот демон определяет интервалы для принудительного создания " +"контрольных точек. Он обеспечивает синхронизацию и сохранение на диск " +"образов движков базы данных (как memtx, так и vinyl), а также автоматически " +"удаляет более ранние WAL-файлы." + +msgid "Snapshot files can be created even if there is no WAL file." +msgstr "Файлы со снимками можно создавать, даже если WAL-файлы отсутствуют." + +msgid "" +"The memtx engine makes only regular checkpoints with the interval set in " +":ref:`checkpoint daemon ` configuration." +msgstr "" +"Движок memtx регулярно создает контрольные точки с интервалом, указанным в " +"настройках :ref:`демона создания контрольных точек " +"`." + +msgid "The vinyl engine runs checkpointing in the background at all times." +msgstr "" +"Движок vinyl постоянно сохраняет состояние в контрольной точке в фоновом " +"режиме." + +msgid "" +"See the :ref:`Internals ` section for more " +"details about the WAL writer and the recovery process." +msgstr "" +"Для получения более подробной информации о методе записи WAL-файлов и " +"процессе восстановления см. раздел :ref:`Внутренняя реализация `." diff --git a/locale/ru/LC_MESSAGES/concepts/data_model/schema_desc.po b/locale/ru/LC_MESSAGES/concepts/data_model/schema_desc.po new file mode 100644 index 0000000000..b7b89e89c2 --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/data_model/schema_desc.po @@ -0,0 +1,213 @@ + +msgid "Data schema description" +msgstr "Описание схемы данных" + +msgid "In Tarantool, the use of a data schema is optional." +msgstr "В Tarantool использование схемы данных опционально." + +msgid "" +"When creating a :term:`space `, you do not have to define a data " +"schema. In this case, the tuples store random data. This rule does not apply" +" to indexed fields. Such fields must contain data of the same type." +msgstr "" +"При создании :term:`спейса ` схему можно не задавать и тогда в " +"кортежах могут лежать произвольные данные. Это правило не распространяется " +"на поля, по которым построены индексы. У таких полей данные должны быть " +"одного типа." + +msgid "" +"You can define a data schema when creating a space. Read more in the " +"description of the :doc:`/reference/reference_lua/box_schema/space_create` " +"function. If you have already created a space without specifying a data " +"schema, you can do it later using " +":doc:`/reference/reference_lua/box_space/format`." +msgstr "" +"Схему можно задать при создании спейса. Читайте подробнее в описании функции" +" :doc:`/reference/reference_lua/box_schema/space_create`. Если вы создали " +"спейс без схемы, ее можно добавить позже с помощью метода " +":doc:`/reference/reference_lua/box_space/format`." + +msgid "" +"After the data schema is defined, all the data is validated by type. Before " +"any insert or update, you will get an error if the data types do not match." +msgstr "" +"После указания схемы данные начинают валидироваться по типам. Перед каждой " +"операцией вставки или обновления они проверяются, и в случае несоответствия " +"типов вы получите ошибку." + +msgid "We recommend using a data schema because it helps avoid mistakes." +msgstr "" +"Мы рекомендуем использовать подход со схемой, потому что он помогает " +"избежать ошибок." + +msgid "In Tarantool, you can define a data schema in two different ways." +msgstr "Схему в Tarantool можно задавать двумя разными способами." + +msgid "Data schema description in a code file" +msgstr "Описание схемы в файле с кодом" + +msgid "" +"The code file is usually called ``init.lua`` and contains the following " +"schema description:" +msgstr "" +"Обычно файл с кодом называется ``init.lua`` и имеет следующее описание " +"схемы:" + +msgid "" +"box.cfg()\n" +"\n" +"users = box.schema.create_space('users', { if_not_exists = true })\n" +"users:format({{ name = 'user_id', type = 'number'}, { name = 'fullname', type = 'string'}})\n" +"\n" +"users:create_index('pk', { parts = { { field = 'user_id', type = 'number'}}})" +msgstr "" +"box.cfg()\n" +"\n" +"users = box.schema.create_space('users', { if_not_exists = true })\n" +"users:format({{ name = 'user_id', type = 'number'}, { name = 'fullname', type = 'string'}})\n" +"\n" +"users:create_index('pk', { parts = { { field = 'user_id', type = 'number'}}})" + +msgid "" +"This is quite simple: when you run tarantool, it executes this code and " +"creates a data schema. To run this file, use:" +msgstr "" +"Этот подход довольно простой. Когда вы запустите tarantool, этот код " +"исполнится и создаст схему. Чтобы запустить файл, используйте следующую " +"команду:" + +msgid "tarantool init.lua" +msgstr "tarantool init.lua" + +msgid "" +"However, it may seem complicated if you do not plan to dive deep into the " +"Lua language and its syntax." +msgstr "" +"Но это может показаться слишком сложным, если вы не собираетесь глубоко " +"разбираться с языком Lua и его синтаксисом." + +msgid "" +"Possible difficulty: the snippet above has a function call with a colon: " +"``users:format``. It is used to pass the ``users`` variable as the first " +"argument of the ``format`` function. This is similar to ``self`` in object-" +"based languages." +msgstr "" +"Пример возможной сложности: в фрагменте выше есть вызов функций с " +"двоеточием: ``users:format``. Он используется, чтобы передать переменную " +"``users`` в качестве первого аргумента функции ``format``. Это аналог " +"``self`` в объектно-ориентированных языках." + +msgid "" +"So it might be more convenient for you to describe the data schema with " +"YAML." +msgstr "Поэтому вам может быть удобно описать схему через YAML." + +msgid "Data schema description using the DDL module" +msgstr "Описание через модуль DDL" + +msgid "" +"The `DDL module `_ allows you to describe " +"a data schema in the YAML format in a declarative way." +msgstr "" +"`Модуль DDL `_ позволяет декларативно " +"описывать схему данных в YAML формате." + +msgid "The schema would look something like this:" +msgstr "Схема будет выглядеть примерно вот так:" + +msgid "" +"spaces:\n" +" users:\n" +" engine: memtx\n" +" is_local: false\n" +" temporary: false\n" +" format:\n" +" - {name: user_id, type: uuid, is_nullable: false}\n" +" - {name: fullname, type: string, is_nullable: false}\n" +" indexes:\n" +" - name: user_id\n" +" unique: true\n" +" parts: [{path: user_id, type: uuid, is_nullable: false}]\n" +" type: HASH" +msgstr "" +"spaces:\n" +" users:\n" +" engine: memtx\n" +" is_local: false\n" +" temporary: false\n" +" format:\n" +" - {name: user_id, type: uuid, is_nullable: false}\n" +" - {name: fullname, type: string, is_nullable: false}\n" +" indexes:\n" +" - name: user_id\n" +" unique: true\n" +" parts: [{path: user_id, type: uuid, is_nullable: false}]\n" +" type: HASH" + +msgid "" +"This alternative is simpler to use, and you do not have to dive deep into " +"Lua." +msgstr "" +"Этот вариант проще для старта: его проще использовать и не нужно вникать в " +"язык Lua." + +msgid "" +"``DDL`` is a built-in :doc:`Cartridge ` module. " +"Cartridge is a cluster solution for Tarantool. In its WebUI, there is a " +"separate tab called \"Schema\". On this tab, you can define the schema, " +"check its correctness, and apply it to the whole cluster." +msgstr "" +"Модуль ``DDL`` встроен по умолчанию в :doc:`Cartridge `.\n" +"Cartridge — это кластерное решение для Tarantool. В его веб-интерфейсе есть\n" +"отдельная вкладка \"Schema\". Там можно написать схему, проверить ее корректность и применить на всем кластере." + +msgid "" +"If you do not use Cartridge, you can still use the DDL module: put the " +"following Lua code into the file that you use to run Tarantool. This file is" +" usually called ``init.lua``." +msgstr "" +"Если вы не используете Cartridge, то чтобы использовать модуль DDL, нужно " +"вставить нижеприведенный код на Lua в файл, с которым вы запускаете " +"Tarantool. Обычно это ``init.lua``." + +msgid "" +"local yaml = require('yaml')\n" +"local ddl = require('ddl')\n" +"\n" +"box.cfg{}\n" +"\n" +"local fh = io.open('ddl.yml', 'r')\n" +"local schema = yaml.decode(fh:read('*all'))\n" +"fh:close()\n" +"local ok, err = ddl.check_schema(schema)\n" +"if not ok then\n" +" print(err)\n" +"end\n" +"local ok, err = ddl.set_schema(schema)\n" +"if not ok then\n" +" print(err)\n" +"end" +msgstr "" +"local yaml = require('yaml')\n" +"local ddl = require('ddl')\n" +"\n" +"box.cfg{}\n" +"\n" +"local fh = io.open('ddl.yml', 'r')\n" +"local schema = yaml.decode(fh:read('*all'))\n" +"fh:close()\n" +"local ok, err = ddl.check_schema(schema)\n" +"if not ok then\n" +" print(err)\n" +"end\n" +"local ok, err = ddl.set_schema(schema)\n" +"if not ok then\n" +" print(err)\n" +"end" + +msgid "" +"It is forbidden to modify the data schema in DDL after it has been applied. " +"For migration, there are different scenarios described below." +msgstr "" +"Менять схему в самом DDL после ее применения нельзя. Для миграций есть " +"несколько подходов — они описаны ниже." diff --git a/locale/ru/LC_MESSAGES/concepts/data_model/value_store.po b/locale/ru/LC_MESSAGES/concepts/data_model/value_store.po new file mode 100644 index 0000000000..9c6569083e --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/data_model/value_store.po @@ -0,0 +1,798 @@ +msgid "Data storage" +msgstr "Хранение данных" + +msgid "Tuples" +msgstr "Кортежи" + +msgid "Tarantool operates data in the form of tuples." +msgstr "Tarantool обрабатывает данные в виде кортежей." + +msgid "tuple" +msgstr "кортеж" + +msgid "" +"A tuple is a group of data values in Tarantool's memory. Think of it as a " +"\"database record\" or a \"row\". The data values in the tuple are called " +":term:`fields `." +msgstr "" +"Кортеж — это группа значений данных в памяти Tarantool. По сути, это " +"\"запись в базе данных\" или \"строка\". Значения данных в кортеже " +"называются :term:`полями `." + +msgid "" +"When Tarantool returns a tuple value in the console, by default, it uses " +":ref:`YAML ` format, for example: ``[3, 'Ace of Base', " +"1993]``." +msgstr "" +"Когда Tarantool выводит значение кортежа в консоль, по умолчанию " +"используется формат :ref:`YAML `, например: ``[3, 'Ace " +"of Base', 1993]``." + +msgid "" +"Internally, Tarantool stores tuples as `MsgPack " +"`_ arrays." +msgstr "" +"В Tarantool кортежи хранятся в виде массивов в формате `MsgPack " +"`_." + +msgid "field" +msgstr "поле" + +msgid "" +"Fields are distinct data values, contained in a tuple. They play the same " +"role as \"row columns\" or \"record fields\" in relational databases, with a" +" few improvements:" +msgstr "" +"Поля — это отдельные значения данных, которые содержатся в кортеже. Они " +"играют ту же роль, что и \"столбцы\" или \"поля записи\" в реляционных базах" +" данных, но несколько усовершенствованы:" + +msgid "fields can be composite structures, such as arrays or maps," +msgstr "" +"поля могут представлять собой композитные структуры, такие как таблицы типа " +"массива или ассоциативного массива," + +msgid "fields don't need to have names." +msgstr "полям не нужны имена." + +msgid "" +"A given tuple may have any number of fields, and the fields may be of " +"different :ref:`types `." +msgstr "" +"В кортеже может быть любое количество полей, и это могут быть поля разных " +":ref:`типов `." + +msgid "" +"The field's number is the identifier of the field. Numbers are counted from " +"base 1 in Lua and other 1-based languages, or from base 0 in languages like " +"PHP or C/C++. So, ``1`` or ``0`` can be used in some contexts to refer to " +"the first field of a tuple." +msgstr "" +"Номер поля служит его идентификатором. В Lua и некоторых других языках " +"нумерация начинается с 1, в других — с 0 (например, в PHP или C/C++). Таким " +"образом, в некоторых контекстах у первого поля кортежа будет индекс ``1`` " +"или ``0``." + +msgid "Spaces" +msgstr "Спейсы" + +msgid "" +"Tarantool stores tuples in containers called spaces. In the example above, " +"there's a space called ``tester``." +msgstr "" +"Tarantool хранит кортежи в контейнерах, называемых спейсами (space). Спейс в" +" примере выше называется ``tester``." + +msgid "space" +msgstr "спейс" + +msgid "" +"In Tarantool, a space is a primary container that stores data. It is " +"analogous to tables in relational databases. Spaces contain :term:`tuples " +"` -- the Tarantool name for database records. The number of tuples " +"in a space is unlimited." +msgstr "" +"В Tarantool спейс — это первичный контейнер, хранящий данные. Он похож на " +"таблицы в реляционных базах данных. Спейсы содержат :term:`кортежи ` " +"— так в Tarantool называются записи в базе данных. Количество кортежей в " +"спейсе не ограничено." + +msgid "" +"At least one space is required to store data with Tarantool. Each space has " +"the following attributes:" +msgstr "" +"Для хранения данных с помощью Tarantool требуется хотя бы один спейс. У " +"каждого спейса есть следующие атрибуты:" + +msgid "a unique **name** specified by the user," +msgstr "уникальное **имя**, указанное пользователем;" + +msgid "" +"a unique **numeric identifier** which can be specified by the user, but " +"usually is assigned automatically by Tarantool," +msgstr "" +"уникальный **числовой идентификатор**, обычно Tarantool назначает его " +"автоматически, но пользователь может его указать сам, если посчитает нужным;" + +msgid "" +"an **engine**: *memtx* (default) --- in-memory engine, fast but limited in " +"size, or *vinyl* --- on-disk engine for huge data sets." +msgstr "" +"**движок**: *memtx* (по умолчанию) — движок «in-memory», быстрый, но " +"ограниченный в размере, или *vinyl* — дисковый движок для огромных наборов " +"данных." + +msgid "" +"To be functional, a space also needs to have a :ref:`primary index `. It can also have secondary indexes." +msgstr "" +"Для работы спейсу нужен :ref:`первичный индекс `. Также он может\n" +"использовать вторичные индексы." + +msgid "Data types" +msgstr "Типы данных" + +msgid "" +"Tarantool is both a database manager and an application server. Therefore a " +"developer often deals with two type sets: the types of the programming " +"language (such as Lua) and the types of the Tarantool storage format " +"(MsgPack)." +msgstr "" +"Tarantool представляет собой систему управления базой данных и сервер " +"приложений одновременно. Поэтому разработчику часто приходится работать с " +"двумя системами типов данных: типы языка программирования (например, Lua) и " +"типы формата хранения данных Tarantool (MsgPack)." + +msgid "Lua versus MsgPack" +msgstr "Lua в сравнении с MsgPack" + +msgid "Scalar / compound" +msgstr "Скалярный / составной" + +msgid "MsgPack |nbsp| type" +msgstr "MsgPack-тип |nbsp|" + +msgid "Lua type" +msgstr "Lua-тип" + +msgid "Example value" +msgstr "Пример значения" + +msgid "scalar" +msgstr "скалярный" + +msgid "nil" +msgstr "nil" + +msgid "\"`nil`_\"" +msgstr "\"`nil`_\"" + +msgid "``nil``" +msgstr "``nil``" + +msgid "boolean" +msgstr "boolean" + +msgid "\"`boolean`_\"" +msgstr "\"`boolean`_\" (логическое значение)" + +msgid "``true``" +msgstr "``true``" + +msgid "string" +msgstr "string" + +msgid "\"`string`_\"" +msgstr "\"`string`_\"" + +msgid "``'A B C'``" +msgstr "``'A B C'``" + +msgid "integer" +msgstr "integer" + +msgid "\"`number`_\"" +msgstr "\"`number`_\"" + +msgid "``12345``" +msgstr "``12345``" + +msgid "float 64 (double)" +msgstr "float 64 (double)" + +msgid "``1.2345``" +msgstr "``1.2345``" + +msgid "\"`cdata`_\"" +msgstr "\"`cdata`_\"" + +msgid "binary" +msgstr "binary" + +msgid "``[!!binary 3t7e]``" +msgstr "``[!!binary 3t7e]``" + +msgid "ext (for Tarantool decimal)" +msgstr "ext (для decimal в Tarantool)" + +msgid "``1.2``" +msgstr "``1.2``" + +msgid "ext (for Tarantool uuid)" +msgstr "ext (для uuid в Tarantool)" + +msgid "``12a34b5c-de67-8f90-`` |br| ``123g-h4567ab8901``" +msgstr "``12a34b5c-de67-8f90-`` |br| ``123g-h4567ab8901``" + +msgid "compound" +msgstr "составной" + +msgid "map" +msgstr "map (ассоциативный массив)" + +msgid "\"`table`_\" (with string keys)" +msgstr "\"`table`_\" (таблица со строковыми ключами)" + +msgid "``{'a': 5, 'b': 6}``" +msgstr "``{'a': 5, 'b': 6}``" + +msgid "array" +msgstr "array (массив)" + +msgid "\"`table`_\" (with integer keys)" +msgstr "\"`table`_\" (таблица с целочисленными ключами)" + +msgid "``[1, 2, 3, 4, 5]``" +msgstr "``[1, 2, 3, 4, 5]``" + +msgid "tuple (\"`cdata`_\")" +msgstr "tuple (\"`cdata`_\") (кортеж)" + +msgid "``[12345, 'A B C']``" +msgstr "``[12345, 'A B C']``" + +msgid "" +"MsgPack values have variable lengths. So, for example, the smallest number " +"requires only one byte, but the largest number requires nine bytes." +msgstr "" +"Данные в формате MsgPack имеют переменный размер. Так, например, для " +"наименьшего значения number потребуется только один байт, a для наибольшего " +"потребуется девять байтов." + +msgid "Field type details" +msgstr "Описание типов полей" + +msgid "" +"**nil**. In Lua, the nil type has only one possible value, also called " +"``nil``. Tarantool displays it as ``null`` when using the default :ref:`YAML" +" ` format. Nil may be compared to values of any types " +"with == (is-equal) or ~= (is-not-equal), but other comparison operations " +"will not work. Nil may not be used in Lua tables; the workaround is to use " +":ref:`box.NULL ` because ``nil == box.NULL`` is true. Example: " +"``nil``." +msgstr "" +"**nil**. В языке Lua у типа nil есть только одно значение, также называемое " +"``nil``. Tarantool отображает его как ``null`` при использовании формата по " +"умолчанию :ref:`YAML `. Значение nil можно сравнивать " +"со значениями любых типов данных с помощью операторов == (равно) или ~= (не " +"равно), но никакие другие операции сравнения к nil не применимы. Значение " +"nil также нельзя использовать в Lua-таблицах — в качестве обходного пути " +"вместо nil в таком случае можно указать :ref:`box.NULL `, " +"поскольку условие ``nil == box.NULL`` является истинным. Пример: ``nil``." + +msgid "" +"**boolean**. A boolean is either ``true`` or ``false``. Example: ``true``." +msgstr "" +"**boolean**. Логический тип данных boolean принимает значения ``true`` или " +"``false``. Пример: ``true``." + +msgid "" +"**integer**. The Tarantool integer type is for integers between " +"-9223372036854775808 and 18446744073709551615, which is about 18 " +"quintillion. This type corresponds to the number type in Lua and to the " +"integer type in MsgPack. Example: ``-2^63``." +msgstr "" +"**integer**. В Tarantool тип полей integer используется для целых чисел от " +"−9 223 372 036 854 775 808 до 18 446 744 073 709 551 615, то есть до " +"примерно 18 квинтиллионов. Такой тип данных соответствует типам number в Lua" +" и integer в MsgPack. Пример: ``-2^63``." + +msgid "" +"**unsigned**. The Tarantool unsigned type is for integers between 0 and " +"18446744073709551615. So it is a subset of integer. Example: ``123456``." +msgstr "" +"**unsigned**. Тип unsigned в Tarantool используется для целых чисел от 0 до " +"18 446 744 073 709 551 615. Он представляет собой подмножество типа integer." +" Пример: ``123456``." + +msgid "" +"**double**. The double field type exists mainly to be equivalent to " +"Tarantool/SQL's :ref:`DOUBLE data type `. In " +"`msgpuck.h `_ (Tarantool's interface to " +"MsgPack), the storage type is ``MP_DOUBLE`` and the size of the encoded " +"value is always 9 bytes. In Lua, fields of the double type can only contain " +"non-integer numeric values and cdata values with double floating-point " +"numbers. Examples: ``1.234``, ``-44``, ``1.447e+44``." +msgstr "" +"**double**. Поле типа double существует главным образом для соответствия " +"типу :ref:`DOUBLE data type ` в Tarantool/SQL . В " +"`msgpuck.h `_ (интерфейс Tarantool к " +"MsgPack) тип в хранилище — ``MP_DOUBLE``, а размер закодированного значения " +"всегда составляет 9 байтов. В Lua поля типа double могут содержать только не" +" целые числовые значения и значения cdata с числами с плавающей точкой " +"двойной точности (double). Примеры: ``1.234``, ``-44``, ``1.447e+44``." + +msgid "" +"To avoid using the wrong kind of values inadvertently, use ``ffi.cast()`` " +"when searching or changing ``double`` fields. For example, instead of " +":samp:`{space_object}:insert`:code:`{`:samp:`{value}`:code:`}` use ``ffi = " +"require('ffi') ...`` " +":samp:`{space_object}:insert`:code:`({ffi.cast('double',`:samp:`{value}`:code:`)})`." +" Example:" +msgstr "" +"Чтобы избежать случайного использования неправильного типа значений, " +"используйте явное преобразование типа ``ffi.cast()``, когда вы ищете или " +"изменяете поля типа ``double``. Например, вместо " +":samp:`{space_object}:insert`:code:`{`:samp:`{value}`:code:`}` используйте " +"``ffi = require('ffi') ...`` " +":samp:`{space_object}:insert`:code:`({ffi.cast('double',`:samp:`{value}`:code:`)})`." +" Пример:" + +msgid "" +"s = box.schema.space.create('s', {format = {{'d', 'double'}}})\n" +"s:create_index('ii')\n" +"s:insert({1.1})\n" +"ffi = require('ffi')\n" +"s:insert({ffi.cast('double', 1)})\n" +"s:insert({ffi.cast('double', tonumber('123'))})\n" +"s:select(1.1)\n" +"s:select({ffi.cast('double', 1)})" +msgstr "" +"s = box.schema.space.create('s', {format = {{'d', 'double'}}})\n" +"s:create_index('ii')\n" +"s:insert({1.1})\n" +"ffi = require('ffi')\n" +"s:insert({ffi.cast('double', 1)})\n" +"s:insert({ffi.cast('double', tonumber('123'))})\n" +"s:select(1.1)\n" +"s:select({ffi.cast('double', 1)})" + +msgid "" +"Arithmetic with cdata ``double`` will not work reliably, so for Lua, it is " +"better to use the ``number`` type. This warning does not apply for " +"Tarantool/SQL because Tarantool/SQL does :ref:`implicit casting " +"`." +msgstr "" +"Арифметические операции с cdata формата ``double`` работают ненадёжно, " +"поэтому для Lua лучше использовать тип ``number``. Это не относится к " +"Tarantool/SQL, так как Tarantool/SQL применяет :ref:`неявное приведение " +"типов `." + +msgid "" +"**number**. The Tarantool number field may have both integer and floating-" +"point values, although in Lua a ``number`` is a double-precision floating-" +"point." +msgstr "" +"**number**. Поле number в Tarantool может содержать значения как целые, так " +"и с плавающей точкой, хотя в Lua тип ``number`` означает число с плавающей " +"точкой двойной точности." + +msgid "" +"Tarantool will try to store a Lua number as floating-point if the value " +"contains a decimal point or is very large (greater than 100 trillion = " +"1e14), otherwise Tarantool will store it as an integer. To ensure that even " +"very large numbers are stored as integers, use the :ref:`tonumber64 ` function, or the LL (Long Long) suffix, or the ULL (Unsigned " +"Long Long) suffix. Here are examples of numbers using regular notation, " +"exponential notation, the ULL suffix and the ``tonumber64`` function: " +"``-55``, ``-2.7e+20``, ``100000000000000ULL``, " +"``tonumber64('18446744073709551615')``." +msgstr "" +"Tarantool по возможности сохраняет числа языка Lua в виде чисел с плавающей " +"запятой, если числовое значение содержит десятичную запятую или если оно " +"очень велико (более 100 триллионов = 1e14). В противном случае Tarantool " +"сохраняет такое значение в виде целого числа. Чтобы даже очень большие " +"величины гарантированно сохранялись как целые числа, используйте функцию " +":ref:`tonumber64 ` или приписывайте в конце суффикс LL " +"(Long Long) или ULL (Unsigned Long Long). Вот примеры записи чисел в обычном" +" представлении, экспоненциальном, с суффиксом ULL и с использованием функции" +" ``tonumber64``: ``−55``, ``−2.7e+20``, ``100000000000000ULL``, " +"``tonumber64('18446744073709551615')``." + +msgid "" +"**decimal**. The Tarantool decimal type is stored as a MsgPack ext " +"(Extension). Values with the decimal type are not floating-point values " +"although they may contain decimal points. They are exact with up to 38 " +"digits of precision. Example: a value returned by a function in the " +":ref:`decimal ` module." +msgstr "" +"**decimal**. Тип данных decimal в Tarantool хранится в формате MsgPack ext " +"(Extension). Значения с типом decimal не являются числами с плавающей " +"запятой, хотя могут содержать десятичную запятую. Они представляют собой " +"числа с точностью до 38 знаков. Пример: значение, которое возвращает функция" +" в модуле :ref:`decimal `." + +msgid "" +"**string**. A string is a variable-length sequence of bytes, usually " +"represented with alphanumeric characters inside single quotes. In both Lua " +"and MsgPack, strings are treated as binary data, with no attempts to " +"determine a string's character set or to perform any string conversion -- " +"unless there is an optional :ref:`collation `. So, usually," +" string sorting and comparison are done byte-by-byte, without any special " +"collation rules applied. For example, numbers are ordered by their point on " +"the number line, so 2345 is greater than 500; meanwhile, strings are ordered" +" by the encoding of the first byte, then the encoding of the second byte, " +"and so on, so ``'2345'`` is less than ``'500'``. Example: ``'A, B, C'``." +msgstr "" +"**string**. Строка (string) представляет собой последовательность байтов " +"переменной длины. Обычно она записывается буквенно-цифровыми символами в " +"одинарных кавычках. Как Lua, так и MsgPack рассматривают строки как двоичные" +" данные, не пытаясь определить кодировку строки или как-то её преобразовать," +" кроме случаев, когда указаны необязательные :ref:`правила сравнения " +"символов `. Таким образом, обычно сортировка и сравнение " +"строк выполняются побайтово, а дополнительные правила сравнения символов не " +"применяются. Например, числа упорядочены по их положению на числовой прямой," +" поэтому 2345 больше, чем 500. Строки же упорядочены сначала по кодировке " +"первого байта, затем по кодировке второго байта и так далее, так что " +"``'2345'`` меньше ``'500'``. Пример: ``'A, B, C'``." + +msgid "" +"**bin**. A bin (binary) value is not directly supported by Lua but there is " +"a Tarantool type ``varbinary`` which is encoded as MsgPack binary. For an " +"(advanced) example showing how to insert varbinary into a database, see the " +"Cookbook Recipe for :ref:`ffi_varbinary_insert `. Example: ``\"\\65 \\66 \\67\"``." +msgstr "" +"**bin**. Значения типа bin (двоичные значения) не поддерживаются " +"непосредственно в Lua, но в Tarantool есть тип ``varbinary``, который " +"кодируется в тип binary из MsgPack. Пример вставки varbinary в базу данных " +"см. в рекомендациях по разработке :ref:`ffi_varbinary_insert ` (продвинутого уровня). Пример: ``\"\\65 \\66 " +"\\67\"``." + +msgid "" +"**uuid**. The Tarantool uuid type is used for :ref:`Universally Unique " +"Identifiers `. Since version :doc:`2.4.1 ` " +"Tarantool stores ``uuid`` values as a :ref:`MsgPack ext ` (Extension)." +msgstr "" +"**uuid**. Тип uuid в Tarantool используется для :ref:`универсальных " +"уникальных идентификаторов (UUID) `. Начиная с версии " +":doc:`2.4.1 `, Tarantool хранит значения ``uuid`` в формате " +":ref:`MsgPack ext ` (Extension)." + +msgid "Example: ``64d22e4d-ac92-4a23-899a-e5934af5479``." +msgstr "Пример: ``64d22e4d-ac92-4a23-899a-e5934af5479``." + +msgid "" +"**array**. An array is represented in Lua with ``{...}`` (`braces " +"`_). Examples: lists of numbers " +"representing points in geometric figures: ``{10, 11}``, ``{3, 5, 9, 10}``." +msgstr "" +"**array**. В Lua массив (array) обозначается ``{...}`` (`фигурными скобками " +"`_). Примеры: списки чисел, которые " +"обозначают точки геометрической фигуры: ``{10, 11}``, ``{3, 5, 9, 10}``." + +msgid "" +"**table**. Lua tables with string keys are stored as MsgPack maps; Lua " +"tables with integer keys starting with 1 are stored as MsgPack arrays. Nils " +"may not be used in Lua tables; the workaround is to use :ref:`box.NULL `. Example: a ``box.space.tester:select()`` request will return a Lua " +"table." +msgstr "" +"**table**. Lua-таблицы со строковыми ключами хранятся в виде ассоциативных " +"массивов MsgPack map. Lua-таблицы с целочисленными ключами, начиная с 1, " +"хранятся в виде массивов MsgPack array. В Lua-таблицах нельзя использовать " +"nil; вместо этого можно использовать :ref:`box.NULL `. Пример: " +"запрос ``box.space.tester:select()`` вернет Lua-таблицу." + +msgid "" +"**tuple**. A tuple is a light reference to a MsgPack array stored in the " +"database. It is a special type (cdata) to avoid conversion to a Lua table on" +" retrieval. A few functions may return tables with multiple tuples. For " +"tuple examples, see :ref:`box.tuple `." +msgstr "" +"**tuple**. Кортеж (tuple) представляет собой легкую ссылку на массив типа " +"MsgPack array, который хранится в базе данных. Это особый тип (cdata), " +"который создан во избежание конвертации в Lua-таблицу при выборке данных. " +"Некоторые функции могут возвращать таблицы с множеством кортежей. Примеры с " +"кортежами см. в разделе :ref:`box.tuple `." + +msgid "" +"**scalar**. Values in a scalar field can be boolean, integer, unsigned, " +"double, number, decimal, string, uuid, or varbinary; but not array, map, or " +"tuple. Examples: ``true``, ``1``, ``'xxx'``." +msgstr "" +"**scalar**. Значения в поле типа scalar могут быть следующих типов: boolean," +" integer, unsigned, double, number, decimal, string, uuid, varbinary. Они не" +" могут иметь тип array, map или tuple. Примеры: ``true``, ``1``, ``'xxx'``." + +msgid "" +"**any**. Values in a field of this type can be boolean, integer, unsigned, " +"double, number, decimal, string, uuid, varbinary, array, map, or tuple. " +"Examples: ``true``, ``1``, ``'xxx'``, ``{box.NULL, 0}``." +msgstr "" +"**any**. Значения в поле типа any могут быть следующих типов: boolean, " +"integer, unsigned, double, number, decimal, string, uuid, varbinary, array, " +"map, tuple. Примеры: ``true``, ``1``, ``'xxx'``, ``{box.NULL, 0}``." + +msgid "Examples of insert requests with different field types:" +msgstr "Примеры запросов вставки с разными типами полей:" + +msgid "" +"tarantool> box.space.K:insert{1,nil,true,'A B C',12345,1.2345}\n" +"---\n" +"- [1, null, true, 'A B C', 12345, 1.2345]\n" +"...\n" +"tarantool> box.space.K:insert{2,{['a']=5,['b']=6}}\n" +"---\n" +"- [2, {'a': 5, 'b': 6}]\n" +"...\n" +"tarantool> box.space.K:insert{3,{1,2,3,4,5}}\n" +"---\n" +"- [3, [1, 2, 3, 4, 5]]\n" +"..." +msgstr "" +"tarantool> box.space.K:insert{1,nil,true,'A B C',12345,1.2345}\n" +"---\n" +"- [1, null, true, 'A B C', 12345, 1.2345]\n" +"...\n" +"tarantool> box.space.K:insert{2,{['a']=5,['b']=6}}\n" +"---\n" +"- [2, {'a': 5, 'b': 6}]\n" +"...\n" +"tarantool> box.space.K:insert{3,{1,2,3,4,5}}\n" +"---\n" +"- [3, [1, 2, 3, 4, 5]]\n" +"..." + +msgid "Indexed field types" +msgstr "Типы индексированных полей" + +msgid "" +"To learn more about what values can be stored in indexed fields, read the " +":ref:`Indexes ` section." +msgstr "" +"О том, какие значения можно хранить в индексированных полях, читайте " +"в разделе :ref:`об индексах `". + +msgid "Collations" +msgstr "Сортировка" + +msgid "" +"By default, when Tarantool compares strings, it uses the so-called **binary " +"collation**. It only considers the numeric value of each byte in a string. " +"For example, the encoding of ``'A'`` (what used to be called the \"ASCII " +"value\") is 65, the encoding of ``'B'`` is 66, and the encoding of ``'a'`` " +"is 98. Therefore, if the string is encoded with ASCII or UTF-8, then ``'A' <" +" 'B' < 'a'``." +msgstr "" +"Когда Tarantool сравнивает строки, по умолчанию он использует **двоичные " +"параметры сортировки** (**binary collation**). При этом он учитывает только " +"числовое значение каждого байта в строке. Например, код символа ``'A'`` " +"(раньше называлась \"значение ASCII\") — число 65, код ``'B'`` — число 66, а" +" код ``'a'`` -- число 98. Поэтому ``'A' < 'B' < 'a'``, если строка " +"закодирована в ASCII или UTF-8." + +msgid "" +"Binary collation is the best choice for fast deterministic simple " +"maintenance and searching with Tarantool indexes." +msgstr "" +"Двоичная сортировка — лучший выбор для быстрого детерминированного простого " +"обслуживания и поиска с использованием индексов Tarantool." + +msgid "" +"But if you want the ordering that you see in phone books and dictionaries, " +"then you need Tarantool's optional collations, such as ``unicode`` and " +"``unicode_ci``, which allow for ``'a' < 'A' < 'B'`` and ``'a' == 'A' < 'B'``" +" respectively." +msgstr "" +"Но если вы хотите такое упорядочение, как в телефонных справочниках и " +"словарях, то вам нужна одна из дополнительных сортировок Tarantool: " +"``unicode`` или ``unicode_ci``. Они обеспечивают ``'a' < 'A' < 'B'`` и ``'a'" +" == 'A' < 'B'`` соответственно." + +msgid "" +"**The unicode and unicode_ci optional collations** use the ordering " +"according to the `Default Unicode Collation Element Table (DUCET) " +"`_" +" and the rules described in `Unicode® Technical Standard #10 Unicode " +"Collation Algorithm (UTS #10 UCA) `_. The " +"only difference between the two collations is about `weights " +"`_:" +msgstr "" +"Дополнительные виды сортировки **unicode и unicode_ci** обеспечивают " +"упорядочение в соответствии с `Таблицей сортировки символов Юникода по " +"умолчанию (DUCET) " +"`_" +" и правилами, указанными в `Техническом стандарте Юникода №10 -- Алгоритм " +"сортировки по Юникоду (Unicode® Technical Standard #10 Unicode Collation " +"Algorithm (UTS #10 UCA)) `_. Единственное " +"отличие между двумя видами сортировки — `вес " +"`_:" + +msgid "" +"``unicode`` collation observes L1, L2, and L3 weights (strength = " +"'tertiary');" +msgstr "" +"сортировка ``unicode`` принимает во внимание уровни веса L1, L2 и L3 " +"(уровень = 'tertiary', третичный);" + +msgid "" +"``unicode_ci`` collation observes only L1 weights (strength = 'primary'), so" +" for example ``'a' == 'A' == 'á' == 'Á'``." +msgstr "" +"сортировка ``unicode_ci`` принимает во внимание только вес L1 (уровень = " +"'primary', первичный), поэтому, например, ``'a' == 'A' == 'á' == 'Á'``." + +msgid "As an example, take some Russian words:" +msgstr "Для примера возьмем некоторые русские слова:" + +msgid "" +"'ЕЛЕ'\n" +"'елейный'\n" +"'ёлка'\n" +"'еловый'\n" +"'елозить'\n" +"'Ёлочка'\n" +"'ёлочный'\n" +"'ЕЛь'\n" +"'ель'" +msgstr "" +"'ЕЛЕ'\n" +"'елейный'\n" +"'ёлка'\n" +"'еловый'\n" +"'елозить'\n" +"'Ёлочка'\n" +"'ёлочный'\n" +"'ЕЛь'\n" +"'ель'" + +msgid "...and show the difference in ordering and selecting by index:" +msgstr "...и покажем разницу в упорядочении и выборке по индексу:" + +msgid "with ``unicode`` collation:" +msgstr "с сортировкой по ``unicode``:" + +msgid "" +"tarantool> box.space.T:create_index('I', {parts = {{field = 1, type = 'str', collation='unicode'}}})\n" +"...\n" +"tarantool> box.space.T.index.I:select()\n" +"---\n" +"- - ['ЕЛЕ']\n" +" - ['елейный']\n" +" - ['ёлка']\n" +" - ['еловый']\n" +" - ['елозить']\n" +" - ['Ёлочка']\n" +" - ['ёлочный']\n" +" - ['ель']\n" +" - ['ЕЛь']\n" +"...\n" +"tarantool> box.space.T.index.I:select{'ЁлКа'}\n" +"---\n" +"- []\n" +"..." +msgstr "" +"tarantool> box.space.T:create_index('I', {parts = {{field = 1, type = 'str', collation='unicode'}}})\n" +"...\n" +"tarantool> box.space.T.index.I:select()\n" +"---\n" +"- - ['ЕЛЕ']\n" +" - ['елейный']\n" +" - ['ёлка']\n" +" - ['еловый']\n" +" - ['елозить']\n" +" - ['Ёлочка']\n" +" - ['ёлочный']\n" +" - ['ель']\n" +" - ['ЕЛь']\n" +"...\n" +"tarantool> box.space.T.index.I:select{'ЁлКа'}\n" +"---\n" +"- []\n" +"..." + +msgid "with ``unicode_ci`` collation:" +msgstr "с сортировкой по ``unicode_ci``:" + +msgid "" +"tarantool> box.space.T:create_index('I', {parts = {{field = 1, type ='str', collation='unicode_ci'}}})\n" +"...\n" +"tarantool> box.space.T.index.I:select()\n" +"---\n" +"- - ['ЕЛЕ']\n" +" - ['елейный']\n" +" - ['ёлка']\n" +" - ['еловый']\n" +" - ['елозить']\n" +" - ['Ёлочка']\n" +" - ['ёлочный']\n" +" - ['ЕЛь']\n" +"...\n" +"tarantool> box.space.T.index.I:select{'ЁлКа'}\n" +"---\n" +"- - ['ёлка']\n" +"..." +msgstr "" +"tarantool> box.space.T:create_index('I', {parts = {{field = 1, type ='str', collation='unicode_ci'}}})\n" +"...\n" +"tarantool> box.space.T.index.I:select()\n" +"---\n" +"- - ['ЕЛЕ']\n" +" - ['елейный']\n" +" - ['ёлка']\n" +" - ['еловый']\n" +" - ['елозить']\n" +" - ['Ёлочка']\n" +" - ['ёлочный']\n" +" - ['ЕЛь']\n" +"...\n" +"tarantool> box.space.T.index.I:select{'ЁлКа'}\n" +"---\n" +"- - ['ёлка']\n" +"..." + +msgid "" +"In all, collation involves much more than these simple examples of upper " +"case / lower case and accented / unaccented equivalence in alphabets. We " +"also consider variations of the same character, non-alphabetic writing " +"systems, and special rules that apply for combinations of characters." +msgstr "" +"Сортировка включает в себя ещё множество аспектов, кроме показанного в этом " +"примере сопоставления букв верхнего и нижнего регистра, с диакритическими " +"знаками и без них, и с учётом алфавита. Учитываются также вариации одного и " +"того же символа, системы неалфавитного письма и применяются специальные " +"правила для комбинаций символов." + +msgid "" +"For English, Russian, and most other languages and use cases, use the " +"\"unicode\" and \"unicode_ci\" collations. If you need Cyrillic letters 'Е' " +"and 'Ё' to have the same level-1 weights, try the Kyrgyz collation." +msgstr "" +"Для английского, русского и большинства других языков используйте " +"\"unicode\" и \"unicode_ci\". Если вам нужно, чтобы у кириллических букв 'Е'" +" и 'Ё' веса 1 уровня были одинаковыми, попробуйте киргизскую сортировку." + +msgid "" +"**The tailored optional collations**: for other languages, Tarantool " +"supplies tailored collations for every modern language that has more than a " +"million native speakers, and for specialized situations such as the " +"difference between dictionary order and telephone book order. Run " +"``box.space._collation:select()`` to see the complete list." +msgstr "" +"**Специализированные дополнительные виды сортировки**: Для других языков " +"Tarantool предлагает специализированные виды сортировки для любого " +"современного языка, на котором говорят более миллиона человек. Кроме того, " +"специализированные дополнительные виды сортировки возможны для особых " +"случаев, когда слова в словаре упорядочиваются не так, как в телефонном " +"справочнике. Чтобы увидеть полный список, выполните команду " +"``box.space._collation:select()``." + +msgid "" +"The tailored collation names have the form ``unicode_[language " +"code]_[strength]``, where language code is a standard 2-character or " +"3-character language abbreviation, and strength is ``s1`` for \"primary " +"strength\" (level-1 weights), ``s2`` for \"secondary\", ``s3`` for " +"\"tertiary\". Tarantool uses the same language codes as the ones in the " +"\"list of tailorable locales\" on man pages of `Ubuntu " +"`_" +" and `Fedora " +"`_." +" Charts explaining the precise differences from DUCET order are in the " +"`Common Language Data Repository " +"`_." +msgstr "" +"Названия специализированных видов сортировки имеют вид ``unicode_[language " +"code]_[strength]``], где language code — это стандартный код языка из 2 или " +"3 символов, а значение strength может быть ``s1`` для уровня \"primary\" " +"(вес уровня 1), ``s2`` для уровня \"secondary\", ``s3`` для уровня " +"\"tertiary\". Tarantool использует те же коды языков, что указаны в списке " +"специализированных вариантов языковых настроек на страницах руководств по " +"`Ubuntu " +"`_" +" и `Fedora " +"`_." +" Схемы, в деталях объясняющие отличия от упорядочения по DUCET, можно найти " +"в `Общем репозитории языковых данных (Common Language Data Repository) " +"`_." diff --git a/locale/ru/LC_MESSAGES/book/box/engines/index.po b/locale/ru/LC_MESSAGES/concepts/engines/index.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/box/engines/index.po rename to locale/ru/LC_MESSAGES/concepts/engines/index.po diff --git a/locale/ru/LC_MESSAGES/book/box/engines/memtx.po b/locale/ru/LC_MESSAGES/concepts/engines/memtx.po similarity index 98% rename from locale/ru/LC_MESSAGES/book/box/engines/memtx.po rename to locale/ru/LC_MESSAGES/concepts/engines/memtx.po index a0d9f914c4..4b3b29451c 100644 --- a/locale/ru/LC_MESSAGES/book/box/engines/memtx.po +++ b/locale/ru/LC_MESSAGES/concepts/engines/memtx.po @@ -96,12 +96,12 @@ msgstr "" msgid "" "Data is stored in :term:`spaces `. Spaces contain database " "records—:term:`tuples `. To access and manipulate the data stored in " -"spaces and tuples, Tarantool builds :doc:`indexes `." +"spaces and tuples, Tarantool builds :doc:`indexes `." msgstr "" "Данные хранятся в :term:`спейсах `. Спейсы содержат записи базы " "данных — :term:`кортежи `. Чтобы обращаться к данным, хранящимся в " "спейсах и кортежах, и изменять их, Tarantool создаёт :doc:`индексы " -"`." +"`." msgid "" "Special `allocators `__ manage memory " @@ -279,9 +279,9 @@ msgstr "" msgid "" "For detailed information about indexes, refer to the " -":doc:`/book/box/indexes` page." +":doc:`/concepts/data_model/indexes` page." msgstr "" -"Подробности про индексы можно найти на странице :doc:`/book/box/indexes`." +"Подробности про индексы можно найти на странице :doc:`/concepts/data_model/indexes`." msgid "Replicating data" msgstr "Репликация данных" @@ -340,11 +340,11 @@ msgstr "" "транзакции." msgid "" -"For more information on replication, refer to the :doc:`corresponding " -"chapter `." +"For more information on replication, refer to the :ref:`corresponding " +"chapter `." msgstr "" -"Более подробные сведения вы найдете в :doc:`главе о репликации " -"`." +"Более подробные сведения вы найдете в :ref:`главе о репликации " +"`." msgid "Summary" msgstr "Ключевые сведения" diff --git a/locale/ru/LC_MESSAGES/book/box/engines/memtx_vinyl_diff.po b/locale/ru/LC_MESSAGES/concepts/engines/memtx_vinyl_diff.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/box/engines/memtx_vinyl_diff.po rename to locale/ru/LC_MESSAGES/concepts/engines/memtx_vinyl_diff.po diff --git a/locale/ru/LC_MESSAGES/book/box/engines/vinyl.po b/locale/ru/LC_MESSAGES/concepts/engines/vinyl.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/box/engines/vinyl.po rename to locale/ru/LC_MESSAGES/concepts/engines/vinyl.po diff --git a/locale/ru/LC_MESSAGES/concepts/index.po b/locale/ru/LC_MESSAGES/concepts/index.po new file mode 100644 index 0000000000..dcc4782aa8 --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/index.po @@ -0,0 +1,13 @@ + +msgid "Database" +msgstr "Функциональность СУБД" + +msgid "" +"In this chapter, we introduce the basic concepts of working with Tarantool " +"as a database manager." +msgstr "" +"В данной главе мы рассмотрим основные понятия при работе с Tarantool в " +"качестве системы управления базой данных." + +msgid "This chapter contains the following sections:" +msgstr "Эта глава состоит из следующих разделов:" diff --git a/locale/ru/LC_MESSAGES/book/replication/index.po b/locale/ru/LC_MESSAGES/concepts/replication/index.po similarity index 90% rename from locale/ru/LC_MESSAGES/book/replication/index.po rename to locale/ru/LC_MESSAGES/concepts/replication/index.po index 8fbb8695d9..dd7025d1a7 100644 --- a/locale/ru/LC_MESSAGES/book/replication/index.po +++ b/locale/ru/LC_MESSAGES/concepts/replication/index.po @@ -1,6 +1,6 @@ -msgid "Replication" -msgstr "Репликация" +msgid "Replication tutorials" +msgstr "Руководство по репликации" msgid "" "Replication allows multiple Tarantool instances to work on copies of the " diff --git a/locale/ru/LC_MESSAGES/book/replication/repl_architecture.po b/locale/ru/LC_MESSAGES/concepts/replication/repl_architecture.po similarity index 94% rename from locale/ru/LC_MESSAGES/book/replication/repl_architecture.po rename to locale/ru/LC_MESSAGES/concepts/replication/repl_architecture.po index c6c307fac8..cf6053508c 100644 --- a/locale/ru/LC_MESSAGES/book/replication/repl_architecture.po +++ b/locale/ru/LC_MESSAGES/concepts/replication/repl_architecture.po @@ -16,10 +16,10 @@ msgstr "" msgid "" "A replica gets all updates from the master by continuously fetching and " -"applying its :ref:`write ahead log (WAL)`. Each record in the" +"applying its :ref:`write ahead log (WAL) `. Each record in the" " WAL represents a single Tarantool data-change request such as " -":ref:`INSERT`, :ref:`UPDATE` or " -":ref:`DELETE`, and is assigned a monotonically growing log" +":ref:`INSERT `, :ref:`UPDATE ` or " +":ref:`DELETE `, and is assigned a monotonically growing log" " sequence number (**LSN**). In essence, Tarantool replication is **row-" "based**: each data-change request is fully deterministic and operates on a " "single :ref:`tuple`. However, unlike a classical row-based " @@ -234,44 +234,9 @@ msgstr "" "системой значений -- см. описание конфигурационного параметра " ":ref:`replicaset_uuid `." -msgid "Replication setup" -msgstr "Настройка репликации" - -msgid "" -"To enable replication, you need to specify two parameters in a ``box.cfg{}``" -" request:" -msgstr "" -"Чтобы включить репликацию, необходимо указать два параметра в запросе " -"``box.cfg{}``:" - -msgid "" -":ref:`replication ` which defines the " -"replication source(s), and" -msgstr "" -":ref:`replication `, который определяет " -"источники репликации, и" - -msgid "" -":ref:`read_only ` which is ``true`` for a replica and " -"``false`` for a master." -msgstr "" -":ref:`read_only ` со значением ``true`` для реплики и " -"``false`` для мастера." - -msgid "" -"Both these parameters are \"dynamic\". This allows a replica to become a " -"master and vice versa on the fly with the help of a ``box.cfg{}`` request." -msgstr "" -"\"Динамические\" параметры репликации можно менять на лету, что позволяет " -"назначать реплику на роль мастера и наоборот. Для этого используется запрос " -"``box.cfg{}``." - -msgid "" -"Later we will give a detailed example of :ref:`bootstrapping a replica set " -"`." -msgstr "" -"Далее подробно рассмотрим пример :ref:`настройки набора реплик `." +msgid "To learn how to enable replication, check the :ref:`how-to guide `." +msgstr "Чтобы узнать, как включить репликацию, перейдите на страницу " +":ref:`практическое руководство `." msgid "Replication roles: master and replica" msgstr "Роли в репликации: мастер и реплика" @@ -485,3 +450,21 @@ msgstr "" msgid "The maximal number of replicas in a mesh is 32." msgstr "Максимальное количество реплик в ячейке -- 32." + +msgid "Orphan status" +msgstr "Статус orphan (одиночный)" + +msgid "" +"During ``box.cfg()``, an instance will try" +" to join all masters listed in :ref:`box.cfg.replication `. If the instance does not succeed with at least the number of " +"masters specified in :ref:`replication_connect_quorum `, then it will switch to " +":ref:`orphan status `." +msgstr "" +"Во время ``box.cfg()`` экземпляр пытается подключиться " +"ко всем мастерам, указанным в :ref:`box.cfg.replication `. Если не было успешно выполнено подключение к количеству " +"мастеров, указанному в :ref:`replication_connect_quorum `, " +"экземпляр переходит в :ref:`статус orphan (одиночный) `." diff --git a/locale/ru/LC_MESSAGES/concepts/replication/repl_leader_elect.po b/locale/ru/LC_MESSAGES/concepts/replication/repl_leader_elect.po new file mode 100644 index 0000000000..9a0f15c560 --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/replication/repl_leader_elect.po @@ -0,0 +1,176 @@ + +msgid "Automated leader election" +msgstr "Автоматические выборы лидера" + +msgid "" +"Starting from version :doc:`2.6.1 `, Tarantool has the " +"built-in functionality managing automated *leader election* in a replica " +"set. This functionality increases the fault tolerance of the systems built " +"on the base of Tarantool and decreases dependency on the external tools for " +"replica set management." +msgstr "" +"В Tarantool, начиная с версии :doc:`2.6.1 `, есть встроенная" +" функциональность для управления автоматическими *выборами лидера* " +"(automated leader election) в наборе реплик (replica set). Эта " +"функциональность повышает отказоустойчивость систем на базе Tarantool и " +"снижает зависимость от внешних инструментов для управления набором реплик." + +msgid "" +"To learn how to configure and monitor automated leader elections, +check the :ref:`how-to guide `." +msgstr "" +"Чтобы узнать, как настраивать и отслеживать автоматические выборы лидера, " +"прочитайте :ref:`практическое руководство `." + +msgid "The following topics are described below:" +msgstr "Ниже описаны следующие темы:" + +msgid "Leader election and synchronous replication" +msgstr "Выборы лидера и синхронная репликация" + +msgid "" +"Leader election and synchronous replication are implemented in Tarantool as " +"a modification of the `Raft " +"`__ algorithm. Raft " +"is an algorithm of synchronous replication and automatic leader election. " +"Its complete description can be found in the `corresponding document " +"`_." +msgstr "" +"В Tarantool используется модификация `Raft " +"`__ — алгоритма " +"синхронной репликации и автоматических выборов лидера. Полное описание " +"алгоритма Raft можно прочитать `в соответствующем документе " +"`_." + +msgid "" +"In Tarantool, :ref:`synchronous replication ` and leader election" +" are supported as two separate subsystems. So it is possible to get " +"synchronous replication but use an alternative algorithm for leader " +"election. And vice versa -- elect a leader in the cluster but don't use " +"synchronous spaces at all. Synchronous replication has a separate " +":ref:`documentation section `. Leader election is described " +"below." +msgstr "" +":ref:`Синхронная репликация ` и выборы лидера в Tarantool " +"реализованы как две независимые подсистемы. Это означает, что можно " +"настроить синхронную репликацию, а для выборов лидера использовать " +"альтернативный алгоритм. Встроенный механизм выборов лидера, в свою очередь," +" не требует использования синхронных спейсов. Синхронной репликации посвящен" +" :ref:`этот раздел документации `. Процесс выборов лидера описан " +"ниже." + +msgid "Leader election process" +msgstr "Процесс выборов лидера" + +msgid "" +"Automated leader election in Tarantool helps guarantee that there is at most" +" one leader at any given moment of time in a replica set. A *leader* is a " +"writable node, and all other nodes are non-writable -- they accept read-only" +" requests exclusively." +msgstr "" +"Автоматические выборы лидера в Tarantool гарантируют, что в каждый момент " +"времени в наборе реплик будет максимум один *лидер* — узел, доступный для " +"записи. Все остальные узлы будут принимать исключительно запросы на чтение." + +msgid "" +"When :ref:`the election is enabled `, the life " +"cycle of a replica set is divided into so-called *terms*. Each term is " +"described by a monotonically growing number. After the first boot, each node" +" has its term equal to 1. When a node sees that it is not a leader and there" +" is no leader available for some time in the replica set, it increases the " +"term and starts a new leader election round." +msgstr "" +"Когда :ref:`функция выборов включена `, жизненный " +"цикл набора реплик разделен на так называемые *термы* (term). Каждый терм " +"описывается монотонно растущим числом. После первой загрузки узла значение " +"его терма равно 1. Когда узел обнаруживает, что не является лидером и при " +"этом лидера в наборе реплик уже какое-то время нет, он увеличивает значение " +"своего терма и начинает новый тур выборов." + +msgid "" +"Leader election happens via votes. The node which started the election votes" +" for itself and sends vote requests to other nodes. Upon receiving vote " +"requests, a node votes for the first of them, and then cannot do anything in" +" the same term but wait for a leader being elected." +msgstr "" +"Выборы лидера происходят посредством голосования. Узел, начинающий выборы, " +"голосует сам за себя и отправляет другим запросы на голос. Каждый экземпляр " +"голосует за первый узел, от которого пришел такой запрос, и далее в течение " +"всего терма ожидает избрания лидера, не выполняя никаких действий." + +msgid "" +"The node that collected a :ref:`quorum of votes ` " +"becomes the leader and notifies other nodes about that. Also, a split vote " +"can happen when no nodes received a quorum of votes. In this case, after a " +":ref:`random timeout `, each node increases its " +"term and starts a new election round if no new vote request with a greater " +"term arrives during this time period. Eventually, a leader is elected." +msgstr "" +"Узел, собравший :ref:`кворум голосов `, становится" +" лидером и оповещает об этом другие узлы. Голоса могут разделиться, если ни " +"один узел не получит кворума. В этом случае спустя :ref:`случайное время " +"` происходят перевыборы: каждый узел увеличивает " +"значение терма и начинает новый тур, если за период ожидания не получил " +"запроса на голос от узла, чей терм больше. В итоге определяется лидер " +"кластера." + +msgid "" +"All the non-leader nodes are called *followers*. The nodes that start a new " +"election round are called *candidates*. The elected leader sends heartbeats " +"to the non-leader nodes to let them know it is alive. So if there are no " +"heartbeats for a period set by the :ref:`replication_timeout " +"` option, a new election starts. Terms " +"and votes are persisted by each instance in order to preserve certain Raft " +"guarantees." +msgstr "" +"Узлы, не являющиеся лидерами, называются *последователями* (followers). " +"Узлы, которые начинают новый тур выборов, называются *кандидатами* " +"(candidates). Избранный лидер отправляет остальным узлам контрольные сигналы" +" (heartbeats), оповещая о том, что он работает (alive). Если контрольные " +"сигналы не приходят в течение времени, заданного параметром " +":ref:`replication_timeout `, начинаются" +" новые выборы. Чтобы алгоритм Raft гарантированно выполнялся, термы и голоса" +" сохраняются на каждом экземпляре." + +msgid "" +"During the election, the nodes prefer to vote for those ones that have the " +"newest data. So as if an old leader managed to send something before its " +"death to a quorum of replicas, that data wouldn't be lost." +msgstr "" +"При голосовании узлы отдают предпочтение экземплярам, где сохранены самые " +"новые данные. Поэтому, если прежний лидер перед тем, как стать недоступным, " +"отправит кворуму реплик какую-либо информацию, она не будет потеряна." + +msgid "" +"When :ref:`election is enabled `, there must be " +"connections between each node pair so as it would be the full mesh topology." +" This is needed because election messages for voting and other internal " +"things need direct connection between the nodes." +msgstr "" +"Необходимо, чтобы все узлы, :ref:`включенные в процесс выборов " +"`, были соединены попарно и образовывали полную " +"ячеистую топологию (full mesh). Для передачи запросов, связанных с " +"голосованием, и других внутренних сообщений требуется прямая связь между " +"узлами." + +msgid "" +"Also, if election is enabled on the node, it won't replicate from any nodes " +"except the newest leader. This is done to avoid the issue when a new leader " +"is elected, but the old leader has somehow survived and tries to send more " +"changes to the other nodes." +msgstr "" +"Любой узел, участвующий в процессе выборов, реплицирует данные только с " +"последнего избранного лидера. Это позволяет избежать ситуации, в которой " +"прежний лидер после выборов нового все еще пытается отправлять изменения на " +"реплики." + +msgid "" +"Term numbers also work as a kind of a filter. For example, you can be sure " +"that if election is enabled on two nodes and ``node1`` has the term number " +"less than ``node2``, then ``node2`` won't accept any transactions from " +"``node1``." +msgstr "" +"Числовые значения термов также выполняют функцию своеобразного фильтра. " +"Например, если на двух узлах включена функция выборов и значение терма " +"``node1`` меньше значения терма ``node2``, то узел ``node2`` не будет " +"принимать транзакций от узла ``node1``." diff --git a/locale/ru/LC_MESSAGES/concepts/replication/repl_monitoring.po b/locale/ru/LC_MESSAGES/concepts/replication/repl_monitoring.po new file mode 100644 index 0000000000..2c53adabe8 --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/replication/repl_monitoring.po @@ -0,0 +1,150 @@ + +msgid "Monitoring a replica set" +msgstr "Мониторинг набора реплик" + +msgid "" +"To learn what instances belong in the replica set, and obtain statistics for" +" all these instances, issue a " +":doc:`/reference/reference_lua/box_info/replication` request:" +msgstr "" +"Чтобы узнать, какие экземпляры входят в набор реплик и получить статистику " +"по всем этим экземплярам, передайте запрос " +":doc:`/reference/reference_lua/box_info/replication`:" + +msgid "" +"tarantool> box.info.replication\n" +"---\n" +" replication:\n" +" 1:\n" +" id: 1\n" +" uuid: b8a7db60-745f-41b3-bf68-5fcce7a1e019\n" +" lsn: 88\n" +" 2:\n" +" id: 2\n" +" uuid: cd3c7da2-a638-4c5d-ae63-e7767c3a6896\n" +" lsn: 31\n" +" upstream:\n" +" status: follow\n" +" idle: 43.187747001648\n" +" peer: replicator@192.168.0.102:3301\n" +" lag: 0\n" +" downstream:\n" +" vclock: {1: 31}\n" +" 3:\n" +" id: 3\n" +" uuid: e38ef895-5804-43b9-81ac-9f2cd872b9c4\n" +" lsn: 54\n" +" upstream:\n" +" status: follow\n" +" idle: 43.187621831894\n" +" peer: replicator@192.168.0.103:3301\n" +" lag: 2\n" +" downstream:\n" +" vclock: {1: 54}\n" +"..." +msgstr "" +"tarantool> box.info.replication\n" +"---\n" +" replication:\n" +" 1:\n" +" id: 1\n" +" uuid: b8a7db60-745f-41b3-bf68-5fcce7a1e019\n" +" lsn: 88\n" +" 2:\n" +" id: 2\n" +" uuid: cd3c7da2-a638-4c5d-ae63-e7767c3a6896\n" +" lsn: 31\n" +" upstream:\n" +" status: follow\n" +" idle: 43.187747001648\n" +" peer: replicator@192.168.0.102:3301\n" +" lag: 0\n" +" downstream:\n" +" vclock: {1: 31}\n" +" 3:\n" +" id: 3\n" +" uuid: e38ef895-5804-43b9-81ac-9f2cd872b9c4\n" +" lsn: 54\n" +" upstream:\n" +" status: follow\n" +" idle: 43.187621831894\n" +" peer: replicator@192.168.0.103:3301\n" +" lag: 2\n" +" downstream:\n" +" vclock: {1: 54}\n" +"..." + +msgid "" +"This report is for a master-master replica set of three instances, each " +"having its own instance id, UUID and log sequence number." +msgstr "" +"Данный отчет сгенерирован для набора реплик из трех экземпляров с " +"конфигурацией мастер-мастер, у каждого из которых есть свой собственный ID " +"экземпляра, UUID и номер записи в журнале." + +msgid "" +"The request was issued at master #1, and the reply includes statistics for " +"the other two masters, given in regard to master #1." +msgstr "" +"Запрос был выполнен с мастера №1, и ответ включает в себя статистику по двум" +" другим мастерам относительно мастера №1." + +msgid "The primary indicators of replication health are:" +msgstr "Основные индикаторы работоспособности репликации:" + +msgid "" +":ref:`idle `, the time (in seconds) " +"since the instance received the last event from a master." +msgstr "" +":ref:`бездействие `, время (в секундах) " +"с момента получения последнего события от мастера." + +#, fuzzy +msgid "" +"If the master has no updates to send to the replicas, it sends heartbeat " +"messages every :ref:`replication_timeout ` seconds. The master is programmed to disconnect if it " +"does not see acknowledgments of the heartbeat messages within " +"``replication_timeout`` * 4 seconds." +msgstr "" +"Если на мастере нет новых данных, требующих репликации, он отправляет на " +"реплики сообщения контрольного сигнала каждые :ref:`replication_timeout " +"` секунд. Мастер запрограммирован на " +"отключение, если он не получает сообщения контрольного сигнала дольше " +"``replication_timeout`` * 4 секунд." + +msgid "" +"Therefore, in a healthy replication setup, ``idle`` should never exceed " +"``replication_timeout``: if it does, either the replication is lagging " +"seriously behind, because the master is running ahead of the replica, or the" +" network link between the instances is down." +msgstr "" +"Таким образом, в работоспособном состоянии значение ``idle`` никогда не " +"должно превышать значение ``replication_timeout``: в противном случае, либо " +"репликация сильно отстает, поскольку мастер опережает реплику, либо " +"отсутствует сетевое подключение между экземплярами." + +msgid "" +":ref:`lag `, the time difference between " +"the local time at the instance, recorded when the event was received, and " +"the local time at another master recorded when the event was written to the " +":ref:`write ahead log ` on that master." +msgstr "" +":ref:`отставание `, разница во времени " +"между локальным временем на экземпляре, зарегистрированным при получении " +"события, и локальное время на другом мастере, зарегистрированное при записи " +"события в :ref:`журнал упреждающей записи ` на этом мастере." + +msgid "" +"Since the ``lag`` calculation uses the operating system clocks from two " +"different machines, do not be surprised if it’s negative: a time drift may " +"lead to the remote master clock being consistently behind the local " +"instance's clock." +msgstr "" +"Поскольку при расчете ``отставания`` используются часы операционной системы " +"с двух разных машин, не удивляйтесь, получив отрицательное число: смещение " +"во времени может привести к постоянному запаздыванию времени на удаленном " +"мастере относительно часов на локальном экземпляре." + +msgid "For multi-master configurations, ``lag`` is the maximal lag." +msgstr "Для многомастерной конфигурации это максимально возможное отставание." diff --git a/locale/ru/LC_MESSAGES/concepts/replication/repl_problem_solving.po b/locale/ru/LC_MESSAGES/concepts/replication/repl_problem_solving.po new file mode 100644 index 0000000000..175d08719e --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/replication/repl_problem_solving.po @@ -0,0 +1,447 @@ + +msgid "Resolving replication conflicts" +msgstr "Решение конфликтов репликации" + +msgid "Solving problems with master-master replication" +msgstr "Устранение конфликтов репликации мастер-мастер" + +msgid "" +"Tarantool guarantees that every update is applied only once on every " +"replica. However, due to the asynchronous nature of replication, the order " +"of updates is not guaranteed. We now analyze this problem with more details," +" provide examples of replication going out of sync, and suggest solutions." +msgstr "" +"Tarantool гарантирует, что все обновления применяются однократно на каждой " +"реплике. Однако, поскольку репликация носит асинхронный характер, порядок " +"обновлений не гарантируется. Сейчас мы проанализируем данную проблему более " +"подробно с примерами рассинхронизации репликации и предложим соответствующие" +" решения." + +msgid "Replacing the same primary key" +msgstr "Замена по одному и тому же первичному ключу" + +msgid "" +"**Case 1:** You have two instances of Tarantool. For example, you try to " +"make a ``replace`` operation with the same primary key on both instances in " +"the same time. This will cause a conflict over which tuple to save and which" +" one to discard." +msgstr "" +"**Кейс 1:** у вас есть два экземпляра Тарантула. Например, вы пытаетесь " +"сделать операцию замены одного и того же первичного ключа на обоих " +"экземплярах одновременно. Случится конфликт из-за того, какой кортеж " +"сохранить, а какой отбросить." + +msgid "" +"Tarantool :ref:`trigger functions ` can help here to implement the" +" rules of conflict resolution on some condition. For example, if you have a " +"timestamp, you can declare saving the tuple with the bigger one." +msgstr "" +":ref:`Триггер-функции ` Тарантула могут помочь в реализации правил" +" разрешения конфликтов при определенных условиях. Например, если у вас есть " +"метка времени, то можно указать, что сохранять нужно кортеж с большей " +"меткой." + +msgid "" +"First, you need a :ref:`before_replace() ` trigger" +" on the space which may have conflicts. In this trigger you can compare the " +"old and new replica records and choose which one to use (or skip the update " +"entirely, or merge two records together)." +msgstr "" +"Во-первых, вам нужно повесить триггер :ref:`before_replace() ` на спейс, в котором могут быть конфликты. В этом триггере " +"вы можете сравнить старую и новую записи реплики и выбрать, какую из них " +"использовать (или полностью пропустить обновление, или объединить две записи" +" вместе)." + +msgid "" +"Then you need to set the trigger at the right time, before the space starts " +"to receive any updates. The way you usually set the ``before_replace`` " +"trigger is right when the space is created, so you need a trigger to set " +"another trigger on the system space ``_space``, to capture the moment when " +"your space is created and set the trigger there. This can be an " +":ref:`on_replace() ` trigger." +msgstr "" +"Затем вам нужно установить триггер в нужное время, прежде чем спейс начнет " +"получать обновления. Триггер ``before_replace`` нужно устанавливать в тот " +"момент, когда спейс создается, поэтому еще нужен триггер, чтобы установить " +"другой триггер на системном спейсе ``_space``, чтобы поймать момент, когда " +"ваш спейс создается, и установить триггер там. Для этого подходит триггер " +":ref:`on_replace() `." + +msgid "" +"The difference between ``before_replace`` and ``on_replace`` is that " +"``on_replace`` is called after a row is inserted into the space, and " +"``before_replace`` is called before that." +msgstr "" +"Разница между ``before_replace`` и ``on_replace`` заключается в том, что " +"``on_replace`` вызывается после вставки строки в спейс, а ``before_replace``" +" вызывается перед ней." + +msgid "" +"To set a ``_space:on_replace()`` trigger correctly, you also need the right " +"timing. The best timing to use it is when ``_space`` is just created, which " +"is the :ref:`box.ctl.on_schema_init() ` trigger." +msgstr "" +"Устанавливать триггер ``_space:on_replace()`` также нужно в определенный " +"момент. Лучшее время для его использования -- это когда только что создан " +"``_space``, что является триггером на :ref:`box.ctl.on_schema_init() " +"`." + +msgid "" +"You will also need to utilize ``box.on_commit`` to get access to the space " +"being created. The resulting snippet would be the following:" +msgstr "" +"Вам также нужно использовать ``box.on_commit``, чтобы получить доступ к " +"создаваемому спейсу. В результате код будет выглядеть следующим образом:" + +msgid "" +"local my_space_name = 'my_space'\n" +"local my_trigger = function(old, new) ... end -- your function resolving a conflict\n" +"box.ctl.on_schema_init(function()\n" +" box.space._space:on_replace(function(old_space, new_space)\n" +" if not old_space and new_space and new_space.name == my_space_name then\n" +" box.on_commit(function()\n" +" box.space[my_space_name]:before_replace(my_trigger)\n" +" end\n" +" end\n" +" end)\n" +"end)" +msgstr "" +"local my_space_name = 'my_space'\n" +"local my_trigger = function(old, new) ... end -- ваша функция, устраняющая конфликт\n" +"box.ctl.on_schema_init(function()\n" +" box.space._space:on_replace(function(old_space, new_space)\n" +" if not old_space and new_space and new_space.name == my_space_name then\n" +" box.on_commit(function()\n" +" box.space[my_space_name]:before_replace(my_trigger)\n" +" end\n" +" end\n" +" end)\n" +"end)" + +msgid "Preventing duplicate insert" +msgstr "Предотвращение дублирующей вставки" + +msgid "" +"**Case 2:** In a replica set of two masters, suppose master #1 tries to " +"``insert`` a tuple with the same unique key:" +msgstr "" +"**Кейс 2:** Предположим, что в наборе реплик с двумя мастерами мастер №1 " +"пытается вставить кортеж с одинаковым уникальным ключом:" + +msgid "tarantool> box.space.tester:insert{1, 'data'}" +msgstr "tarantool> box.space.tester:insert{1, 'data'}" + +msgid "" +"This would cause an error saying ``Duplicate key exists in unique index " +"'primary' in space 'tester'`` and the replication would be stopped. (This is" +" the behavior when the :ref:`replication_skip_conflict ` configuration parameter has its default " +"recommended value, ``false``.)" +msgstr "" +"Это вызовет сообщение об ошибке дубликата ключа (``Duplicate key exists in " +"unique index 'primary' in space 'tester'``), и репликация остановится. Такое" +" поведение системы обеспечивается использованием рекомендуемого значения " +"``false`` (по умолчанию) для конфигурационного параметра " +":ref:`replication_skip_conflict `." + +msgid "" +"$ # error messages from master #1\n" +"2017-06-26 21:17:03.233 [30444] main/104/applier/rep_user@100.96.166.1 I> can't read row\n" +"2017-06-26 21:17:03.233 [30444] main/104/applier/rep_user@100.96.166.1 memtx_hash.cc:226 E> ER_TUPLE_FOUND:\n" +"Duplicate key exists in unique index 'primary' in space 'tester'\n" +"2017-06-26 21:17:03.233 [30444] relay/[::ffff:100.96.166.178]/101/main I> the replica has closed its socket, exiting\n" +"2017-06-26 21:17:03.233 [30444] relay/[::ffff:100.96.166.178]/101/main C> exiting the relay loop\n" +"\n" +"$ # error messages from master #2\n" +"2017-06-26 21:17:03.233 [30445] main/104/applier/rep_user@100.96.166.1 I> can't read row\n" +"2017-06-26 21:17:03.233 [30445] main/104/applier/rep_user@100.96.166.1 memtx_hash.cc:226 E> ER_TUPLE_FOUND:\n" +"Duplicate key exists in unique index 'primary' in space 'tester'\n" +"2017-06-26 21:17:03.234 [30445] relay/[::ffff:100.96.166.178]/101/main I> the replica has closed its socket, exiting\n" +"2017-06-26 21:17:03.234 [30445] relay/[::ffff:100.96.166.178]/101/main C> exiting the relay loop" +msgstr "" +"$ # сообщения об ошибках от мастера №1\n" +"2017-06-26 21:17:03.233 [30444] main/104/applier/rep_user@100.96.166.1 I> can't read row\n" +"2017-06-26 21:17:03.233 [30444] main/104/applier/rep_user@100.96.166.1 memtx_hash.cc:226 E> ER_TUPLE_FOUND:\n" +"Duplicate key exists in unique index 'primary' in space 'tester'\n" +"2017-06-26 21:17:03.233 [30444] relay/[::ffff:100.96.166.178]/101/main I> the replica has closed its socket, exiting\n" +"2017-06-26 21:17:03.233 [30444] relay/[::ffff:100.96.166.178]/101/main C> exiting the relay loop\n" +"\n" +"$ # сообщения об ошибках от мастера №2\n" +"2017-06-26 21:17:03.233 [30445] main/104/applier/rep_user@100.96.166.1 I> can't read row\n" +"2017-06-26 21:17:03.233 [30445] main/104/applier/rep_user@100.96.166.1 memtx_hash.cc:226 E> ER_TUPLE_FOUND:\n" +"Duplicate key exists in unique index 'primary' in space 'tester'\n" +"2017-06-26 21:17:03.234 [30445] relay/[::ffff:100.96.166.178]/101/main I> the replica has closed its socket, exiting\n" +"2017-06-26 21:17:03.234 [30445] relay/[::ffff:100.96.166.178]/101/main C> exiting the relay loop" + +msgid "" +"If we check replication statuses with ``box.info``, we will see that " +"replication at master #1 is stopped (``1.upstream.status = stopped``). " +"Additionally, no data is replicated from that master (section " +"``1.downstream`` is missing in the report), because the downstream has " +"encountered the same error:" +msgstr "" +"Если мы проверим статус репликации с помощью ``box.info``, то увидим, что " +"репликация на мастере №1 остановлена (``1.upstream.status = stopped``). " +"Кроме того, данные с этого мастера не реплицируются (группа ``1.downstream``" +" отсутствует в отчете), поскольку встречается та же ошибка:" + +msgid "" +"# replication statuses (report from master #3)\n" +"tarantool> box.info\n" +"---\n" +"- version: 1.7.4-52-g980d30092\n" +" id: 3\n" +" ro: false\n" +" vclock: {1: 9, 2: 1000000, 3: 3}\n" +" uptime: 557\n" +" lsn: 3\n" +" vinyl: []\n" +" cluster:\n" +" uuid: 34d13b1a-f851-45bb-8f57-57489d3b3c8b\n" +" pid: 30445\n" +" status: running\n" +" signature: 1000012\n" +" replication:\n" +" 1:\n" +" id: 1\n" +" uuid: 7ab6dee7-dc0f-4477-af2b-0e63452573cf\n" +" lsn: 9\n" +" upstream:\n" +" peer: replicator@192.168.0.101:3301\n" +" lag: 0.00050592422485352\n" +" status: stopped\n" +" idle: 445.8626639843\n" +" message: Duplicate key exists in unique index 'primary' in space 'tester'\n" +" 2:\n" +" id: 2\n" +" uuid: 9afbe2d9-db84-4d05-9a7b-e0cbbf861e28\n" +" lsn: 1000000\n" +" upstream:\n" +" status: follow\n" +" idle: 201.99915885925\n" +" peer: replicator@192.168.0.102:3301\n" +" lag: 0.0015020370483398\n" +" downstream:\n" +" vclock: {1: 8, 2: 1000000, 3: 3}\n" +" 3:\n" +" id: 3\n" +" uuid: e826a667-eed7-48d5-a290-64299b159571\n" +" lsn: 3\n" +" uuid: e826a667-eed7-48d5-a290-64299b159571\n" +"..." +msgstr "" +"# статусы репликации (отчет от мастера №3)\n" +"tarantool> box.info\n" +"---\n" +"- version: 1.7.4-52-g980d30092\n" +" id: 3\n" +" ro: false\n" +" vclock: {1: 9, 2: 1000000, 3: 3}\n" +" uptime: 557\n" +" lsn: 3\n" +" vinyl: []\n" +" cluster:\n" +" uuid: 34d13b1a-f851-45bb-8f57-57489d3b3c8b\n" +" pid: 30445\n" +" status: running\n" +" signature: 1000012\n" +" replication:\n" +" 1:\n" +" id: 1\n" +" uuid: 7ab6dee7-dc0f-4477-af2b-0e63452573cf\n" +" lsn: 9\n" +" upstream:\n" +" peer: replicator@192.168.0.101:3301\n" +" lag: 0.00050592422485352\n" +" status: stopped\n" +" idle: 445.8626639843\n" +" message: Duplicate key exists in unique index 'primary' in space 'tester'\n" +" 2:\n" +" id: 2\n" +" uuid: 9afbe2d9-db84-4d05-9a7b-e0cbbf861e28\n" +" lsn: 1000000\n" +" upstream:\n" +" status: follow\n" +" idle: 201.99915885925\n" +" peer: replicator@192.168.0.102:3301\n" +" lag: 0.0015020370483398\n" +" downstream:\n" +" vclock: {1: 8, 2: 1000000, 3: 3}\n" +" 3:\n" +" id: 3\n" +" uuid: e826a667-eed7-48d5-a290-64299b159571\n" +" lsn: 3\n" +" uuid: e826a667-eed7-48d5-a290-64299b159571\n" +"..." + +msgid "When replication is later manually resumed:" +msgstr "Когда позднее репликация возобновлена вручную:" + +msgid "" +"# resuming stopped replication (at all masters)\n" +"tarantool> original_value = box.cfg.replication\n" +"tarantool> box.cfg{replication={}}\n" +"tarantool> box.cfg{replication=original_value}" +msgstr "" +"# возобновление остановленной репликации (на всех мастерах)\n" +"tarantool> original_value = box.cfg.replication\n" +"tarantool> box.cfg{replication={}}\n" +"tarantool> box.cfg{replication=original_value}" + +msgid "... the faulty row in the write-ahead-log files is skipped." +msgstr "... запись с ошибкой в журнале упреждающей записи пропущена." + +msgid "**Solution #1: replication runs out of sync**" +msgstr "**Решение #1: рассинхронизация репликации**" + +msgid "" +"In a master-master cluster of two instances, suppose we make the following " +"operation:" +msgstr "" +"Предположим, что мы выполняем следующую операцию в кластере из двух " +"экземпляров с конфигурацией мастер-мастер:" + +msgid "tarantool> box.space.tester:upsert({1}, {{'=', 2, box.info.uuid}})" +msgstr "tarantool> box.space.tester:upsert({1}, {{'=', 2, box.info.uuid}})" + +msgid "When this operation is applied on both instances in the replica set:" +msgstr "Когда эта операция применяется на обоих экземплярах в наборе реплик:" + +msgid "" +"# at master #1\n" +"tarantool> box.space.tester:upsert({1}, {{'=', 2, box.info.uuid}})\n" +"# at master #2\n" +"tarantool> box.space.tester:upsert({1}, {{'=', 2, box.info.uuid}})" +msgstr "" +"# на мастере #1\n" +"tarantool> box.space.tester:upsert({1}, {{'=', 2, box.info.uuid}})\n" +"# на мастере #2\n" +"tarantool> box.space.tester:upsert({1}, {{'=', 2, box.info.uuid}})" + +msgid "" +"... we can have the following results, depending on the order of execution:" +msgstr "" +"... можно получить следующие результаты в зависимости от порядка выполнения:" + +msgid "each master’s row contains the UUID from master #1," +msgstr "каждая строка мастера содержит UUID из мастера №1," + +msgid "each master’s row contains the UUID from master #2," +msgstr "каждая строка мастера содержит UUID из мастера №2," + +msgid "master #1 has the UUID of master #2, and vice versa." +msgstr "у мастера №1 UUID мастера №2, и наоборот." + +msgid "**Solution #2: commutative changes**" +msgstr "**Решение #2: коммутативные изменения**" + +msgid "" +"The cases described in the previous paragraphs represent examples of **non-" +"commutative** operations, i.e. operations whose result depends on the " +"execution order. On the contrary, for **commutative operations**, the " +"execution order does not matter." +msgstr "" +"Случаи, описанные в предыдущих абзацах, представляют собой примеры " +"**некоммутативных** операций, т.е. операций, результат которых зависит от " +"порядка их выполнения. Для **коммутативных операций** порядок выполнения " +"значения не имеет." + +msgid "Consider for example the following command:" +msgstr "Рассмотрим, например, следующую команду:" + +msgid "tarantool> box.space.tester:upsert{{1, 0}, {{'+', 2, 1)}" +msgstr "tarantool> box.space.tester:upsert{{1, 0}, {{'+', 2, 1)}" + +msgid "" +"This operation is commutative: we get the same result no matter in which " +"order the update is applied on the other masters." +msgstr "" +"Эта операция коммутативна: получаем одинаковый результат, независимо от " +"порядка, в котором обновление применяется на других мастерах." + +msgid "**Solution #3: trigger usage**" +msgstr "**Решение #3: использование триггера**" + +msgid "" +"The logic and the snippet setting a trigger will be the same here as in case" +" 1. But the trigger function will differ:" +msgstr "" +"Логика и установка триггера будет такой же, как в кейсе 1. Но сама триггер-" +"функция будет отличаться:" + +msgid "" +"local my_space_name = 'test'\n" +"local my_trigger = function(old, new, sp, op)\n" +" -- op: ‘INSERT’, ‘DELETE’, ‘UPDATE’, or ‘REPLACE’\n" +" if new == nil then\n" +" print(\"No new during \"..op, old)\n" +" return -- deletes are ok\n" +" end\n" +" if old == nil then\n" +" print(\"Insert new, no old\", new)\n" +" return new -- insert without old value: ok\n" +" end\n" +" print(op..\" duplicate\", old, new)\n" +" if op == 'INSERT' then\n" +" if new[2] > old[2] then\n" +" -- Creating new tuple will change op to ‘REPLACE’\n" +" return box.tuple.new(new)\n" +" end\n" +" return old\n" +" end\n" +" if new[2] > old[2] then\n" +" return new\n" +" else\n" +" return old\n" +" end\n" +" return\n" +"end\n" +"\n" +"box.ctl.on_schema_init(function()\n" +" box.space._space:on_replace(function(old_space, new_space)\n" +" if not old_space and new_space and new_space.name == my_space_name then\n" +" box.on_commit(function()\n" +" box.space[my_space_name]:before_replace(my_trigger)\n" +" end)\n" +" end\n" +" end)\n" +"end)" +msgstr "" +"local my_space_name = 'test'\n" +"local my_trigger = function(old, new, sp, op)\n" +" -- op: ‘INSERT’, ‘DELETE’, ‘UPDATE’, or ‘REPLACE’\n" +" if new == nil then\n" +" print(\"No new during \"..op, old)\n" +" return -- удаление допустимо\n" +" end\n" +" if old == nil then\n" +" print(\"Insert new, no old\", new)\n" +" return new -- вставка без старого значения допустима\n" +" end\n" +" print(op..\" duplicate\", old, new)\n" +" if op == 'INSERT' then\n" +" if new[2] > old[2] then\n" +" -- Создание нового кортежа сменит оператор на REPLACE\n" +" return box.tuple.new(new)\n" +" end\n" +" return old\n" +" end\n" +" if new[2] > old[2] then\n" +" return new\n" +" else\n" +" return old\n" +" end\n" +" return\n" +"end\n" +"\n" +"box.ctl.on_schema_init(function()\n" +" box.space._space:on_replace(function(old_space, new_space)\n" +" if not old_space and new_space and new_space.name == my_space_name then\n" +" box.on_commit(function()\n" +" box.space[my_space_name]:before_replace(my_trigger)\n" +" end)\n" +" end\n" +" end)\n" +"end)" diff --git a/locale/ru/LC_MESSAGES/concepts/replication/repl_recover.po b/locale/ru/LC_MESSAGES/concepts/replication/repl_recover.po new file mode 100644 index 0000000000..6ba3cc6e9a --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/replication/repl_recover.po @@ -0,0 +1,195 @@ + +msgid "Recovering from a degraded state" +msgstr "Восстановление после сбоя" + +msgid "" +"\"Degraded state\" is a situation when the master becomes unavailable -- due" +" to hardware or network failure, or due to a programming bug." +msgstr "" +"\"Сбой\" -- это ситуация, когда мастер становится недоступен вследствие " +"проблем с оборудованием, сетевых неполадок или программной ошибки." + +msgid "" +"In a master-replica set, if a master disappears, error messages appear on " +"the replicas stating that the connection is lost:" +msgstr "" +"В конфигурации мастер-реплика, если мастер пропадает, на репликах выводятся " +"сообщения об ошибке с указанием потери соединения:" + +msgid "" +"$ # messages from a replica's log\n" +"2017-06-14 16:23:10.993 [19153] main/105/applier/replicator@192.168.0. I> can't read row\n" +"2017-06-14 16:23:10.993 [19153] main/105/applier/replicator@192.168.0. coio.cc:349 !> SystemError\n" +"unexpected EOF when reading from socket, called on fd 17, aka 192.168.0.101:57815,\n" +"peer of 192.168.0.101:3301: Broken pipe\n" +"2017-06-14 16:23:10.993 [19153] main/105/applier/replicator@192.168.0. I> will retry every 1 second\n" +"2017-06-14 16:23:10.993 [19153] relay/[::ffff:192.168.0.101]:/101/main I> the replica has closed its socket, exiting\n" +"2017-06-14 16:23:10.993 [19153] relay/[::ffff:192.168.0.101]:/101/main C> exiting the relay loop" +msgstr "" +"$ # сообщения из журнала реплики\n" +"2017-06-14 16:23:10.993 [19153] main/105/applier/replicator@192.168.0. I> can't read row\n" +"2017-06-14 16:23:10.993 [19153] main/105/applier/replicator@192.168.0. coio.cc:349 !> SystemError\n" +"unexpected EOF when reading from socket, called on fd 17, aka 192.168.0.101:57815,\n" +"peer of 192.168.0.101:3301: Broken pipe\n" +"2017-06-14 16:23:10.993 [19153] main/105/applier/replicator@192.168.0. I> will retry every 1 second\n" +"2017-06-14 16:23:10.993 [19153] relay/[::ffff:192.168.0.101]:/101/main I> the replica has closed its socket, exiting\n" +"2017-06-14 16:23:10.993 [19153] relay/[::ffff:192.168.0.101]:/101/main C> exiting the relay loop" + +msgid "... and the master's status is reported as \"disconnected\":" +msgstr "... а статус мастера выводится как \"отключенный\" (disconnected):" + +msgid "" +"# report from replica #1\n" +"tarantool> box.info.replication\n" +"---\n" +"- 1:\n" +" id: 1\n" +" uuid: 70e8e9dc-e38d-4046-99e5-d25419267229\n" +" lsn: 542\n" +" upstream:\n" +" peer: replicator@192.168.0.101:3301\n" +" lag: 0.00026607513427734\n" +" status: disconnected\n" +" idle: 182.36929893494\n" +" message: connect, called on fd 13, aka 192.168.0.101:58244\n" +" 2:\n" +" id: 2\n" +" uuid: fb252ac7-5c34-4459-84d0-54d248b8c87e\n" +" lsn: 0\n" +" 3:\n" +" id: 3\n" +" uuid: fd7681d8-255f-4237-b8bb-c4fb9d99024d\n" +" lsn: 0\n" +" downstream:\n" +" vclock: {1: 542}\n" +"..." +msgstr "" +"# отчет от реплики № 1\n" +"tarantool> box.info.replication\n" +"---\n" +"- 1:\n" +" id: 1\n" +" uuid: 70e8e9dc-e38d-4046-99e5-d25419267229\n" +" lsn: 542\n" +" upstream:\n" +" peer: replicator@192.168.0.101:3301\n" +" lag: 0.00026607513427734\n" +" status: disconnected\n" +" idle: 182.36929893494\n" +" message: connect, called on fd 13, aka 192.168.0.101:58244\n" +" 2:\n" +" id: 2\n" +" uuid: fb252ac7-5c34-4459-84d0-54d248b8c87e\n" +" lsn: 0\n" +" 3:\n" +" id: 3\n" +" uuid: fd7681d8-255f-4237-b8bb-c4fb9d99024d\n" +" lsn: 0\n" +" downstream:\n" +" vclock: {1: 542}\n" +"..." + +msgid "" +"# report from replica #2\n" +"tarantool> box.info.replication\n" +"---\n" +"- 1:\n" +" id: 1\n" +" uuid: 70e8e9dc-e38d-4046-99e5-d25419267229\n" +" lsn: 542\n" +" upstream:\n" +" peer: replicator@192.168.0.101:3301\n" +" lag: 0.00027203559875488\n" +" status: disconnected\n" +" idle: 186.76988101006\n" +" message: connect, called on fd 13, aka 192.168.0.101:58253\n" +" 2:\n" +" id: 2\n" +" uuid: fb252ac7-5c34-4459-84d0-54d248b8c87e\n" +" lsn: 0\n" +" upstream:\n" +" status: follow\n" +" idle: 186.76960110664\n" +" peer: replicator@192.168.0.102:3301\n" +" lag: 0.00020599365234375\n" +" 3:\n" +" id: 3\n" +" uuid: fd7681d8-255f-4237-b8bb-c4fb9d99024d\n" +" lsn: 0\n" +"..." +msgstr "" +"# отчет от реплики № 2\n" +"tarantool> box.info.replication\n" +"---\n" +"- 1:\n" +" id: 1\n" +" uuid: 70e8e9dc-e38d-4046-99e5-d25419267229\n" +" lsn: 542\n" +" upstream:\n" +" peer: replicator@192.168.0.101:3301\n" +" lag: 0.00027203559875488\n" +" status: disconnected\n" +" idle: 186.76988101006\n" +" message: connect, called on fd 13, aka 192.168.0.101:58253\n" +" 2:\n" +" id: 2\n" +" uuid: fb252ac7-5c34-4459-84d0-54d248b8c87e\n" +" lsn: 0\n" +" upstream:\n" +" status: follow\n" +" idle: 186.76960110664\n" +" peer: replicator@192.168.0.102:3301\n" +" lag: 0.00020599365234375\n" +" 3:\n" +" id: 3\n" +" uuid: fd7681d8-255f-4237-b8bb-c4fb9d99024d\n" +" lsn: 0\n" +"..." + +msgid "" +"To declare that one of the replicas must now take over as a new master:" +msgstr "Чтобы объявить, что одна из реплик должна стать новым мастером:" + +msgid "Make sure that the old master is gone for good:" +msgstr "Убедитесь, что старый мастер окончательно недоступен:" + +msgid "" +"change network routing rules to avoid any more packets being delivered to " +"the master, or" +msgstr "" +"измените правила маршрутизации в сети, чтобы больше не отправлять пакеты на " +"мастер, или" + +msgid "shut down the master instance, if you have access to the machine, or" +msgstr "отключите мастер-экземпляр, если у вас есть доступ к машине, или" + +msgid "power off the container or the machine." +msgstr "отключите питание контейнера или машины." + +msgid "" +"Say ``box.cfg{read_only=false, listen=URI}`` on the replica, and " +"``box.cfg{replication=URI}`` on the other replicas in the set." +msgstr "" +"Выполните ``box.cfg{read_only=false, listen=URI}`` на реплике и " +"``box.cfg{replication=URI}`` на других репликах в наборе." + +msgid "" +"If there are updates on the old master that were not propagated before the " +"old master went down, :ref:`re-apply them manually ` to the new master using ``tarantoolctl cat`` and " +"``tarantoolctl play`` commands." +msgstr "" +"Если на старом мастере есть обновления, не переданные до выхода старого " +"мастера из строя, :ref:`примените их вручную ` на новом мастере с помощью команд ``tarantoolctl cat`` и " +"``tarantoolctl play``." + +msgid "" +"There is no automatic way for a replica to detect that the master is gone " +"forever, since sources of failure and replication environments vary " +"significantly. So the detection of degraded state requires an external " +"observer." +msgstr "" +"Реплика не может автоматически определить, что мастер не будет доступен в " +"будущем, поскольку причины отказа и среды репликации могут существенно " +"отличаться друг от друга. Поэтому обнаруживать сбой должен человек." diff --git a/locale/ru/LC_MESSAGES/concepts/replication/repl_reseed.po b/locale/ru/LC_MESSAGES/concepts/replication/repl_reseed.po new file mode 100644 index 0000000000..f3bbda4601 --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/replication/repl_reseed.po @@ -0,0 +1,51 @@ + +msgid "Reseeding a replica" +msgstr "Перезагрузка реплики" + +msgid "" +"If any of a replica's .xlog/.snap/.run files are corrupted or deleted, you " +"can \"re-seed\" the replica:" +msgstr "" +"Если один из файлов формата .xlog/.snap/.run на реплике поврежден или " +"удален, можно \"перезагрузить\" реплику данными:" + +msgid "" +"Stop the replica and destroy all local database files (the ones with " +"extensions .xlog/.snap/.run/.inprogress)." +msgstr "" +"Остановите реплику и удалите все локальные файлы базы данных (с расширениями" +" .xlog/.snap/.run/.inprogress)." + +msgid "Delete the replica's record from the following locations:" +msgstr "Удалите запись о реплике из следующих мест:" + +msgid "" +"the ``replication`` parameter at all running instances in the replica set." +msgstr "" +"параметр ``replication`` на всех работающих экземплярах в наборе реплик." + +msgid "the ``box.space._cluster`` tuple on the master instance." +msgstr "кортеж ``box.space._cluster`` на мастер-экземпляре." + +msgid "" +"See section :ref:`Removing instances ` for " +"details." +msgstr "" +"Для получения подробной информации см. Раздел :ref:`Удаление экземпляров " +"`." + +msgid "" +"Restart the replica with the same instance file to contact the master again." +" The replica will then catch up with the master by retrieving all the " +"master’s tuples." +msgstr "" +"Перезапустите реплику с тем же файлом экземпляра для повторного подключения " +"к мастеру. Реплика синхронизируется с мастером после получения всех " +"кортежей." + +msgid "" +"Remember that this procedure works only if the master’s WAL files are " +"present." +msgstr "" +"Следует отметить, что эта процедура сработает только в том случае, если на " +"мастере есть WAL-файлы." diff --git a/locale/ru/LC_MESSAGES/concepts/replication/repl_sync.po b/locale/ru/LC_MESSAGES/concepts/replication/repl_sync.po new file mode 100644 index 0000000000..320b78fbda --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/replication/repl_sync.po @@ -0,0 +1,129 @@ + +msgid "Synchronous replication" +msgstr "Синхронная репликация" + +msgid "Overview" +msgstr "Общие сведения" + +msgid "" +"By default, replication in Tarantool is **asynchronous**: if a transaction " +"is committed locally on a master node, it does not mean it is replicated " +"onto any replicas. If a master responds success to a client and then dies, " +"after failover to a replica, from the client's point of view the transaction" +" will disappear." +msgstr "" +"По умолчанию репликация в Tarantool **асинхронная**: локальный коммит " +"транзакции на мастере не означает, что эта транзакция будет сразу же " +"выполнена на репликах. Если мастер сообщит клиенту об успешном выполнении " +"операции, а потом прекратит работу и после отказа восстановится на реплике, " +"то с точки зрения клиента транзакция пропадет." + +msgid "" +"**Synchronous** replication exists to solve this problem. Synchronous " +"transactions are not considered committed and are not responded to a client " +"until they are replicated onto some number of replicas." +msgstr "" +"Эту проблему решает **синхронная** репликация. Каждая синхронная транзакция " +"проходит коммит лишь после репликации на некотором количестве экземпляров, и" +" только тогда клиенту приходит ответ о завершении транзакции." + +msgid "Synchronous and asynchronous transactions" +msgstr "Синхронные и асинхронные транзакции" + +msgid "" +"A killer feature of Tarantool's synchronous replication is its being *per-" +"space*. So, if you need it only rarely for some critical data changes, you " +"won't pay for it in performance terms." +msgstr "" +"В Tarantool синхронную репликацию можно настроить для отдельных спейсов. Эта" +" удобная функция позволит вам не потерять в производительности, если " +"синхронная репликация нужна вам лишь изредка для изменения критически важных" +" данных." + +msgid "" +"When there is more than one synchronous transaction, they all wait for being" +" replicated. Moreover, if an asynchronous transaction appears, it will also " +"be blocked by the existing synchronous transactions. This behavior is very " +"similar to a regular queue of asynchronous transactions because all the " +"transactions are committed in the same order as they make the " +"``box.commit()`` call. So, here comes **the commit rule**: transactions are " +"committed in the same order as they make the ``box.commit()`` " +"call—regardless of being synchronous or asynchronous." +msgstr "" +"Если наряду с несколькими синхронными транзакциями, ожидающими репликации, " +"совершается асинхронная транзакция, она блокируется синхронными. Коммиты при" +" этом выполняются в той последовательности, в которой для каждой из " +"транзакций вызывается метод ``box.commit()``. Похожим образом работает " +"обычная очередь асинхронных транзакций. Можно сформулировать **правило " +"коммитов**: порядок коммитов соответствует порядку вызова ``box.commit()`` " +"для каждой из транзакций, независимо от того, синхронные транзакции или " +"асинхронные." + +msgid "" +"If one of the waiting synchronous transactions times out and is rolled back," +" it will first roll back all the newer pending transactions. Again, just " +"like how asynchronous transactions are rolled back when WAL write fails. So," +" here comes **the rollback rule:** transactions are always rolled back in " +"the order reversed from the one they make the ``box.commit()`` " +"call—regardless of being synchronous or asynchronous." +msgstr "" +"Если для одной из синхронных транзакций истечет время ожидания, эта " +"транзакция будет отменена, а вместе с ней и все последующие транзакции в " +"очереди на репликацию. Похожим образом отменяются и асинхронные транзакции " +"при ошибке записи в WAL. Действует **правило отмены**: транзакции отменяются" +" в порядке, обратном порядку вызова ``box.commit()`` для каждой из них, " +"независимо от того, синхронные транзакции или асинхронные." + +msgid "" +"One more important thing is that if an asynchronous transaction is blocked " +"by a synchronous transaction, it does not become synchronous as well. This " +"just means it will wait for the synchronous transaction to be committed. But" +" once it is done, the asynchronous transaction will be committed " +"immediately—it won't wait for being replicated itself." +msgstr "" +"Асинхронная транзакция, заблокированная синхронной, не становится сама " +"синхронной, а просто ожидает коммита синхронной транзакции. Как только это " +"произойдет, асинхронная транзакция сразу сможет пройти коммит, не ожидая " +"репликации." + +msgid "Limitations and known problems" +msgstr "Ограничения и известные проблемы" + +msgid "" +"Until version :doc:`2.5.2 `, there was no way to enable " +"synchronous replication for existing spaces, but since 2.5.2 it can be " +"enabled by :ref:`space_object:alter({is_sync = true}) `." +msgstr "" +"До версии :doc:`2.5.2 ` способа настроить синхронную " +"репликацию для существующих спейсов не было. Однако, начиная с версии 2.5.2," +" ее можно включить, вызвав метод :ref:`space_object:alter({is_sync = true}) " +"`." + +msgid "" +"Synchronous transactions work only for master-slave topology. You can have " +"multiple replicas, anonymous replicas, but only one node can make " +"synchronous transactions." +msgstr "" +"Синхронные транзакции работают исключительно в топологии \"мастер-реплика\"." +" В кластере может быть несколько реплик, в том числе анонимных, однако " +"синхронные транзакции должен совершать только один узел." + +msgid "" +"Since Tarantool :doc:`2.10.0 `, anonymous replicas " +"do not participate in the quorum." +msgstr "" +"Начиная с версии Tarantool :doc:`2.10.0 `, анонимные реплики не участвуют в кворуме." + +msgid "Leader election" +msgstr "Выборы лидера" + +msgid "" +"Starting from version :doc:`2.6.1 `, Tarantool has the " +"built-in functionality managing automated leader election in a replica set. " +"For more information, refer to the :ref:`corresponding chapter " +"`." +msgstr "" +"В Tarantool, начиная с версии :doc:`2.6.1 `, есть встроенная" +" функциональность для управления автоматическими выборами лидера (automated " +"leader election) в наборе реплик. Подробности можно найти в " +":ref:`соответствующей главе `." diff --git a/locale/ru/LC_MESSAGES/concepts/sharding/index.po b/locale/ru/LC_MESSAGES/concepts/sharding/index.po new file mode 100644 index 0000000000..592633faaa --- /dev/null +++ b/locale/ru/LC_MESSAGES/concepts/sharding/index.po @@ -0,0 +1,88 @@ + +msgid "" +"Scaling databases in a growing project is often considered one of the most " +"challenging issues. Once a single server cannot withstand the load, scaling " +"methods should be applied." +msgstr "" +"С ростом проекта масштабируемость баз данных часто становится одной из " +"наиболее серьезных проблем. Если отдельный сервер не может справиться с " +"нагрузкой, необходимо применять средства масштабирования." + +msgid "" +"**Sharding** is a database architecture that allows for `horizontal scaling " +"`_," +" which implies that a dataset is partitioned and distributed over multiple " +"servers." +msgstr "" + +msgid "" +"With Tarantool's `vshard `_ module, the" +" tuples of a dataset are distributed across multiple nodes, with a Tarantool" +" database server instance on each node. Each instance handles only a subset " +"of the total data, so larger loads can be handled by simply adding more " +"servers. The initial dataset is partitioned into multiple parts, so each " +"part is stored on a separate server." +msgstr "" +"С помощью модуля `vshard `_ кортежи " +"набора данных распределяются по множеству узлов, на каждом из которых " +"находится экземпляр сервера базы данных Tarantool. Каждый экземпляр " +"обрабатывает лишь подмножество от общего количества данных, поэтому " +"увеличение нагрузки можно компенсировать добавлением новых серверов. " +"Первоначальный набор данных секционируется на множество частей, то есть " +"каждая часть хранится на отдельном сервере." + +msgid "" +"The ``vshard`` module is based on the concept of :ref:`virtual buckets " +"`, where a tuple set is partitioned into a large number of " +"abstract virtual nodes (**virtual buckets**, further just **buckets**) " +"rather than into a smaller number of physical nodes." +msgstr "" +"Модуль ``vshard`` основан на концепции :ref:`виртуальных сегментов `: набор кортежей распределяется на большое количество абстрактных " +"виртуальных узлов (**виртуальных сегментов**, или просто **сегментов** далее" +" по тексту), а не на малое количество физических узлов." + +msgid "" +"The dataset is partitioned using **sharding keys** (bucket id numbers). " +"Hashing a sharding key into a large number of buckets allows seamlessly " +"changing the number of servers in the cluster. The **rebalancing mechanism**" +" distributes buckets evenly among all shards in case some servers were added" +" or removed." +msgstr "" +"Секционирование набора данных осуществляется с помощью **сегментных ключей**" +" (идентификаторов сегментов). Хеширование сегментного ключа в большое " +"количество сегментов позволяет незаметно для пользователя изменять " +"количество серверов в кластере. **Механизм балансирования** распределяет " +"сегменты между шардами при добавлении или удалении каких-либо серверов." + +msgid "" +"The buckets have **states**, so it is easy to monitor the server states. For" +" example, a server instance is active and available for all types of " +"requests, or a failover occurred and the instance accepts only read " +"requests." +msgstr "" +"Для сегментов предусмотрены **состояния**, поэтому можно легко отслеживать " +"состояние сервера. Например, активен ли экземпляр сервера и доступен ли он " +"для всех типов запросов, или же произошел отказ, и сервер принимает только " +"запросы на чтение." + +msgid "" +"The ``vshard`` module provides router and storage API (public and internal) " +"for sharding-aware applications." +msgstr "" +"Модуль ``vshard`` предоставляет общедоступные и внутренние API роутера и " +"хранилища для приложений с поддержкой шардинга." + +msgid "" +"Check out the :ref:`quick start guide ` or " +"learn more about :ref:`how sharding works ` in Tarantool:" +msgstr "" +"Начните с :ref:`руководства по быстрому запуску ` " +"или узнайте подробности об :ref:`архитектуре шардирования ` в Tarantool:" + +msgid "" +"You can also find out more about :ref:`sharding administration ` " +"or dive into the ``vshard`` configuration and API :ref:`reference `." +msgstr "" +"Ознакомьтесь с :ref:`руководством администратора ` по шардированию " +"или перейдите к :ref:`справочнику ` по конфигурации и API модуля ``vshard``." diff --git a/locale/ru/LC_MESSAGES/reference/reference_rock/vshard/vshard_architecture.po b/locale/ru/LC_MESSAGES/concepts/sharding/vshard_architecture.po similarity index 99% rename from locale/ru/LC_MESSAGES/reference/reference_rock/vshard/vshard_architecture.po rename to locale/ru/LC_MESSAGES/concepts/sharding/vshard_architecture.po index 9bcf648382..bfa5e6e727 100644 --- a/locale/ru/LC_MESSAGES/reference/reference_rock/vshard/vshard_architecture.po +++ b/locale/ru/LC_MESSAGES/concepts/sharding/vshard_architecture.po @@ -518,8 +518,8 @@ msgstr "" "неприменимое к перемещаемому сегменту. В этом случае необходимо повторить " "попытку выполнения запроса." -msgid "The `_bucket` system space" -msgstr "Системный спейс `_bucket`" +msgid "The _bucket system space" +msgstr "Системный спейс _bucket" msgid "" "The ``_bucket`` system space of each replica set stores the ids of buckets " diff --git a/locale/ru/LC_MESSAGES/book/box/triggers.po b/locale/ru/LC_MESSAGES/concepts/triggers.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/box/triggers.po rename to locale/ru/LC_MESSAGES/concepts/triggers.po diff --git a/locale/ru/LC_MESSAGES/book/app_server/contributing_module.po b/locale/ru/LC_MESSAGES/dev_guide/contributing_module.po similarity index 83% rename from locale/ru/LC_MESSAGES/book/app_server/contributing_module.po rename to locale/ru/LC_MESSAGES/dev_guide/contributing_module.po index e3f8250db8..e1489c40ca 100644 --- a/locale/ru/LC_MESSAGES/book/app_server/contributing_module.po +++ b/locale/ru/LC_MESSAGES/dev_guide/contributing_module.po @@ -3,19 +3,23 @@ msgid "Contributing a module" msgstr "Добавление собственного модуля" msgid "" -"We have already discussed :ref:`how to create a simple module in Lua for " -"local usage `. Now let's discuss how to create a more " -"advanced Tarantool module and then get it published on `Tarantool rocks page" +"This page discusses how to create a Tarantool module and then get it published on `Tarantool rocks page" " `_ and included in `official Tarantool " "images `_ for Docker." msgstr "" -"Мы уже обсуждали, :ref:`как создать простой модуль на языке Lua для " -"локального использования `.Теперь давайте обсудим, как " -"создать модуль более продвинутого уровня для Tarantool, а затем разместить" +"На этой странице рассказано, как " +"создать модуль для Tarantool, а затем разместить" " его на странице модулей Tarantool `_ и " "включить его в `официальные образы Tarantool " "`_ для Docker." +msgid "" +"To learn how to create a simple module in Lua for local usage, check the corresponding " +":ref:`how-to guide `." +msgstr "" +"Чтобы узнать, как разработать несложный Lua-модуль для локального использования, " +"прочитайте :ref:`практическое руководство `." + msgid "" "To help our contributors, we have created `modulekit " "`_, a set of templates for creating " diff --git a/locale/ru/LC_MESSAGES/dev_guide/internals/box_protocol.po b/locale/ru/LC_MESSAGES/dev_guide/internals/box_protocol.po index bd20d1bea3..e62de8f424 100644 --- a/locale/ru/LC_MESSAGES/dev_guide/internals/box_protocol.po +++ b/locale/ru/LC_MESSAGES/dev_guide/internals/box_protocol.po @@ -2489,12 +2489,12 @@ msgid "FLAGS" msgstr "Сообщения с идентификатором FLAG" msgid "" -"For replication of :doc:`synchronous transactions " -"` a header may contain a key = IPROTO_FLAGS and" +"For replication of :ref:`synchronous transactions " +"` a header may contain a key = IPROTO_FLAGS and" " an MP_UINT value = one or more bits: IPROTO_FLAG_COMMIT or " "IPROTO_FLAG_WAIT_SYNC or IPROTO_FLAG_WAIT_ACK." msgstr "" -"При репликации :doc:`синхронных транзакций ` " +"При репликации :ref:`синхронных транзакций ` " "заголовок может содержать ключ = IPROTO_FLAGS и значение MP_UINT = один или " "несколько битов: IPROTO_FLAG_COMMIT, IPROTO_FLAG_WAIT_SYNC или " "IPROTO_FLAG_WAIT_ACK." diff --git a/locale/ru/LC_MESSAGES/dev_guide/internals/replication/orphan.po b/locale/ru/LC_MESSAGES/dev_guide/internals/replication/orphan.po new file mode 100644 index 0000000000..90e818a4b8 --- /dev/null +++ b/locale/ru/LC_MESSAGES/dev_guide/internals/replication/orphan.po @@ -0,0 +1,299 @@ + +msgid "Orphan status" +msgstr "Статус orphan (одиночный)" + +msgid "" +"Starting with Tarantool version 1.9, there is a change to the procedure when" +" an instance joins a replica set. During ``box.cfg()`` the instance will try" +" to join all masters listed in :ref:`box.cfg.replication `. If the instance does not succeed with at least the number of " +"masters specified in :ref:`replication_connect_quorum `, then it will switch to **orphan status**. " +"While an instance is in orphan status, it is read-only." +msgstr "" +"Начиная с версии Tarantool 1.9, процедура подключения реплики к набору " +"реплик изменяется. Во время ``box.cfg()`` экземпляр попытается подключиться " +"ко всем мастерам, указанным в :ref:`box.cfg.replication `. Если не было успешно выполнено подключение к количеству " +"мастеров, указанному в :ref:`replication_connect_quorum `, экземпляр переходит в **статус orphan** " +"(одиночный). Когда экземпляр находится в статусе orphan, он доступен только " +"для чтения." + +msgid "" +"To \"join\" a master, a replica instance must \"connect\" to the master node" +" and then \"sync\"." +msgstr "" +"Чтобы \"подключиться\" к мастеру, реплика должна \"установить соединение\" с" +" узлом мастера, а затем \"выполнить синхронизацию\"." + +msgid "" +"\"Connect\" means contact the master over the physical network and receive " +"acknowledgment. If there is no acknowledgment after " +":ref:`box.replication_connect_timeout ` seconds (usually 4 seconds), and retries fail," +" then the connect step fails." +msgstr "" +"\"Установка соединения\" означает контакт с мастером по физической сети и " +"получение подтверждения. Если нет подтверждения соединения через " +":ref:`box.replication_connect_timeout ` секунд (обычно 4 секунды), и повторные попытки" +" подключения не сработали, то соединение не установлено." + +msgid "" +"\"Sync\" means receive updates from the master in order to make a local " +"database copy. Syncing is complete when the replica has received all the " +"updates, or at least has received enough updates that the replica's lag (see" +" :ref:`replication.upstream.lag ` in " +"``box.info()``) is less than or equal to the number of seconds specified in " +":ref:`box.cfg.replication_sync_lag `. " +"If ``replication_sync_lag`` is unset (nil) or set to TIMEOUT_INFINITY, then " +"the replica skips the \"sync\" state and switches to \"follow\" immediately." +msgstr "" +"\"Синхронизация\" означает получение обновлений от мастера для создания " +"локальной копии базы данных. Синхронизация завершена, когда реплика получила" +" все обновления или хотя бы получила достаточное количество обновлений, " +"чтобы отставание реплики (см. :ref:`replication.upstream.lag " +"` в ``box.info()``) было меньше или равно" +" количеству секунд, указанному в :ref:`box.cfg.replication_sync_lag " +"`. Если значение " +"``replication_sync_lag`` не задано (nil) или указано как " +"\"TIMEOUT_INFINITY\", то реплика пропускает шаг \"синхронизация\" и сразу же" +" переходит на \"отслеживание\"." + +msgid "" +"In order to leave orphan mode you need to sync with a sufficient number " +"(:ref:`replication_connect_quorum `) of instances. To do so, you may either:" +msgstr "" +"Чтобы вывести узел из одиночного статуса, нужно синхронизировать его с " +"достаточным (т.е. равным :ref:`replication_connect_quorum `) количеством других узлов. Этого можно " +"добиться, выполнив любое из следующих действий:" + +msgid "" +"Set :ref:`replication_connect_quorum ` to a lower value." +msgstr "" +"Уменьшить значение :ref:`replication_connect_quorum `." + +msgid "" +"Reset ``box.cfg.replication`` to exclude instances that cannot be reached or" +" synced with." +msgstr "" +"Убрать из списка ``box.cfg.replication`` недоступные и прочие узлы, с " +"которыми нельзя синхронизироваться." + +msgid "Set ``box.cfg.replication`` to ``\"\"`` (empty string)." +msgstr "" +"Вообще задать ``\"\"`` (пустую строку) в качестве значения " +"``box.cfg.replication``." + +msgid "The following situations are possible." +msgstr "Возможны следующие ситуации." + +msgid "**Situation 1: bootstrap**" +msgstr "**Ситуация 1: настройка**" + +msgid "" +"Here ``box.cfg{}`` is being called for the first time. A replica is joining " +"but no replica set exists yet." +msgstr "" +"Здесь впервые происходит вызов ``box.cfg{}``. Реплика подключается, но " +"набора реплик пока нет." + +msgid "Set status to 'orphan'." +msgstr "Установка статуса 'orphan' (одиночный)." + +msgid "" +"Try to connect to all nodes from ``box.cfg.replication``, or to the number " +"of nodes required by :ref:`replication_connect_quorum `. Retrying up to 3 times in 30 seconds is " +"possible because this is bootstrap, :ref:`replication_connect_timeout " +"` is overridden." +msgstr "" +"Попытка установить соединение со всеми узлами из ``box.cfg.replication`` или" +" с количеством узлов, указанным в параметре :ref:`replication_connect_quorum" +" `. Допускаются три повторные " +"попытки за 30 секунд, поскольку идет стадия настройки, параметр " +":ref:`replication_connect_timeout ` не учитывается." + +msgid "" +"Abort and throw an error if not connected to all nodes in " +"``box.cfg.replication`` or :ref:`replication_connect_quorum " +"`." +msgstr "" +"Прекращение работы и выдача ошибки в случае отсутствия соединения со всеми " +"узлами в ``box.cfg.replication`` или :ref:`replication_connect_quorum " +"`." + +msgid "" +"This instance might be elected as the replica set 'leader'. Criteria for " +"electing a leader include vclock value (largest is best), and whether it is " +"read-only or read-write (read-write is best unless there is no other " +"choice). The leader is the master that other instances must join. The leader" +" is the master that executes :doc:`box.once() " +"` functions." +msgstr "" +"Экземпляр может быть выбран в качестве лидера 'leader' в наборе реплик. " +"Критерии выбора лидера включают в себя значение vclock (чем больше, тем " +"лучше), а также доступность только для чтения или для чтения и записи (лучше" +" всего для чтения и записи, кроме случаев, когда других вариантов нет). " +"Лидер является мастером, к которому должны подключиться другие экземпляры. " +"Лидер является мастером, который выполняет функции :doc:`box.once() " +"`." + +msgid "" +"If this instance is elected as the replica set leader, then perform an " +"\"automatic bootstrap\":" +msgstr "" +"Если данный экземпляр выбран лидером набора реплик, выполняется " +"\"самонастройка\":" + +msgid "Set status to 'running'." +msgstr "Установка статуса 'running' (запущен)." + +msgid "Return from ``box.cfg{}``." +msgstr "Возврат из ``box.cfg{}``." + +msgid "" +"Otherwise this instance will be a replica joining an existing replica set, " +"so:" +msgstr "" +"В противном случае, данный экземпляр будет репликой, которая подключается к " +"существующему набору реплик, поэтому:" + +msgid "" +"Bootstrap from the leader. See examples in section :ref:`Bootstrapping a " +"replica set `." +msgstr "" +"Настройка от лидера. См. примеры в разделе :ref:`Настройка набора реплик " +"`." + +msgid "In background, sync with all the other nodes in the replication set." +msgstr "" +"Синхронизация со всеми остальными узлами в наборе реплик в фоновом режиме." + +msgid "**Situation 2: recovery**" +msgstr "**Ситуация 2: восстановление**" + +msgid "" +"Here ``box.cfg{}`` is not being called for the first time. It is being " +"called again in order to perform recovery." +msgstr "" +"Здесь вызов ``box.cfg{}`` происходит не впервые, а повторно для " +"осуществления восстановления." + +msgid "" +"Perform :ref:`recovery ` from the last local " +"snapshot and the WAL files." +msgstr "" +"Проведение :ref:`восстановления ` из последнего " +"локального снимка и WAL-файлов." + +msgid "" +"Connect to at least :ref:`replication_connect_quorum ` nodes. If failed -- set status to 'orphan'. " +"(Attempts to sync will continue in the background and when/if they succeed " +"then 'orphan' will be changed to 'connected'.)" +msgstr "" +"Установить соединение с количеством узлов не меньшим, чем " +":ref:`replication_connect_quorum `. Если не получается -- установить статус " +"'orphan'. (Попытки синхронизации будут повторяться в фоновом режиме, и " +"когда/если они окажутся успешными, статус 'orphan' сменится на 'connected'.)" + +msgid "" +"If connected - sync with all connected nodes, until the difference is not " +"more than :ref:`replication_sync_lag `" +" seconds." +msgstr "" +"Если соединение установлено - осуществлять синхронизацию со всеми " +"подключенными узлами до тех пор, пока отличия не будут более " +":ref:`replication_sync_lag ` секунд." + +msgid "**Situation 3: configuration update**" +msgstr "**Ситуация 3: обновление конфигурации**" + +msgid "" +"Here ``box.cfg{}`` is not being called for the first time. It is being " +"called again because some replication parameter or something in the replica " +"set has changed." +msgstr "" +"Здесь вызов ``box.cfg{}`` происходит не впервые, а повторно, поскольку " +"изменились некоторые параметры репликации или что-то в наборе реплик." + +msgid "" +"Try to connect to all nodes from ``box.cfg.replication``, or to the number " +"of nodes required by :ref:`replication_connect_quorum `, within the time period specified in " +":ref:`replication_connect_timeout `." +msgstr "" +"Попытка установить соединение со всеми узлами из ``box.cfg.replication`` или" +" с количеством узлов, указанным в параметре :ref:`replication_connect_quorum" +" ` в течение периода времени, " +"указанного в :ref:`replication_connect_timeout `." + +msgid "" +"Try to sync with the connected nodes, within the time period specified in " +":ref:`replication_sync_timeout `." +msgstr "" +"Попытка синхронизации со всеми подключенными узлами в течение периода " +"времени, указанного в :ref:`replication_sync_timeout `." + +msgid "" +"If earlier steps fail, change status to 'orphan'. (Attempts to sync will " +"continue in the background and when/if they succeed then 'orphan' status " +"will end.)" +msgstr "" +"Если предыдущие шаги не выполнены, статус изменяется на 'orphan' " +"(одиночный). (Попытки синхронизации будут продолжаться в фоновом режиме, и " +"когда/если они будут успешны, статус 'orphan' отключится.)" + +msgid "" +"If earlier steps succeed, set status to 'running' (master) or 'follow' " +"(replica)." +msgstr "" +"Если предыдущие шаги выполнены, статус изменяется на 'running' (мастер) или " +"'follow' (реплика)." + +msgid "**Situation 4: rebootstrap**" +msgstr "**Ситуация 4: повторная настройка**" + +msgid "" +"Here ``box.cfg{}`` is not being called. The replica connected successfully " +"at some point in the past, and is now ready for an update from the master. " +"But the master cannot provide an update. This can happen by accident, or " +"more likely can happen because the replica is slow (its :ref:`lag " +"` is large), and the WAL (.xlog) files" +" containing the updates have been deleted. This is not crippling. The " +"replica can discard what it received earlier, and then ask for the master's " +"latest snapshot (.snap) file contents. Since it is effectively going through" +" the bootstrap process a second time, this is called \"rebootstrapping\". " +"However, there has to be one difference from an ordinary bootstrap -- the " +"replica's :ref:`replica id ` will remain the same. " +"If it changed, then the master would think that the replica is a new " +"addition to the cluster, and would maintain a record of an instance ID of a " +"replica that has ceased to exist. Rebootstrapping was introduced in " +"Tarantool version 1.10.2 and is completely automatic." +msgstr "" +"Здесь не происходит вызов ``box.cfg{}``. В определенный момент в прошлом " +"реплика успешно установила соединение и в настоящий момент ожидает " +"обновления от мастера. Однако мастер не может передать обновления, что может" +" произойти случайно, или же если реплика работает слишком медленно (большое " +"значение :ref:`lag `), а WAL-файлы " +"(.xlog) с обновлениями были удалены. Такая ситуация не является критической " +"-- реплика может сбросить ранее полученные данные, а затем запросить " +"содержание последнего файла снимка (.snap) мастера. Поскольку фактически в " +"таком случае повторно проводится процесс настройки, это называется " +"\"повторная настройка\". Тем не менее, есть отличие от обычной настройки -- " +":ref:`идентификатор реплики ` останется прежним. " +"Если он изменится, то мастер посчитает, что в кластер добавляется новая " +"реплика, и сохранит идентификатор экземпляра реплики, которой уже не " +"существует. Полностью автоматизированный процесс повторной настройки " +"появился в версии Tarantool 1.10.2." diff --git a/locale/ru/LC_MESSAGES/dev_guide/internals/replication/replication_internals.po b/locale/ru/LC_MESSAGES/dev_guide/internals/replication/replication_internals.po new file mode 100644 index 0000000000..58e8b25ebe --- /dev/null +++ b/locale/ru/LC_MESSAGES/dev_guide/internals/replication/replication_internals.po @@ -0,0 +1,224 @@ + +msgid "Server startup with replication" +msgstr "Запуск сервера с репликацией" + +msgid "" +"In addition to the recovery process described in the section :ref:`Recovery " +"process `, the server must take additional steps" +" and precautions if :ref:`replication ` is enabled." +msgstr "" +"Помимо процесса восстановления, описанного в разделе :ref:`Процесс " +"восстановления `, сервер должен предпринять " +"дополнительные шаги и меры предосторожности, если включена :ref:`репликация " +"`." + +msgid "" +"Once again the startup procedure is initiated by the ``box.cfg{}`` request. " +"One of the ``box.cfg`` parameters may be :ref:`replication ` which specifies replication source(-s). We will refer to this " +"replica, which is starting up due to ``box.cfg``, as the \"local\" replica " +"to distinguish it from the other replicas in a replica set, which we will " +"refer to as \"distant\" replicas." +msgstr "" +"И снова процедура запуска начинается с запроса ``box.cfg{}``. Одним из " +"параметров запроса ``box.cfg`` может быть :ref:`replication " +"`, в котором указываются источники репликации. " +"Реплику, которая запускается сейчас с помощью ``box.cfg``, мы будем называть" +" локальной, чтобы отличать ее от других реплик в наборе реплик, которые мы " +"будем называть удаленными." + +msgid "" +"*If there is no snapshot .snap file and the* ``replication`` *parameter is " +"empty and* ``cfg.read_only=false``: |br| then the local replica assumes it " +"is an unreplicated \"standalone\" instance, or is the first replica of a new" +" replica set. It will generate new UUIDs for itself and for the replica set." +" The replica UUID is stored in the ``_cluster`` space; the replica set UUID " +"is stored in the ``_schema`` space. Since a snapshot contains all the data " +"in all the spaces, that means the local replica's snapshot will contain the " +"replica UUID and the replica set UUID. Therefore, when the local replica " +"restarts on later occasions, it will be able to recover these UUIDs when it " +"reads the .snap file." +msgstr "" +"*Если нет файла снимка .snap и не указано значение параметра* " +"``replication`` *и* ``cfg.read_only=false``: |br| то локальная реплика " +"предполагает, что является нереплицируемым обособленным экземпляром или же " +"первой репликой в новом наборе реплик. Она сгенерирует новые UUID для себя и" +" для набора реплик. UUID реплики хранится в спейсе ``_cluster``; UUID набора" +" реплик хранится в спейсе ``_schema``. Поскольку снимок содержит все данные " +"во всех спейсах, это означает, что снимок локальной реплики будет содержать " +"UUID реплики и UUID набора реплик. Таким образом, когда локальная реплика " +"будет позднее перезапускаться, она сможет восстановить эти UUID после " +"прочтения файла снимка .snap." + +msgid "" +"*If there is no snapshot .snap file and the* ``replication`` *parameter is " +"empty and* ``cfg.read_only=true``: |br| it cannot be the first replica of a " +"new replica set because the first replica must be a master. Therefore an " +"error message will occur: ER_BOOTSTRAP_READONLY. To avoid this, change the " +"setting for this (local) instance to ``read_only = false``, or ensure that " +"another (distant) instance starts first and has the local instance's UUID in" +" its ``_cluster`` space. In the latter case, if ER_BOOTSTRAP_READONLY still " +"occurs, set the local instance's :ref:`box.replication_connect_timeout " +"` to a larger value." +msgstr "" +"*Если нет файла снимка .snap, не указано значение параметра* ``replication``" +" *и* ``cfg.read_only=true``:|br| такая реплика не может быть первой, потому " +"что первая реплика должна быть мастером. Поэтому выдастся ошибка: " +"ER_BOOTSTRAP_READONLY. Чтобы этого избежать, измените в настройке локального" +" экземпляра ``read_only`` на ``false``, или убедитесь, что удаленный " +"экземпляр запускается первым и имеет UUID локального экземпляра в спейсе " +"``_cluster``. Во втором случае, если произойдет ER_BOOTSTRAP_READONLY, " +"выставите на локальном экземпляре :ref:`box.replication_connect_timeout " +"` на большее значение." + +msgid "" +"*If there is no snapshot .snap file and the* ``replication`` *parameter is " +"not empty and the* ``_cluster`` *space contains no other replica UUIDs*: " +"|br| then the local replica assumes it is not a standalone instance, but is " +"not yet part of a replica set. It must now join the replica set. It will " +"send its replica UUID to the first distant replica which is listed in " +"``replication`` and which will act as a master. This is called the \"join " +"request\". When a distant replica receives a join request, it will send " +"back:" +msgstr "" +"*Если нет файла снимка .snap, указано значение параметра* ``replication``, " +"*а в спейсе* ``_cluster`` *отсутствуют UUID других реплик*: |br| то " +"локальная реплика предполагает, что не является обособленным экземпляром, но" +" еще не входит в набор реплик. Сейчас она должна подключиться в набор " +"реплик. Она отправит свой UUID реплики первой удаленной реплике, указанной в" +" параметре ``replication``, которая будет выступать в качестве мастера. Это " +"называется \"запрос на подключение\". Когда удаленная реплика получает " +"запрос на подключение, она отправляет в ответ:" + +msgid "the distant replica's replica set UUID," +msgstr "UUID набора реплик, в который входит удаленная реплика" + +msgid "" +"the contents of the distant replica's .snap file. |br| When the local " +"replica receives this information, it puts the replica set UUID in its " +"``_schema`` space, puts the distant replica's UUID and connection " +"information in its ``_cluster`` space, and makes a snapshot containing all " +"the data sent by the distant replica. Then, if the local replica has data in" +" its WAL .xlog files, it sends that data to the distant replica. The distant" +" replica will receive this and update its own copy of the data, and add the " +"local replica's UUID to its ``_cluster`` space." +msgstr "" +"содержимое файла снимка .snap удаленной реплики. |br| Когда локальная " +"реплика получает эту информацию, она размещает UUID набора реплики в своем " +"спейсе ``_schema``, UUID удаленной реплики и информацию о подключении в " +"своем спейсе ``_cluster``, а затем создает снимок, который содержит все " +"данные, отправленные удаленной репликой. Затем, если в WAL-файлах .xlog " +"локальной реплики содержатся данные, они отправляются на удаленную реплику. " +"Удаленная реплика получается данные и обновляет свою копию данных, а затем " +"добавляет UUID локальной реплики в свой спейс ``_cluster``." + +msgid "" +"*If there is no snapshot .snap file and the* ``replication`` *parameter is " +"not empty and the* ``_cluster`` *space contains other replica UUIDs*: |br| " +"then the local replica assumes it is not a standalone instance, and is " +"already part of a replica set. It will send its replica UUID and replica set" +" UUID to all the distant replicas which are listed in ``replication``. This " +"is called the \"on-connect handshake\". When a distant replica receives an " +"on-connect handshake: |br|" +msgstr "" +"*Если нет файла снимка .snap, указано значение параметра* ``replication``, " +"*а в спейсе* ``_cluster`` *есть UUID других реплик*: |br| то локальная " +"реплика предполагает, что не является обособленным экземпляром, и уже входит" +" в набор реплик. Она отправит свой UUID реплики и UUID набора реплик всем " +"удаленным репликам, указанным в параметре ``replication``. Это называется " +"\"подтверждение связи при подключении\". Когда удаленная реплика получает " +"подтверждение связи при подключении: |br|" + +msgid "" +"the distant replica compares its own copy of the replica set UUID to the one" +" in the on-connect handshake. If there is no match, then the handshake fails" +" and the local replica will display an error." +msgstr "" +"удаленная реплика сопоставляет свою версию UUID набора реплик с UUID, " +"переданным в ходе подтверждения связи при подключении. Если они не " +"совпадают, связь не устанавливается, и локальная реплика отобразит ошибку." + +msgid "" +"the distant replica looks for a record of the connecting instance in its " +"``_cluster`` space. If there is none, then the handshake fails. |br| " +"Otherwise the handshake is successful. The distant replica will read any new" +" information from its own .snap and .xlog files, and send the new requests " +"to the local replica." +msgstr "" +"удаленная реплика ищет запись о подключающемся экземпляре в своем спейсе " +"``_cluster``. Если такой записи нет, связь не устанавливается. |br| Если " +"есть, связь подтверждается. Удаленная реплика выполняет чтение любой новой " +"информации из своих файлов .snap и .xlog и отправляет новые запросы на " +"локальную реплику." + +msgid "" +"In the end, the local replica knows what replica set it belongs to, the " +"distant replica knows that the local replica is a member of the replica set," +" and both replicas have the same database contents." +msgstr "" +"Наконец, локальная реплика понимает, к какому набору реплик относится, " +"удаленная реплика понимает, что локальная реплика входит в набор реплик, и у" +" двух реплик одинаковое содержимое базы данных." + +msgid "" +"*If there is a snapshot file and replication source is not empty*: |br| " +"first the local replica goes through the recovery process described in the " +"previous section, using its own .snap and .xlog files. Then it sends a " +"\"subscribe\" request to all the other replicas of the replica set. The " +"subscribe request contains the server vector clock. The vector clock has a " +"collection of pairs 'server id, lsn' for every replica in the ``_cluster`` " +"system space. Each distant replica, upon receiving a subscribe request, will" +" read its .xlog files' requests and send them to the local replica if (lsn " +"of .xlog file request) is greater than (lsn of the vector clock in the " +"subscribe request). After all the other replicas of the replica set have " +"responded to the local replica's subscribe request, the replica startup is " +"complete." +msgstr "" +"*Если есть файл снимка и указан источник репликации*: |br| сначала локальная" +" реплика проходит процесс восстановления, описанный в предыдущем разделе, " +"используя свои собственные файлы .snap и .xlog. Затем она отправляет запрос " +"подписки всем репликам в наборе реплик. Запрос подписки содержит векторные " +"часы сервера. Векторные часы включают набор пар 'идентификатор сервера, LSN'" +" для каждой реплики в системном спейсе ``_cluster``. Каждая удаленная " +"реплика, получив запрос подписки, выполняет чтение запросов из файла .xlog и" +" отправляет их на локальную реплику, если LSN из запроса файла .xlog больше," +" чем LSN векторных часов из запроса подписки. После того, как все реплики из" +" набора реплик отправили ответ на запрос подписки локальной реплики, запуск " +"реплики завершен." + +msgid "" +"The following temporary limitations applied for Tarantool versions earlier " +"than 1.7.7:" +msgstr "" +"Следующие временные ограничения применимы к версиям Tarantool ниже 1.7.7:" + +msgid "" +"The URIs in the ``replication`` parameter should all be in the same order on" +" all replicas. This is not mandatory but is an aid to consistency." +msgstr "" +"URI в параметре ``replication`` должны быть указаны в одинаковом порядке на " +"всех репликах. Это необязательно, но помогает соблюдать консистентность." + +msgid "" +"The replicas of a replica set should be started up at slightly different " +"times. This is not mandatory but prevents a situation where each replica is " +"waiting for the other replica to be ready." +msgstr "" +"Реплики в наборе реплик должны запускаться не одновременно. Это " +"необязательно, но помогает избежать ситуации, когда все реплики ждут " +"готовности друг друга." + +msgid "" +"The following limitation still applies for the current Tarantool version:" +msgstr "Следующее ограничение всё еще применимо к текущей версии Tarantool:" + +msgid "" +"The maximum number of entries in the ``_cluster`` space is :ref:`32 " +"`. Tuples for out-of-date replicas are not " +"automatically re-used, so if this 32-replica limit is reached, users may " +"have to reorganize the ``_cluster`` space manually." +msgstr "" +"Максимальное количество записей в спейсе ``_cluster`` -- :ref:`32 " +"`. Кортежи для устаревших реплик не переиспользуются " +"автоматически, поэтому по достижении предела в 32 реплики, может " +"понадобиться реорганизация спейса ``_cluster`` вручную." diff --git a/locale/ru/LC_MESSAGES/dev_guide/internals/replication_internals.po b/locale/ru/LC_MESSAGES/dev_guide/internals/replication_internals.po deleted file mode 100644 index 7de109608f..0000000000 --- a/locale/ru/LC_MESSAGES/dev_guide/internals/replication_internals.po +++ /dev/null @@ -1,213 +0,0 @@ - -msgid "Server startup with replication" -msgstr "Запуск сервера с репликацией" - -msgid "" -"In addition to the recovery process described above, the server must take " -"additional steps and precautions if :ref:`replication ` is " -"enabled." -msgstr "" -"Помимо вышеописанного процесса восстановления, сервер должен предпринять " -"дополнительные меры предосторожности, если включена :ref:`репликация " -"`." - -msgid "" -"Once again the startup procedure is initiated by the ``box.cfg{}`` request. " -"One of the ``box.cfg`` parameters may be :ref:`replication ` that specifies replication source(-s). We will refer to this " -"replica, which is starting up due to ``box.cfg``, as the \"local\" replica " -"to distinguish it from the other replicas in a replica set, which we will " -"refer to as \"distant\" replicas." -msgstr "" -"И снова процедура запуска начинается с запроса ``box.cfg{}``. Одним из " -"параметров запроса ``box.cfg`` может быть :ref:`replication " -"`, в котором указываются источники репликации. " -"Реплику, которая запускается сейчас с помощью ``box.cfg``, мы будем называть" -" локальной, чтобы отличать ее от других реплик в наборе реплик, которые мы " -"будем называть удаленными." - -msgid "" -"*#1. If there is no snapshot .snap file and the 'replication' parameter is " -"empty and cfg.read_only=false*: |br| then the local replica assumes it is an" -" unreplicated \"standalone\" instance, or is the first replica of a new " -"replica set. It will generate new UUIDs for itself and for the replica set. " -"The replica UUID is stored in the ``_cluster`` space (unless the replica is " -":ref:`anonymous `); the replica set UUID " -"is stored in the ``_schema`` space. Since a snapshot contains all the data " -"in all the spaces, that means the local replica's snapshot will contain the " -"replica UUID and the replica set UUID. Therefore, when the local replica " -"restarts on later occasions, it will be able to recover these UUIDs when it " -"reads the .snap file." -msgstr "" -"*#1. Если нет файла снимка .snap, и не указано значение параметра " -"'replication', и cfg.read_only=false*: |br| Локальная реплика предполагает, " -"что она нереплицируемый обособленный экземпляр или же первая реплика в новом" -" наборе реплик. Она сгенерирует новые UUID для себя и для набора реплик. " -"UUID реплики хранится в спейсе ``_cluster`` (если только реплика не является" -" :ref:`анонимной `). UUID набора реплик " -"хранится в спейсе ``_schema``. Поскольку снимок содержит все данные во всех " -"спейсах, это означает, что снимок локальной реплики будет содержать UUID " -"реплики и UUID набора реплик. Таким образом, когда локальная реплика позднее" -" перезапустится, она сможет восстановить эти UUID после того, как прочитает " -"файл снимка .snap." - -msgid "" -"*#1a. If there is no snapshot .snap file and the 'replication' parameter is " -"empty and cfg.read_only=true*: |br| When an instance is starting with " -"``box.cfg({... read_only = true})``, it cannot be the first replica of a new" -" replica set because the first replica must be a master. Therefore an error " -"message will occur: ER_BOOTSTRAP_READONLY. To avoid this, change the setting" -" for this (local) instance to ``read_only = false``, or ensure that another " -"(distant) instance starts first and has the local instance's UUID in its " -"_cluster space. In the latter case, if ER_BOOTSTRAP_READONLY still occurs, " -"set the local instance's :ref:`box.replication_connect_timeout " -"` to a larger value." -msgstr "" -"*#1a. Если нет файла снимка .snap, не указано значение параметра " -"'replication' и cfg.read_only=true*: |br| Когда запуск экземпляра " -"осуществляется с помощью an instance ``box.cfg({... read_only = true})``, " -"такая реплика не может быть первой в наборе реплик, потому что первая " -"реплика должна быть мастером. Поэтому возникнет ошибка: " -"ER_BOOTSTRAP_READONLY. Чтобы этого избежать, измените в настройке локального" -" экземпляра ``read_only`` на ``false``, или убедитесь, что удаленный " -"экземпляр запускается первым и имеет UUID локального экземпляра в спейсе " -"_cluster. Во втором случае, если произойдет ER_BOOTSTRAP_READONLY, выставите" -" на локальном экземпляре большее значение " -":ref:`box.replication_connect_timeout `." - -msgid "" -"*#2. If there is no snapshot .snap file and the 'replication' parameter is " -"not empty and the ``_cluster`` space contains no other replica UUIDs*: |br| " -"then the local replica assumes it is not a standalone instance, but is not " -"yet part of a replica set. It must now join the replica set. It will send " -"its replica UUID to the first distant replica which is listed in " -"``replication`` and which will act as a master. This is called the \"join " -"request\". When a distant replica receives a join request, it will send " -"back:" -msgstr "" -"*#2. Если нет файла снимка .snap, указано значение параметра 'replication', " -"а в спейсе ``_cluster`` отсутствуют UUID других реплик*: |br| Локальная " -"реплика предполагает, что она не является обособленным экземпляром, но еще " -"не входит в набор реплик. Сейчас она должна подключиться в набор реплик. Она" -" отправит свой UUID реплики первой удаленной реплике из параметра " -"``replication``, которая будет выступать в качестве мастера. Это называется " -"\"запрос на подключение\". Когда удаленная реплика получает запрос на " -"подключение, она отправляет в ответ:" - -msgid "the distant replica's replica set UUID," -msgstr "UUID набора реплик, в который входит удаленная реплика" - -msgid "" -"the contents of the distant replica's .snap file. |br| When the local " -"replica receives this information, it puts the replica set UUID in its " -"``_schema`` space, puts the distant replica's UUID and connection " -"information in its ``_cluster`` space, and makes a snapshot containing all " -"the data sent by the distant replica. Then, if the local replica has data in" -" its WAL .xlog files, it sends that data to the distant replica. The distant" -" replica will receive this and update its own copy of the data, and add the " -"local replica's UUID to its ``_cluster`` space." -msgstr "" -"содержимое файла снимка .snap удаленной реплики. |br| Когда локальная " -"реплика получает эту информацию, она размещает UUID набора реплики в своем " -"спейсе ``_schema``, UUID удаленной реплики и информацию о подключении в " -"своем спейсе ``_cluster``, а затем создает снимок, который содержит все " -"данные, отправленные удаленной репликой. Затем, если в WAL-файлах .xlog " -"локальной реплики содержатся данные, они отправляются на удаленную реплику. " -"Удаленная реплика получается данные и обновляет свою копию данных, а затем " -"добавляет UUID локальной реплики в свой спейс ``_cluster``." - -msgid "" -"*#3. If there is no snapshot .snap file and the 'replication' parameter is " -"not empty and the ``_cluster`` space contains other replica UUIDs*: |br| " -"then the local replica assumes it is not a standalone instance, and is " -"already part of a replica set. It will send its replica UUID and replica set" -" UUID to all the distant replicas which are listed in ``replication``. This " -"is called the \"on-connect handshake\". When a distant replica receives an " -"on-connect handshake: |br|" -msgstr "" -"*#3. Если нет файла снимка .snap, указано значение параметра 'replication', " -"а в спейсе ``_cluster`` есть UUID других реплик*: |br| Локальная реплика " -"предполагает, что она не обособленный экземпляр, а уже входит в набор " -"реплик. Она отправит свой UUID реплики и UUID набора реплик всем удаленным " -"репликам из параметра ``replication``. Это называется \"подтверждение связи " -"при подключении\". Когда удаленная реплика получает подтверждение связи при " -"подключении: |br|" - -msgid "" -"the distant replica compares its own copy of the replica set UUID to the one" -" in the on-connect handshake. If there is no match, then the handshake fails" -" and the local replica will display an error." -msgstr "" -"удаленная реплика сопоставляет свою версию UUID набора реплик с UUID, " -"переданным в ходе подтверждения связи при подключении. Если они не " -"совпадают, связь не устанавливается, и локальная реплика отобразит ошибку." - -msgid "" -"the distant replica looks for a record of the connecting instance in its " -"``_cluster`` space. If there is none, then the handshake fails. |br| " -"Otherwise the handshake is successful. The distant replica will read any new" -" information from its own .snap and .xlog files, and send the new requests " -"to the local replica." -msgstr "" -"удаленная реплика ищет запись о подключающемся экземпляре в своем спейсе " -"``_cluster``. Если такой записи нет, связь не устанавливается. |br| Если " -"есть, связь подтверждается. Удаленная реплика выполняет чтение любой новой " -"информации из своих файлов .snap и .xlog и отправляет новые запросы на " -"локальную реплику." - -msgid "" -"In the end ... the local replica knows what replica set it belongs to, the " -"distant replica knows that the local replica is a member of the replica set," -" and both replicas have the same database contents." -msgstr "" -"В итоге: локальная реплика понимает, к какому набору реплик относится; " -"удаленная реплика понимает, что локальная реплика входит в набор реплик; у " -"двух реплик одинаковое содержимое базы данных." - -msgid "" -"*#4. If there is a snapshot file and replication source is not empty*: |br| " -"first the local replica goes through the recovery process described in the " -"previous section, using its own .snap and .xlog files. Then it sends a " -"\"subscribe\" request to all the other replicas of the replica set. The " -"subscribe request contains the server vector clock. The vector clock has a " -"collection of pairs 'server id, lsn' for every replica in the ``_cluster`` " -"system space. Each distant replica, upon receiving a subscribe request, will" -" read its .xlog files' requests and send them to the local replica if (lsn " -"of .xlog file request) is greater than (lsn of the vector clock in the " -"subscribe request). After all the other replicas of the replica set have " -"responded to the local replica's subscribe request, the replica startup is " -"complete." -msgstr "" -"*#4. Если есть файл снимка и указан источник репликации*: |br| Сначала " -"локальная реплика проходит процесс восстановления, описанный в предыдущем " -"разделе, используя свои собственные файлы .snap и .xlog. Затем она " -"отправляет запрос подписки всем репликам в наборе реплик. Запрос подписки " -"содержит векторные часы сервера. Векторные часы включают набор пар " -"'идентификатор сервера, LSN' для каждой реплики в системном спейсе " -"``_cluster``. Каждая удаленная реплика, получив запрос подписки, выполняет " -"чтение запросов из файла .xlog и отправляет их на локальную реплику, если " -"LSN из запроса файла .xlog больше, чем LSN векторных часов из запроса " -"подписки. После того, как все реплики из набора реплик отправили ответ на " -"запрос подписки локальной реплики, запуск реплики завершен." - -msgid "The following temporary limitations apply for versions 1.7 and 2.1:" -msgstr "Следующие временные ограничения применимы к версиям 1.7 and 2.1:" - -msgid "" -"The URIs in the ``replication`` parameter should all be in the same order on" -" all replicas. This is not mandatory but is an aid to consistency." -msgstr "" -"URI в параметре ``replication`` должны быть указаны в одинаковом порядке на " -"всех репликах. Это необязательно, но помогает соблюдать консистентность." - -msgid "" -"The maximum number of entries in the ``_cluster`` space is 32. Tuples for " -"out-of-date replicas are not automatically re-used, so if this 32-replica " -"limit is reached, users may have to reorganize the ``_cluster`` space " -"manually." -msgstr "" -"Максимальное количество записей в спейсе ``_cluster`` — 32. Кортежи для " -"устаревших реплик не переиспользуются автоматически, поэтому по достижении " -"предела в 32 реплики может понадобиться реорганизация спейса ``_cluster`` " -"вручную." diff --git a/locale/ru/LC_MESSAGES/getting_started/change_schema_dynamically.po b/locale/ru/LC_MESSAGES/getting_started/change_schema_dynamically.po index 2142d7145e..7bb9e11e4c 100644 --- a/locale/ru/LC_MESSAGES/getting_started/change_schema_dynamically.po +++ b/locale/ru/LC_MESSAGES/getting_started/change_schema_dynamically.po @@ -23,7 +23,7 @@ msgid "" "The easiest way to change it is to delete the database snapshots and create " "a schema from scratch. Of course, this is only acceptable during application" " development and debugging. For production scenarios, read the section on " -":ref:`migrations`." +":ref:`migrations `." msgstr "" "Самый простой способ изменить ее — это удалить снимки базы данных и создать " "схему с нуля. Разумеется, это приемлемо только на время разработки и отладки" @@ -58,7 +58,7 @@ msgstr "" msgid "" "To understand how the Tarantool data schema works, read the :ref:`Data " -"model` section." +"model ` section." msgstr "" "Чтобы понять, как устроена схема данных в Tarantool, читайте раздел " -":ref:`Модель данных`." +":ref:`Модель данных `." diff --git a/locale/ru/LC_MESSAGES/getting_started/connecting_to_cluster.po b/locale/ru/LC_MESSAGES/getting_started/connecting_to_cluster.po index 9a35cba472..7c92d156a6 100644 --- a/locale/ru/LC_MESSAGES/getting_started/connecting_to_cluster.po +++ b/locale/ru/LC_MESSAGES/getting_started/connecting_to_cluster.po @@ -125,8 +125,8 @@ msgstr ":ref:`для Go `" msgid ":ref:`for PHP `" msgstr ":ref:`для PHP `" -msgid ":doc:`for C++ `" -msgstr ":doc:`для C++ `" +msgid ":doc:`for C++ `" +msgstr ":doc:`для C++ `" msgid "" "For connectors to other languages, check the README for the connector of " diff --git a/locale/ru/LC_MESSAGES/getting_started/writing_cluster_code.po b/locale/ru/LC_MESSAGES/getting_started/writing_cluster_code.po index 30703cc72c..b05a413ab6 100644 --- a/locale/ru/LC_MESSAGES/getting_started/writing_cluster_code.po +++ b/locale/ru/LC_MESSAGES/getting_started/writing_cluster_code.po @@ -20,10 +20,10 @@ msgstr "" msgid "" "However, in Tarantool, you can implement absolutely any business logic on " "top of a cluster. This :doc:`Cartridge getting started section " -"` covers the cluster roles " +"` covers the cluster roles " "mechanism and writing a cluster application from scratch." msgstr "" "Однако в Tarantool можно реализовывать совершенно любую бизнес-логику поверх" " кластера. В разделе :doc:`Создаем свое первое приложение на Tarantool " -"Cartridge ` мы узнаем о " +"Cartridge ` мы узнаем о " "механизме кластерных ролей и напишем кластерное приложение с нуля." diff --git a/locale/ru/LC_MESSAGES/book/app_server/cookbook.po b/locale/ru/LC_MESSAGES/how-to/app/cookbook.po similarity index 99% rename from locale/ru/LC_MESSAGES/book/app_server/cookbook.po rename to locale/ru/LC_MESSAGES/how-to/app/cookbook.po index ea1fc92135..be7dcb3940 100644 --- a/locale/ru/LC_MESSAGES/book/app_server/cookbook.po +++ b/locale/ru/LC_MESSAGES/how-to/app/cookbook.po @@ -1,6 +1,6 @@ -msgid "Cookbook recipes" -msgstr "Примеры и рекомендации по разработке" +msgid "Lua cookbook recipes" +msgstr "Примеры и рекомендации по разработке на Lua" msgid "" "Here are contributions of Lua programs for some frequent or tricky " diff --git a/locale/ru/LC_MESSAGES/book/app_server/creating_app.po b/locale/ru/LC_MESSAGES/how-to/app/creating_app.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/app_server/creating_app.po rename to locale/ru/LC_MESSAGES/how-to/app/creating_app.po diff --git a/locale/ru/LC_MESSAGES/book/app_server/using_ide.po b/locale/ru/LC_MESSAGES/how-to/app/using_ide.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/app_server/using_ide.po rename to locale/ru/LC_MESSAGES/how-to/app/using_ide.po diff --git a/locale/ru/LC_MESSAGES/how-to/crud.po b/locale/ru/LC_MESSAGES/how-to/db/crud.po similarity index 100% rename from locale/ru/LC_MESSAGES/how-to/crud.po rename to locale/ru/LC_MESSAGES/how-to/db/crud.po diff --git a/locale/ru/LC_MESSAGES/how-to/db/indexes.po b/locale/ru/LC_MESSAGES/how-to/db/indexes.po new file mode 100644 index 0000000000..08f29cbe16 --- /dev/null +++ b/locale/ru/LC_MESSAGES/how-to/db/indexes.po @@ -0,0 +1,456 @@ + +msgid "Indexes" +msgstr "Индексы" + +msgid "" +"An **index** is a special data structure that stores a group of key values " +"and pointers. It is used for efficient manipulations with data." +msgstr "" +"**Индекс** — это специальная структура данных, которая хранит группу " +"ключевых значений и указателей. Индекс используется для эффективного " +"управления данными." + +msgid "" +"As with spaces, you should specify the index **name**, and let Tarantool " +"come up with a unique **numeric identifier** (\"index id\")." +msgstr "" +"Как и для спейсов, индексам следует указать **имена**, а Tarantool определит" +" уникальный **числовой идентификатор** (\"ID индекса\")." + +msgid "" +"An index may be **multi-part**, that is, you can declare that an index key " +"value is composed of two or more fields in the tuple, in any order. For " +"example, for an ordinary TREE index, the maximum number of parts is 255." +msgstr "" +"Индекс может быть **составным** (multi-part), то есть можно объявить, что " +"ключ индекса состоит из двух или более полей в кортеже в любом порядке. " +"Например, для обычного TREE-индекса максимальное количество частей равно " +"255." + +msgid "" +"An index may be **unique**, that is, you can declare that it would be " +"illegal to have the same key value twice." +msgstr "" +"Индекс может быть **уникальным**, то есть можно объявить, что недопустимо " +"дважды задавать одно значение ключа." + +msgid "" +"The first index defined on a space is called the **primary key index**, and " +"it must be unique. All other indexes are called **secondary indexes**, and " +"they may be non-unique." +msgstr "" +"Первый индекс, определенный для спейса, называется **первичный индекс** " +"(primary key). Он должен быть уникальным. Все остальные индексы называются " +"**вторичными индексами** (secondary), они могут строиться по неуникальным " +"значениям." + +msgid "" +"Indexes have certain limitations. See details on page :doc:`Limitations " +"`." +msgstr "" +"На индексы распространяются определенные ограничения. Более подробную " +"информацию см. на странице :doc:`Ограничения `." + +msgid "Creating an index" +msgstr "Создание индекса" + +msgid "" +"It is mandatory to create an index for a space before trying to insert " +"tuples into the space, or select tuples from the space." +msgstr "" +"Перед тем, как вставлять кортежи в спейс или выбирать из него кортежи, нужно" +" обязательно создать индекс для этого спейса." + +msgid "" +"The simple :doc:`index-creation " +"` operation is:" +msgstr "" +"Простая операция по :doc:`созданию индекса " +"` выглядит следующим " +"образом:" + +msgid "" +":extsamp:`box.space.{**{space-name}**}:create_index('{*{index-name}*}')`" +msgstr "" +":extsamp:`box.space.{**{space-name}**}:create_index('{*{index-name}*}')`" + +msgid "" +"This creates a unique :ref:`TREE ` index on the first field of" +" all tuples (often called \"Field#1\"), which is assumed to be numeric." +msgstr "" +"При этом создается уникальный :ref:`TREE-индекс ` по первому " +"полю всех кортежей (обычно его называют \"Field#1\"). Предполагается, что " +"индексируемое поле является числовым." + +msgid "" +"A recommended design pattern for a data model is to base primary keys on the" +" first fields of a tuple. This speeds up tuple comparison due to the " +"specifics of data storage and the way comparisons are arranged in Tarantool." +msgstr "" +"Рекомендуется проектировать модель данных так, чтобы первичные ключи были " +"первыми полями в кортеже. Это позволяет быстрее сравнивать кортежи, учитывая" +" специфику хранения данных и способ организации сравнений в Tarantool." + +msgid "" +"The simple :doc:`SELECT ` request" +" is:" +msgstr "" +"Вот простой запрос :doc:`SELECT " +"`:" + +msgid ":extsamp:`box.space.{**{space-name}**}:select({*{value}*})`" +msgstr ":extsamp:`box.space.{**{space-name}**}:select({*{value}*})`" + +msgid "" +"This looks for a single tuple via the first index. Since the first index is " +"always unique, the maximum number of returned tuples will be 1. You can call" +" ``select()`` without arguments, and it will return all tuples. Be careful! " +"Using ``select()`` for huge spaces hangs your instance." +msgstr "" +"Такой запрос ищет отдельный кортеж, используя первичный индекс. Поскольку " +"первичный индекс всегда уникален, то данный запрос вернет не более одного " +"кортежа. Можно также вызвать ``select()`` без аргументов, чтобы вернуть все " +"кортежи. Осторожно! Если вызвать ``select()`` без аргументов в огромном " +"спейсе, ваш экземпляр зависнет." + +msgid "" +"An index definition may also include identifiers of tuple fields and their " +"expected **types**. See allowed indexed field types in section :ref:`Details" +" about indexed field types `:" +msgstr "" +"Определение индекса может также содержать идентификаторы полей кортежа и их " +"предполагаемые **типы**. См. допустимые типы полей в разделе :ref:`Описание " +"типов индексируемых полей `:" + +msgid "" +":extsamp:`box.space.{**{space-name}**}:create_index({**{index-name}**}, " +"{type = 'tree', parts = {{field = 1, type = 'unsigned'}}}`" +msgstr "" +":extsamp:`box.space.{**{space-name}**}:create_index({**{index-name}**}, " +"{type = 'tree', parts = {{field = 1, type = 'unsigned'}}}`" + +msgid "" +"Space definitions and index definitions are stored permanently in " +"Tarantool's system spaces :ref:`_space ` and :ref:`_index " +"`." +msgstr "" +"Определения спейса и определения индексов хранятся в системных спейсах " +"Tarantool :ref:`_space ` и :ref:`_index ` " +"соответственно." + +msgid "Tip" +msgstr "Примечание" + +msgid "" +"See full information about creating indexes, such as how to create a " +"multikey index, an index using the ``path`` option, or how to create a " +"functional index in our reference for " +":doc:`/reference/reference_lua/box_space/create_index`." +msgstr "" +"Полную информацию о создании индексов, например о создании индексов по " +"массиву (multikey), индексов с использованием пути ``path`` или " +"функциональных индексов см. в справочнике " +":doc:`/reference/reference_lua/box_space/create_index`." + +msgid "Index operations" +msgstr "Операции с индексами" + +msgid "" +"Index operations are automatic: if a data manipulation request changes a " +"tuple, then it also changes the index keys defined for the tuple." +msgstr "" +"Операции с индексами производятся автоматически. Если запрос на изменение " +"данных меняет данные в кортеже, то изменятся и ключи индекса для данного " +"кортежа." + +msgid "" +"Let's create a sample space named ``tester`` and " +"put it in a variable ``my_space``:" +msgstr "" +"Для примера создадим спейс с именем ``tester`` и поместим его в переменную " +"``my_space``:" + +msgid "tarantool> my_space = box.schema.space.create('tester')" +msgstr "tarantool> my_space = box.schema.space.create('tester')" + +msgid "Format the created space by specifying field names and types:" +msgstr "Отформатируем созданный спейс, указав имена и типы полей:" + +msgid "" +"tarantool> my_space:format({\n" +" > {name = 'id', type = 'unsigned'},\n" +" > {name = 'band_name', type = 'string'},\n" +" > {name = 'year', type = 'unsigned'},\n" +" > {name = 'rate', type = 'unsigned', is_nullable = true}})" +msgstr "" +"tarantool> my_space:format({\n" +" > {name = 'id', type = 'unsigned'},\n" +" > {name = 'band_name', type = 'string'},\n" +" > {name = 'year', type = 'unsigned'},\n" +" > {name = 'rate', type = 'unsigned', is_nullable = true}})" + +msgid "Create the **primary** index (named ``primary``):" +msgstr "Создадим **первичный** индекс с именем ``primary``:" + +msgid "" +"tarantool> my_space:create_index('primary', {\n" +" > type = 'tree',\n" +" > parts = {'id'}\n" +" > })" +msgstr "" +"tarantool> my_space:create_index('primary', {\n" +" > type = 'tree',\n" +" > parts = {'id'}\n" +" > })" + +msgid "This is a primary index based on the ``id`` field of each tuple." +msgstr "Это первичный индекс по полю ``id`` в каждом кортеже." + +msgid "Insert some :ref:`tuples ` into the space:" +msgstr "Вставим несколько :ref:`кортежей ` в спейс:" + +msgid "" +"tarantool> my_space:insert{1, 'Roxette', 1986, 1}\n" +"tarantool> my_space:insert{2, 'Scorpions', 2015, 4}\n" +"tarantool> my_space:insert{3, 'Ace of Base', 1993}\n" +"tarantool> my_space:insert{4, 'Roxette', 2016, 3}" +msgstr "" +"tarantool> my_space:insert{1, 'Roxette', 1986, 1}\n" +"tarantool> my_space:insert{2, 'Scorpions', 2015, 4}\n" +"tarantool> my_space:insert{3, 'Ace of Base', 1993}\n" +"tarantool> my_space:insert{4, 'Roxette', 2016, 3}" + +msgid "Create a **secondary index**:" +msgstr "Создадим **вторичный индекс**:" + +msgid "" +"tarantool> box.space.tester:create_index('secondary', {parts = {{field=3, type='unsigned'}}})\n" +"---\n" +"- unique: true\n" +" parts:\n" +" - type: unsigned\n" +" is_nullable: false\n" +" fieldno: 3\n" +" id: 2\n" +" space_id: 512\n" +" type: TREE\n" +" name: secondary\n" +"..." +msgstr "" +"tarantool> box.space.tester:create_index('secondary', {parts = {{field=3, type='unsigned'}}})\n" +"---\n" +"- unique: true\n" +" parts:\n" +" - type: unsigned\n" +" is_nullable: false\n" +" fieldno: 3\n" +" id: 2\n" +" space_id: 512\n" +" type: TREE\n" +" name: secondary\n" +"..." + +msgid "Create a **multi-part index** with three parts:" +msgstr "Создадим **составной индекс** (multi-part) из трех частей:" + +msgid "" +"tarantool> box.space.tester:create_index('thrine', {parts = {\n" +" > {field = 2, type = 'string'},\n" +" > {field = 3, type = 'unsigned'},\n" +" > {field = 4, type = 'unsigned'}\n" +" > }})\n" +"---\n" +"- unique: true\n" +" parts:\n" +" - type: string\n" +" is_nullable: false\n" +" fieldno: 2\n" +" - type: unsigned\n" +" is_nullable: false\n" +" fieldno: 3\n" +" - type: unsigned\n" +" is_nullable: true\n" +" fieldno: 4\n" +" id: 6\n" +" space_id: 513\n" +" type: TREE\n" +" name: thrine\n" +"..." +msgstr "" +"tarantool> box.space.tester:create_index('thrine', {parts = {\n" +" > {field = 2, type = 'string'},\n" +" > {field = 3, type = 'unsigned'},\n" +" > {field = 4, type = 'unsigned'}\n" +" > }})\n" +"---\n" +"- unique: true\n" +" parts:\n" +" - type: string\n" +" is_nullable: false\n" +" fieldno: 2\n" +" - type: unsigned\n" +" is_nullable: false\n" +" fieldno: 3\n" +" - type: unsigned\n" +" is_nullable: true\n" +" fieldno: 4\n" +" id: 6\n" +" space_id: 513\n" +" type: TREE\n" +" name: thrine\n" +"..." + +msgid "**There are the following SELECT variations:**" +msgstr "**Можно использовать такие варианты SELECT:**" + +msgid "The search can use **comparisons** other than equality:" +msgstr "" +"Помимо условия равенства, при поиске могут использоваться и другие **условия" +" сравнения**:" + +msgid "" +"tarantool> box.space.tester:select(1, {iterator = 'GT'})\n" +"---\n" +"- - [2, 'Scorpions', 2015, 4]\n" +" - [3, 'Ace of Base', 1993]\n" +" - [4, 'Roxette', 2016, 3]\n" +"..." +msgstr "" +"tarantool> box.space.tester:select(1, {iterator = 'GT'})\n" +"---\n" +"- - [2, 'Scorpions', 2015, 4]\n" +" - [3, 'Ace of Base', 1993]\n" +" - [4, 'Roxette', 2016, 3]\n" +"..." + +msgid "The :ref:`comparison operators ` are:" +msgstr "Есть такие :ref:`операторы сравнения `:" + +msgid "``LT`` for \"less than\"" +msgstr "``LT`` — \"меньше\"" + +msgid "``LE`` for \"less than or equal\"" +msgstr "``LE`` — \"меньше или равно\"" + +msgid "``GT`` for \"greater\"" +msgstr "``GT`` — \"больше\"" + +msgid "``GE`` for \"greater than or equal\" ." +msgstr "``GE`` — \"больше или равно\"" + +msgid "``EQ`` for \"equal\"," +msgstr "``EQ`` — \"равно\"," + +msgid "``REQ`` for \"reversed equal\"" +msgstr "``REQ`` — \"равно, результаты отсортированы в порядке убывания по ключу\"" + +msgid "" +"Value comparisons make sense if and only if the index type is TREE. The " +"iterator types for other types of indexes are slightly different and work " +"differently. See details in section :ref:`Iterator types `." +msgstr "" +"Только для TREE-индексов есть смысл в сравнении значений. Итераторы для " +"других типов индексов немного отличаются и работают по-другому. Более " +"подробную информацию см. в разделе :ref:`Типы итераторов `." + +msgid "" +"Note that we don't use the name of the index, which means we use primary " +"index here." +msgstr "" +"Обратите внимание, что мы не используем имя индекса — значит, здесь мы " +"используем первичный индекс." + +msgid "" +"This type of search may return more than one tuple. The tuples will be " +"sorted in descending order by key if the comparison operator is LT or LE or " +"REQ. Otherwise they will be sorted in ascending order." +msgstr "" +"Этот вариант поиска может вернуть более одного кортежа. Если используется " +"оператор сравнения LT, LE или REQ, то кортежи будут отсортированы по ключу в" +" порядке убывания. Во всех остальных случаях — в порядке возрастания." + +msgid "The search can use a **secondary index**." +msgstr "Для поиска можно использовать **вторичный индекс**." + +msgid "" +"For a primary-key search, it is optional to specify an index name as was " +"demonstrated above. For a secondary-key search, it is mandatory." +msgstr "" +"При поиске по первичному ключу имя индекса можно не указывать, как показано " +"выше. При поиске же по вторичному ключу имя индекса нужно указать " +"обязательно." + +msgid "" +"tarantool> box.space.tester.index.secondary:select({1993})\n" +"---\n" +"- - [3, 'Ace of Base', 1993]\n" +"..." +msgstr "" +"tarantool> box.space.tester.index.secondary:select({1993})\n" +"---\n" +"- - [3, 'Ace of Base', 1993]\n" +"..." + +msgid "" +"**Partial key search:** The search may be for some key parts starting with " +"the prefix of the key. Note that partial key searches are available only in " +"TREE indexes." +msgstr "" +"**Поиск по частям ключа:** Можно производить поиск по частям ключа, начиная " +"с префикса ключа. Обратите внимание, что поиск по части ключа доступен " +"только в TREE-индексах." + +msgid "" +"tarantool> box.space.tester.index.thrine:select({'Scorpions', 2015})\n" +"---\n" +"- - [2, 'Scorpions', 2015, 4]\n" +"..." +msgstr "" +"tarantool> box.space.tester.index.thrine:select({'Scorpions', 2015})\n" +"---\n" +"- - [2, 'Scorpions', 2015, 4]\n" +"..." + +msgid "The search can be for all fields, using a table as the value:" +msgstr "Поиск можно производить по всем полям через запись в виде таблицы:" + +msgid "" +"tarantool> box.space.tester.index.thrine:select({'Roxette', 2016, 3})\n" +"---\n" +"- - [4, 'Roxette', 2016, 3]\n" +"..." +msgstr "" +"tarantool> box.space.tester.index.thrine:select({'Roxette', 2016, 3})\n" +"---\n" +"- - [4, 'Roxette', 2016, 3]\n" +"..." + +msgid "or the search can be for one field, using a table or a scalar:" +msgstr "" +"либо же по одному полю, в этом случае используется таблица или скалярное " +"значение:" + +msgid "" +"tarantool> box.space.tester.index.thrine:select({'Roxette'})\n" +"---\n" +"- - [1, 'Roxette', 1986, 5]\n" +" - [4, 'Roxette', 2016, 3]\n" +"..." +msgstr "" +"tarantool> box.space.tester.index.thrine:select({'Roxette'})\n" +"---\n" +"- - [1, 'Roxette', 1986, 5]\n" +" - [4, 'Roxette', 2016, 3]\n" +"..." + +msgid "" +"You can also add, drop, or alter the definitions at runtime, with some " +"restrictions. Read more about index operations in reference for " +":doc:`box.index submodule `." +msgstr "" +"С некоторыми ограничениями можно добавлять, удалять или изменять определения" +" во время исполнения кода. Более подробную информацию об операциях с " +"индексами см. в справочнике по :doc:`вложенному модулю box.index " +"`." diff --git a/locale/ru/LC_MESSAGES/how-to/other/sequences.po b/locale/ru/LC_MESSAGES/how-to/other/sequences.po new file mode 100644 index 0000000000..01956e4568 --- /dev/null +++ b/locale/ru/LC_MESSAGES/how-to/other/sequences.po @@ -0,0 +1,280 @@ +msgid "Sequences" +msgstr "Последовательности" + +msgid "A **sequence** is a generator of ordered integer values." +msgstr "" +"**Последовательность** -- это генератор упорядоченных значений целых чисел." + +msgid "" +"As with spaces and indexes, you should specify the sequence **name** and let" +" Tarantool generate a unique numeric identifier (sequence ID)." +msgstr "" +"Как и для спейсов и индексов, для последовательности вы должны указать " +"**имя**, а Tarantool создаст уникальный для неё числовой идентификатор (\"ID" +" последовательности)." + +msgid "" +"As well, you can specify several options when creating a new sequence. The " +"options determine what value will be generated whenever the sequence is " +"used." +msgstr "" +"Кроме того, можно указать несколько параметров при создании новой " +"последовательности. Параметры определяют, какое значение будет " +"генерироваться при использовании последовательности." + +msgid "Options for box.schema.sequence.create()" +msgstr "Параметры для box.schema.sequence.create()" + +msgid "Option name" +msgstr "Имя параметра" + +msgid "Type and meaning" +msgstr "Тип и значение" + +msgid "Default" +msgstr "Значение по умолчанию" + +msgid "Examples" +msgstr "Примеры" + +msgid "**start**" +msgstr "**start**" + +msgid "Integer. The value to generate the first time a sequence is used" +msgstr "" +"Integer. Значение генерируется, когда последовательность используется " +"впервые" + +msgid "1" +msgstr "1" + +msgid "start=0" +msgstr "start=0" + +msgid "**min**" +msgstr "**min**" + +msgid "Integer. Values smaller than this cannot be generated" +msgstr "Integer. Значения, ниже указанного, генерироваться не могут" + +msgid "min=-1000" +msgstr "min=-1000" + +msgid "**max**" +msgstr "**max**" + +msgid "Integer. Values larger than this cannot be generated" +msgstr "Integer. Значения, выше указанного, генерироваться не могут" + +msgid "9223372036854775807" +msgstr "9223372036854775807" + +msgid "max=0" +msgstr "max=0" + +msgid "**cycle**" +msgstr "**cycle**" + +msgid "Boolean. Whether to start again when values cannot be generated" +msgstr "" +"Логическое значение. Если значения не могут быть сгенерированы, начинать ли " +"заново" + +msgid "false" +msgstr "false" + +msgid "cycle=true" +msgstr "cycle=true" + +msgid "**cache**" +msgstr "**cache**" + +msgid "Integer. The number of values to store in a cache" +msgstr "Integer. Количество значений, которые будут храниться в кэше" + +msgid "0" +msgstr "0" + +msgid "cache=0" +msgstr "cache=0" + +msgid "**step**" +msgstr "**step**" + +msgid "" +"Integer. What to add to the previous generated value, when generating a new " +"value" +msgstr "" +"Integer. Что добавить к предыдущему сгенерированному значению, когда " +"генерируется новое значение" + +msgid "step=-1" +msgstr "step=-1" + +msgid "**if_not_exists**" +msgstr "**if_not_exists** (если отсутствует)" + +msgid "" +"Boolean. If this is true and a sequence with this name exists already, " +"ignore other options and use the existing values" +msgstr "" +"Логическое значение. Если выставлено в true (истина) и существует " +"последовательность с таким именем, то игнорировать другие опции и " +"использовать текущие значения" + +msgid "if_not_exists=true" +msgstr "if_not_exists=true" + +msgid "" +"Once a sequence exists, it can be altered, dropped, reset, forced to " +"generate the next value, or associated with an index." +msgstr "" +"Существующую последовательность можно изменять, удалять, сбрасывать, " +"заставить сгенерировать новое значение или ассоциировать с индексом." + +msgid "" +"Associating a sequence with an index" +msgstr "" +"Привязка последовательности к индексу" + +msgid "For an initial example, we generate a sequence named 'S'." +msgstr "" +"Для первоначального примера сгенерируем последовательность под названием " +"'S'." + +msgid "" +"tarantool> box.schema.sequence.create('S',{min=5, start=5})\n" +"---\n" +"- step: 1\n" +" id: 5\n" +" min: 5\n" +" cache: 0\n" +" uid: 1\n" +" max: 9223372036854775807\n" +" cycle: false\n" +" name: S\n" +" start: 5\n" +"..." +msgstr "" +"tarantool> box.schema.sequence.create('S',{min=5, start=5})\n" +"---\n" +"- step: 1\n" +" id: 5\n" +" min: 5\n" +" cache: 0\n" +" uid: 1\n" +" max: 9223372036854775807\n" +" cycle: false\n" +" name: S\n" +" start: 5\n" +"..." + +msgid "" +"The result shows that the new sequence has all default values, except for " +"the two that were specified, ``min`` and ``start``." +msgstr "" +"В результате видим, что в новой последовательность есть все значения по " +"умолчанию, за исключением указанных ``min`` и ``start``." + +msgid "Then we get the next value, with the ``next()`` function." +msgstr "Затем получаем следующее значение с помощью функции ``next()``." + +msgid "" +"tarantool> box.sequence.S:next()\n" +"---\n" +"- 5\n" +"..." +msgstr "" +"tarantool> box.sequence.S:next()\n" +"---\n" +"- 5\n" +"..." + +msgid "" +"The result is the same as the start value. If we called ``next()`` again, we" +" would get 6 (because the previous value plus the step value is 6), and so " +"on." +msgstr "" +"Результат точно такой же, как и начальное значение. Если мы снова вызовем " +"``next()``, то получим 6 (потому что предыдущее значение плюс значение шага " +"составит 6) и так далее." + +msgid "" +"Then we create a new table and specify that its primary key should be " +"generated from the sequence." +msgstr "" +"Затем мы создаём новую таблицу и определяем, что ее первичный ключ должен " +"быть получен из последовательности." + +msgid "" +"tarantool> s=box.schema.space.create('T')\n" +"---\n" +"...\n" +"tarantool> s:create_index('I',{sequence='S'})\n" +"---\n" +"- parts:\n" +" - type: unsigned\n" +" is_nullable: false\n" +" fieldno: 1\n" +" sequence_id: 1\n" +" id: 0\n" +" space_id: 520\n" +" unique: true\n" +" type: TREE\n" +" sequence_fieldno: 1\n" +" name: I\n" +"...\n" +"---\n" +"..." +msgstr "" +"tarantool> s=box.schema.space.create('T')\n" +"---\n" +"...\n" +"tarantool> s:create_index('I',{sequence='S'})\n" +"---\n" +"- parts:\n" +" - type: unsigned\n" +" is_nullable: false\n" +" fieldno: 1\n" +" sequence_id: 1\n" +" id: 0\n" +" space_id: 520\n" +" unique: true\n" +" type: TREE\n" +" sequence_fieldno: 1\n" +" name: I\n" +"...\n" +"---\n" +"..." + +msgid "Then we insert a tuple without specifying a value for the primary key." +msgstr "Затем вставляем кортеж, не указывая значение первичного ключа." + +msgid "" +"tarantool> box.space.T:insert{nil,'other stuff'}\n" +"---\n" +"- [6, 'other stuff']\n" +"..." +msgstr "" +"tarantool> box.space.T:insert{nil,'other stuff'}\n" +"---\n" +"- [6, 'other stuff']\n" +"..." + +msgid "" +"The result is a new tuple where the first field has a value of 6. This " +"arrangement, where the system automatically generates the values for a " +"primary key, is sometimes called \"auto-incrementing\" or \"identity\"." +msgstr "" +"В результате имеем новый кортеж со значением 6 в первом поле. Такой способ " +"организации данных, когда система автоматически генерирует значения для " +"первичного ключа, иногда называется \"автоинкрементным\" (т.е. с " +"автоматическим увеличением) или \"по идентификатору\"." + +msgid "" +"For syntax and implementation details, see the reference for " +":doc:`box.schema.sequence `." +msgstr "" +"Для получения подробной информации о синтаксисе и методах реализации см. " +"справочник по :doc:`box.schema.sequence " +"`." diff --git a/locale/ru/LC_MESSAGES/how-to/replication/repl_add_instances.po b/locale/ru/LC_MESSAGES/how-to/replication/repl_add_instances.po new file mode 100644 index 0000000000..92c322faeb --- /dev/null +++ b/locale/ru/LC_MESSAGES/how-to/replication/repl_add_instances.po @@ -0,0 +1,303 @@ + +msgid "Adding instances" +msgstr "Добавление экземпляров" + +msgid "" +"This tutorial is intended as a follow-up to the " +":ref:`replication bootstrapping ` guide. " +"It continues building on the examples from that page. " +"It is recommended that you complete the bootstrapping guide before you proceed." +msgstr "" +"Эта страница логически продолжает " +":ref:`руководство по настройке набора реплик `. " +"Здесь используются и дорабатываются те же примеры. Прежде чем читать дальше, " +"рекомендуется пройти руководство по настройке набора реплик." + +msgid "Adding a replica" +msgstr "Добавление реплики" + +msgid "" +"To add a second **replica** instance to the **master-replica** set from our " +":ref:`bootstrapping example `, we need" +" an analog of the instance file that we created for the first replica in " +"that set:" +msgstr "" +"Чтобы добавить вторую **реплику** в набор реплик с конфигурацией **мастер-" +"реплика** из нашего :ref:`примера настройки `, необходим аналог файла экземпляра, который мы " +"создали для первой реплики в этом наборе:" + +msgid "" +"-- instance file for replica #2\n" +"box.cfg{\n" +" listen = 3301,\n" +" replication = {'replicator:password@192.168.0.101:3301', -- master URI\n" +" 'replicator:password@192.168.0.102:3301', -- replica #1 URI\n" +" 'replicator:password@192.168.0.103:3301'}, -- replica #2 URI\n" +" read_only = true\n" +"}\n" +"box.once(\"schema\", function()\n" +" box.schema.user.create('replicator', {password = 'password'})\n" +" box.schema.user.grant('replicator', 'replication') -- grant replication role\n" +" box.schema.space.create(\"test\")\n" +" box.space.test:create_index(\"primary\")\n" +" print('box.once executed on replica #2')\n" +"end)" +msgstr "" +"-- файл экземпляра для реплики №2\n" +"box.cfg{\n" +" listen = 3301,\n" +" replication = {'replicator:password@192.168.0.101:3301', -- URI мастера\n" +" 'replicator:password@192.168.0.102:3301', -- URI реплики №1\n" +" 'replicator:password@192.168.0.103:3301'}, -- URI реплики №2\n" +" read_only = true\n" +"}\n" +"box.once(\"schema\", function()\n" +" box.schema.user.create('replicator', {password = 'password'})\n" +" box.schema.user.grant('replicator', 'replication') -- предоставить роль для репликации\n" +" box.schema.space.create(\"test\")\n" +" box.space.test:create_index(\"primary\")\n" +" print('box.once executed on replica #2')\n" +"end)" + +msgid "" +"Here we add the URI of replica #2 to the :ref:`replication ` parameter, so now it contains three URIs." +msgstr "" +"Здесь мы добавляем URI реплики №2 в параметр :ref:`replication " +"`, так что теперь он содержит три URI." + +msgid "" +"After we launch the new replica instance, it gets connected to the master " +"instance and retrieves the master's write-ahead-log and snapshot files:" +msgstr "" +"После запуска новая реплика подключается к мастер-серверу и получает от него" +" журнал упреждающей записи и файлы снимков:" + +msgid "" +"$ # launching replica #2\n" +"$ tarantool replica2.lua\n" +"2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> version 1.7.4-52-g980d30092\n" +"2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> log level 5\n" +"2017-06-14 14:54:33.928 [46945] main/101/replica2.lua I> mapping 268435456 bytes for tuple arena...\n" +"2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301\n" +"2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> authenticated\n" +"2017-06-14 14:54:33.930 [46945] main/101/replica2.lua I> bootstrapping replica from 192.168.0.101:3301\n" +"2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> initial data received\n" +"2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> final data received\n" +"2017-06-14 14:54:33.934 [46945] snapshot/101/main I> saving snapshot `/var/lib/tarantool/replica2/00000000000000000010.snap.inprogress'\n" +"2017-06-14 14:54:33.934 [46945] snapshot/101/main I> done\n" +"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> vinyl checkpoint done\n" +"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> ready to accept requests\n" +"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> set 'read_only' configuration option to true\n" +"2017-06-14 14:54:33.936 [46945] main C> entering the event loop" +msgstr "" +"$ # запуск реплики №2\n" +"$ tarantool replica2.lua\n" +"2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> version 1.7.4-52-g980d30092\n" +"2017-06-14 14:54:33.927 [46945] main/101/replica2.lua C> log level 5\n" +"2017-06-14 14:54:33.928 [46945] main/101/replica2.lua I> mapping 268435456 bytes for tuple arena...\n" +"2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301\n" +"2017-06-14 14:54:33.930 [46945] main/104/applier/replicator@192.168.0.10 I> authenticated\n" +"2017-06-14 14:54:33.930 [46945] main/101/replica2.lua I> bootstrapping replica from 192.168.0.101:3301\n" +"2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> initial data received\n" +"2017-06-14 14:54:33.933 [46945] main/104/applier/replicator@192.168.0.10 I> final data received\n" +"2017-06-14 14:54:33.934 [46945] snapshot/101/main I> saving snapshot `/var/lib/tarantool/replica2/00000000000000000010.snap.inprogress'\n" +"2017-06-14 14:54:33.934 [46945] snapshot/101/main I> done\n" +"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> vinyl checkpoint done\n" +"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> ready to accept requests\n" +"2017-06-14 14:54:33.935 [46945] main/101/replica2.lua I> set 'read_only' configuration option to true\n" +"2017-06-14 14:54:33.936 [46945] main C> entering the event loop" + +msgid "" +"Since we are adding a read-only instance, there is no need to dynamically " +"update the ``replication`` parameter on the other running instances. This " +"update would be required if we :ref:`added a master instance `." +msgstr "" +"Поскольку мы добавляем экземпляр только для чтения (read-only), нет " +"необходимости в динамическом обновлении параметра ``replication`` на других " +"работающих экземплярах. Такое обновление необходимо, если бы мы " +":ref:`добавляли мастера `." + +msgid "" +"However, we recommend specifying the URI of replica #3 in all instance files" +" of the replica set. This will keep all the files consistent with each other" +" and with the current replication topology, and so will help to avoid " +"configuration errors in case of further configuration updates and replica " +"set restart." +msgstr "" +"Тем не менее, рекомендуем указать URI реплики №3 во всех файлах экземпляра в" +" наборе реплик. Это поможет сохранить единообразие файлов и согласовать их с" +" текущей топологией репликации, а также не допустить ошибок конфигурации в " +"случае последующего обновления конфигурации и перезапуска набора реплик." + +msgid "Adding a master" +msgstr "Добавление мастера" + +msgid "" +"To add a third master instance to the **master-master** set from our " +":ref:`bootstrapping example `, we need " +"an analog of the instance files that we created to bootstrap the other " +"master instances in that set:" +msgstr "" +"Чтобы добавить третьего мастера в набор реплик с конфигурацией **мастер-" +"мастер** из нашего :ref:`примера настройки `, необходим аналог файлов экземпляров, которые мы " +"создали для настройки других мастеров в этом наборе:" + +msgid "" +"-- instance file for master #3\n" +"box.cfg{\n" +" listen = 3301,\n" +" replication = {'replicator:password@192.168.0.101:3301', -- master#1 URI\n" +" 'replicator:password@192.168.0.102:3301', -- master#2 URI\n" +" 'replicator:password@192.168.0.103:3301'}, -- master#3 URI\n" +" read_only = true, -- temporarily read-only\n" +"}\n" +"box.once(\"schema\", function()\n" +" box.schema.user.create('replicator', {password = 'password'})\n" +" box.schema.user.grant('replicator', 'replication') -- grant replication role\n" +" box.schema.space.create(\"test\")\n" +" box.space.test:create_index(\"primary\")\n" +"end)" +msgstr "" +"-- файл экземпляра для мастера №3\n" +"box.cfg{\n" +" listen = 3301,\n" +" replication = {'replicator:password@192.168.0.101:3301', -- URI мастера №1\n" +" 'replicator:password@192.168.0.102:3301', -- URI мастера №2\n" +" 'replicator:password@192.168.0.103:3301'}, -- URI мастера №3\n" +" read_only = true, -- временно только для чтения\n" +"}\n" +"box.once(\"schema\", function()\n" +" box.schema.user.create('replicator', {password = 'password'})\n" +" box.schema.user.grant('replicator', 'replication') -- выдача роли для репликации\n" +" box.schema.space.create(\"test\")\n" +" box.space.test:create_index(\"primary\")\n" +"end)" + +msgid "Here we make the following changes:" +msgstr "Здесь мы вносим следующие изменения:" + +msgid "" +"Add the URI of master #3 to the :ref:`replication ` parameter." +msgstr "" +"Добавить URI мастера №3 в параметр :ref:`replication `." + +msgid "" +"Temporarily specify :ref:`read_only=true ` to disable " +"data-change operations on the instance. After launch, master #3 will act as " +"a replica until it retrieves all data from the other masters in the replica " +"set." +msgstr "" +"Временно укажите :ref:`read_only=true `, чтобы " +"отключить операции по изменению данных на этом экземпляре. После запуска " +"мастер №3 будет работать в качестве реплики, пока не получит все данные от " +"других мастеров в наборе реплик." + +msgid "" +"After we launch master #3, it gets connected to the other master instances " +"and retrieves their write-ahead-log and snapshot files:" +msgstr "" +"После запуска мастер №3 подключается к другим мастер-экземплярам и получает " +"от них файлы журнала упреждающей записи и файлы снимков:" + +msgid "" +"$ # launching master #3\n" +"$ tarantool master3.lua\n" +"2017-06-14 17:10:00.556 [47121] main/101/master3.lua C> version 1.7.4-52-g980d30092\n" +"2017-06-14 17:10:00.557 [47121] main/101/master3.lua C> log level 5\n" +"2017-06-14 17:10:00.557 [47121] main/101/master3.lua I> mapping 268435456 bytes for tuple arena...\n" +"2017-06-14 17:10:00.559 [47121] iproto/101/main I> binary: bound to [::]:3301\n" +"2017-06-14 17:10:00.559 [47121] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301\n" +"2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.102:3301\n" +"2017-06-14 17:10:00.559 [47121] main/106/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.103:3301\n" +"2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> authenticated\n" +"2017-06-14 17:10:00.559 [47121] main/101/master3.lua I> bootstrapping replica from 192.168.0.102:3301\n" +"2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> initial data received\n" +"2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> final data received\n" +"2017-06-14 17:10:00.562 [47121] snapshot/101/main I> saving snapshot `/Users/e.shebunyaeva/work/tarantool-test-repl/master3_dir/00000000000000000009.snap.inprogress'\n" +"2017-06-14 17:10:00.562 [47121] snapshot/101/main I> done\n" +"2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> vinyl checkpoint done\n" +"2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> ready to accept requests\n" +"2017-06-14 17:10:00.565 [47121] main/101/master3.lua I> set 'read_only' configuration option to true\n" +"2017-06-14 17:10:00.565 [47121] main C> entering the event loop\n" +"2017-06-14 17:10:00.565 [47121] main/104/applier/replicator@192.168.0.10 I> authenticated" +msgstr "" +"$ # запуск мастера №3\n" +"$ tarantool master3.lua\n" +"2017-06-14 17:10:00.556 [47121] main/101/master3.lua C> version 1.7.4-52-g980d30092\n" +"2017-06-14 17:10:00.557 [47121] main/101/master3.lua C> log level 5\n" +"2017-06-14 17:10:00.557 [47121] main/101/master3.lua I> mapping 268435456 bytes for tuple arena...\n" +"2017-06-14 17:10:00.559 [47121] iproto/101/main I> binary: bound to [::]:3301\n" +"2017-06-14 17:10:00.559 [47121] main/104/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.101:3301\n" +"2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.102:3301\n" +"2017-06-14 17:10:00.559 [47121] main/106/applier/replicator@192.168.0.10 I> remote master is 1.7.4 at 192.168.0.103:3301\n" +"2017-06-14 17:10:00.559 [47121] main/105/applier/replicator@192.168.0.10 I> authenticated\n" +"2017-06-14 17:10:00.559 [47121] main/101/master3.lua I> bootstrapping replica from 192.168.0.102:3301\n" +"2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> initial data received\n" +"2017-06-14 17:10:00.562 [47121] main/105/applier/replicator@192.168.0.10 I> final data received\n" +"2017-06-14 17:10:00.562 [47121] snapshot/101/main I> saving snapshot `/Users/e.shebunyaeva/work/tarantool-test-repl/master3_dir/00000000000000000009.snap.inprogress'\n" +"2017-06-14 17:10:00.562 [47121] snapshot/101/main I> done\n" +"2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> vinyl checkpoint done\n" +"2017-06-14 17:10:00.564 [47121] main/101/master3.lua I> ready to accept requests\n" +"2017-06-14 17:10:00.565 [47121] main/101/master3.lua I> set 'read_only' configuration option to true\n" +"2017-06-14 17:10:00.565 [47121] main C> entering the event loop\n" +"2017-06-14 17:10:00.565 [47121] main/104/applier/replicator@192.168.0.10 I> authenticated" + +msgid "" +"Next, we add the URI of master #3 to the ``replication`` parameter on the " +"existing two masters. Replication-related parameters are dynamic, so we only" +" need to make a ``box.cfg{}`` request on each of the running instances:" +msgstr "" +"Затем добавляем URI мастера №3 в параметр ``replication`` на существующих " +"мастерах. В конфигурации репликации используются динамические параметры, " +"поэтому необходимо только выполнить запрос ``box.cfg{}`` на каждом " +"работающем экземпляре:" + +msgid "" +"# adding master #3 URI to replication sources\n" +"tarantool> box.cfg{replication =\n" +" > {'replicator:password@192.168.0.101:3301',\n" +" > 'replicator:password@192.168.0.102:3301',\n" +" > 'replicator:password@192.168.0.103:3301'}}\n" +"---\n" +"..." +msgstr "" +"# добавление URI мастера №3 в источники репликации\n" +"tarantool> box.cfg{replication =\n" +" > {'replicator:password@192.168.0.101:3301',\n" +" > 'replicator:password@192.168.0.102:3301',\n" +" > 'replicator:password@192.168.0.103:3301'}}\n" +"---\n" +"..." + +msgid "" +"When master #3 catches up with the other masters' state, we can disable " +"read-only mode for this instance:" +msgstr "" +"Когда мастер №3 получает все необходимые изменения от других мастеров, можно" +" отключить режим только для чтения:" + +msgid "" +"# making master #3 a real master\n" +"tarantool> box.cfg{read_only=false}\n" +"---\n" +"..." +msgstr "" +"# назначение мастера №3 настоящим мастером\n" +"tarantool> box.cfg{read_only=false}\n" +"---\n" +"..." + +msgid "" +"We also recommend to specify master #3 URI in all instance files in order to" +" keep all the files consistent with each other and with the current " +"replication topology." +msgstr "" +"Также рекомендуется указать URI мастера №3 во всех файлах экземпляра, чтобы " +"сохранить единообразие файлов и согласовать их с текущей топологией " +"репликации." diff --git a/locale/ru/LC_MESSAGES/book/replication/repl_bootstrap.po b/locale/ru/LC_MESSAGES/how-to/replication/repl_bootstrap.po similarity index 97% rename from locale/ru/LC_MESSAGES/book/replication/repl_bootstrap.po rename to locale/ru/LC_MESSAGES/how-to/replication/repl_bootstrap.po index 35848bb7d9..adbc278c3a 100644 --- a/locale/ru/LC_MESSAGES/book/replication/repl_bootstrap.po +++ b/locale/ru/LC_MESSAGES/how-to/replication/repl_bootstrap.po @@ -2,6 +2,38 @@ msgid "Bootstrapping a replica set" msgstr "Настройка набора реплик" +msgid "Replication setup" +msgstr "Первоначальная настройка репликации" + +msgid "" +"To enable :ref:`replication `, you need to specify two parameters in a ``box.cfg{}``" +" request:" +msgstr "" +"Чтобы включить репликацию, необходимо указать два параметра в запросе " +"``box.cfg{}``:" + +msgid "" +":ref:`replication ` which defines the " +"replication source(s), and" +msgstr "" +":ref:`replication `, который определяет " +"источники репликации, и" + +msgid "" +":ref:`read_only ` which is ``true`` for a replica and " +"``false`` for a master." +msgstr "" +":ref:`read_only ` со значением ``true`` для реплики и " +"``false`` для мастера." + +msgid "" +"Both these parameters are \"dynamic\". This allows a replica to become a " +"master and vice versa on the fly with the help of a ``box.cfg{}`` request." +msgstr "" +"\"Динамические\" параметры репликации можно менять на лету, что позволяет " +"назначать реплику на роль мастера и наоборот. Для этого используется запрос " +"``box.cfg{}``." + msgid "Master-replica bootstrap" msgstr "Настройка репликации мастер-реплика" diff --git a/locale/ru/LC_MESSAGES/how-to/replication/repl_leader_elect.po b/locale/ru/LC_MESSAGES/how-to/replication/repl_leader_elect.po new file mode 100644 index 0000000000..b945cfd4ad --- /dev/null +++ b/locale/ru/LC_MESSAGES/how-to/replication/repl_leader_elect.po @@ -0,0 +1,198 @@ +msgid "Configuration" +msgstr "Настройка" + +msgid "" +"box.cfg({\n" +" election_mode = ,\n" +" election_timeout = ,\n" +" replication_timeout = ,\n" +" replication_synchro_quorum = ,\n" +"})" +msgstr "" +"box.cfg({\n" +" election_mode = ,\n" +" election_timeout = ,\n" +" replication_timeout = ,\n" +" replication_synchro_quorum = ,\n" +"})" + +msgid "" +"``election_mode`` -- specifies the role of a node in the leader election " +"process. For the details, refer to the :ref:`option description " +"` in the configuration reference." +msgstr "" +"``election_mode`` — определяет роль узла в процессе выборов лидера. " +"Подробное :ref:`описание параметра ` " +"приводится в справочнике по настройке." + +msgid "" +"``election_timeout`` -- specifies the timeout between election rounds if the" +" previous round ended up with a split vote. For the details, refer to the " +":ref:`option description ` in the " +"configuration reference." +msgstr "" +"``election_timeout`` — задает промежуток времени между турами в случае " +"разделения голосов и последующих перевыборов. Подробное :ref:`описание " +"параметра ` приводится в справочнике по " +"настройке." + +msgid "" +"``replication_timeout`` -- reuse of the :ref:`replication_timeout " +"` configuration option for the purpose " +"of the leader election process. Heartbeats sent by an active leader have a " +"timeout after which a new election starts. Heartbeats are sent once per " +" seconds. Default value is ``1``. The leader is " +"considered dead if it hasn't sent any heartbeats for the period of " +"`` * 4``." +msgstr "" +"``replication_timeout`` — параметр репликации :ref:`replication_timeout " +"`, используемый для выборов лидера. " +"Активный лидер отправляет сообщения контрольного сигнала каждые " +" секунд. Значение параметра по умолчанию — ``1``. Если " +"лидер не отправляет сообщений контрольного сигнала в течение " +"`` * 4`` секунд, он считается недоступным (dead) и " +"начинаются новые выборы." + +msgid "" +"``replication_synchro_quorum`` -- reuse of the " +":ref:`replication_synchro_quorum ` option for the purpose of configuring the " +"election quorum. The default value is ``1``, meaning that each node becomes " +"a leader immediately after voting for itself. It is the best to set up this " +"option value to the ``( / 2) + 1``. Otherwise, there is no " +"guarantee that there is only one leader at a time." +msgstr "" +"``replication_synchro_quorum`` — параметр репликации " +":ref:`replication_synchro_quorum `, используемый для настройки кворума. Значение " +"по умолчанию — ``1``, то есть каждый узел, проголосовав за себя, немедленно " +"становится лидером. Лучше всего задать этому параметру значение ``(<размер " +"кластера> / 2) + 1``. В противном случае нет гарантий, что в каждый момент " +"времени в кластере будет только один лидер." + +msgid "" +"Besides, it is important to know that being a leader is not the only " +"requirement for a node to be writable. A leader node should have its " +":ref:`read_only ` option set to ``false`` " +"(``box.cfg{read_only = false}``), and its :ref:`connectivity quorum " +"` should be satisfied " +"(``box.cfg{replication_connect_quorum = }``) or disabled " +"(``box.cfg{replication_connect_quorum = 0}``)." +msgstr "" +"Важно также понимать, что статус лидера — не единственное, что требуется " +"узлу, чтобы быть доступным для записи. Параметр :ref:`read_only ` на узле-лидере должен иметь значение ``false`` " +"(``box.cfg{read_only = false}``). Необходимо также, чтобы выполнялось " +"условие, заданное параметром :ref:`replication_connect_quorum " +"` " +"(``box.cfg{replication_connect_quorum = }``), или же этот параметр " +"должен быть отключен (``box.cfg{replication_connect_quorum = 0}``)." + +msgid "" +"Nothing prevents from setting the ``read_only`` option to ``true``, but the " +"leader just won't be writable then. The option doesn't affect the election " +"process itself, so a read-only instance can still vote and become a leader." +msgstr "" +"Ничто не мешает задать для параметра ``read_only`` значение ``true``, но это" +" сделает лидера недоступным для записи. На сам процесс выборов параметр " +"никак не влияет, поэтому голосовать и быть лидером может даже экземпляр, " +"доступный только для чтения." + +msgid "Monitoring" +msgstr "Мониторинг" + +msgid "" +"To monitor the current state of a node regarding the leader election, you " +"can use the ``box.info.election`` function. For details, refer to the " +":doc:`function description `." +msgstr "" +"Чтобы отслеживать текущий статус узла в выборах лидера, можно использовать " +"функцию ``box.info.election``. Подробные сведения читайте в :doc:`описании " +"функции `." + +msgid "**Example:**" +msgstr "**Пример:**" + +msgid "" +"tarantool> box.info.election\n" +"---\n" +"- state: follower\n" +" vote: 0\n" +" leader: 0\n" +" term: 1\n" +"..." +msgstr "" +"tarantool> box.info.election\n" +"---\n" +"- state: follower\n" +" vote: 0\n" +" leader: 0\n" +" term: 1\n" +"..." + +msgid "" +"The Raft-based election implementation logs all its actions with the " +"``RAFT:`` prefix. The actions are new Raft message handling, node state " +"changing, voting, term bumping, and so on." +msgstr "" +"Журнальные записи о выборах на основе алгоритма Raft отмечаются префиксом " +"``RAFT:``. В журнал вносятся такие события, как обработка новых сообщений " +"Raft, изменение статуса узла, голосование, увеличение значения терма и пр." + +msgid "Important notes" +msgstr "Важные замечания" + +msgid "" +"Leader election won't work correctly if the election quorum is set to less " +"or equal than `` / 2`` because in that case, a split vote can " +"lead to a state when two leaders are elected at once." +msgstr "" +"Механизм выборов лидера не будет корректно работать, если кворум меньше " +"``<размер кластера> / 2`` или равен этому значению, поскольку в этом случае " +"два лидера могут быть избраны одновременно." + +msgid "" +"For example, let's assume there are five nodes. When quorum is set to ``2``," +" ``node1`` and ``node2`` can both vote for ``node1``. ``node3`` and " +"``node4`` can both vote for ``node5``. In this case, ``node1`` and ``node5``" +" both win the election. When the quorum is set to the cluster majority, that" +" is ``( / 2) + 1`` or bigger, the split vote is not possible." +msgstr "" +"Допустим, есть пять узлов. Если значение кворума — ``2``, то ``node1`` и " +"``node2`` оба могут проголосовать за ``node1``. При этом ``node3`` и " +"``node4`` оба могут проголосовать за ``node5``. Тогда выборы выиграют и " +"``node1``, и ``node5``. Но если в качестве значения кворума установлено " +"большинство, то есть ``(<размер кластера> / 2) + 1`` или больше, то " +"разделение голосов поровну невозможно." + +msgid "" +"That should be considered when adding new nodes. If the majority value is " +"changing, it's better to update the quorum on all the existing nodes before " +"adding a new one." +msgstr "" +"Это особенно актуально при добавлении узлов в кластер. Прежде чем вводить " +"новый узел, рекомендуется обновить значение кворума на всех существующих " +"экземплярах." + +msgid "" +"Also, the automated leader election won't bring many benefits in terms of " +"data safety when used *without* :ref:`synchronous replication `. " +"If the replication is asynchronous and a new leader gets elected, the old " +"leader is still active and considers itself the leader. In such case, " +"nothing stops it from accepting requests from clients and making " +"transactions. Non-synchronous transactions will be successfully committed " +"because they won't be checked against the quorum of replicas. Synchronous " +"transactions will fail because they won't be able to collect the quorum -- " +"most of the replicas will reject these old leader's transactions since it is" +" not a leader anymore." +msgstr "" +"Если использовать автоматические выборы лидера *без* :ref:`синхронной " +"репликации `, может наступить рассогласование данных. При " +"асинхронной репликации успешные выборы нового лидера не означают, что " +"прежний лидер немедленно сложит с себя полномочия. Он по-прежнему будет " +"считать себя активным лидером, принимать запросы от клиентов и совершать " +"транзакции. Асинхронные транзакции, минуя кворум реплик, будут успешно " +"проходить коммиты. При этом синхронные транзакции будут приводить к ошибке, " +"поскольку для их коммита не удастся собрать кворум: большинство реплик будут" +" отвергать транзакции, передаваемые прежним лидером, поскольку уже был " +"избран новый." diff --git a/locale/ru/LC_MESSAGES/book/replication/repl_remove_instances.po b/locale/ru/LC_MESSAGES/how-to/replication/repl_remove_instances.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/replication/repl_remove_instances.po rename to locale/ru/LC_MESSAGES/how-to/replication/repl_remove_instances.po diff --git a/locale/ru/LC_MESSAGES/how-to/replication/repl_sync.po b/locale/ru/LC_MESSAGES/how-to/replication/repl_sync.po new file mode 100644 index 0000000000..f9306a8632 --- /dev/null +++ b/locale/ru/LC_MESSAGES/how-to/replication/repl_sync.po @@ -0,0 +1,182 @@ + +msgid "Configuring synchronous replication" +msgstr "Настройка синхронной репликации" + +msgid "" +"Since version :doc:`2.5.1 `, :ref:`synchronous replication ` can be " +"enabled per-space by using the ``is_sync`` option:" +msgstr "" +"Начиная с версии Tarantool :doc:`2.5.1 `, синхронную " +"репликацию можно включать для отдельных спейсов, используя параметр " +"``is_sync``:" + +msgid "box.schema.create_space('test1', {is_sync = true})" +msgstr "box.schema.create_space('test1', {is_sync = true})" + +msgid "" +"Any transaction doing a DML request on this space becomes synchronous. " +"Notice that DDL on this space (including truncation) is **not** synchronous." +msgstr "" +"Все транзакции, где выполняются DML-запросы к такому спейсу, становятся " +"синхронными. Обратите внимание, что транзакции, где содержатся DDL-операции," +" в том числе запросы на очистку (truncate), синхронными **не будут**." + +msgid "" +"To control the behavior of synchronous transactions, there exist global " +"``box.cfg`` :ref:`options `:" +msgstr "" +"Управлять поведением синхронных транзакций можно с помощью глобальных " +":ref:`параметров ` ``box.cfg``:" + +msgid "box.cfg{replication_synchro_quorum = }" +msgstr "box.cfg{replication_synchro_quorum = <количество экземпляров>}" + +msgid "" +"This option tells how many replicas should confirm the receipt of a " +"synchronous transaction before it is committed. Since version :doc:`2.10.0 `, " +"this option does not account for anonymous replicas. As a usage example, consider " +"this:" +msgstr "" +"Параметр указывает, сколько реплик должно подтвердить получение синхронной " +"транзакции, прежде чем она пройдет коммит. Начиная с версии :doc:`2.10.0 `, " +"анонимные реплики не учитываются. Пример:" + +msgid "" +"-- Instance 1\n" +"box.cfg{\n" +" listen = 3313,\n" +" replication_synchro_quorum = 2,\n" +"}\n" +"box.schema.user.grant('guest', 'super')\n" +"_ = box.schema.space.create('sync', {is_sync=true})\n" +"_ = _:create_index('pk')" +msgstr "" +"-- Экземпляр 1\n" +"box.cfg{\n" +" listen = 3313,\n" +" replication_synchro_quorum = 2,\n" +"}\n" +"box.schema.user.grant('guest', 'super')\n" +"_ = box.schema.space.create('sync', {is_sync=true})\n" +"_ = _:create_index('pk')" + +msgid "" +"-- Instance 2\n" +"box.cfg{\n" +" listen = 3314,\n" +" replication = 'localhost:3313'\n" +"}" +msgstr "" +"-- Экземпляр 2\n" +"box.cfg{\n" +" listen = 3314,\n" +" replication = 'localhost:3313'\n" +"}" + +msgid "" +"-- Instance 1\n" +"box.space.sync:replace{1}" +msgstr "" +"-- Экземпляр 1\n" +"box.space.sync:replace{1}" + +msgid "" +"When the first instance makes ``replace()``, it won't finish until the " +"second instance confirms its receipt and successful appliance. Note that the" +" quorum is set to 2, but the transaction was still committed even though " +"there is only one replica. This is because the master instance itself also " +"participates in the quorum." +msgstr "" +"Операция ``replace()``, вызванная на первом экземпляре, не будет " +"завершена, пока второй экземпляр не подтвердит получение и успешное " +"применение транзакции. Обратите внимание, что кворум равен 2, а реплика " +"одна, но транзакция все же успешно проходит коммит. Это происходит " +"потому, что мастер также участвует в кворуме." + +msgid "" +"Now, if the second instance is down, the first one won't be able to commit " +"any synchronous change." +msgstr "" +"Если второй экземпляр прекратит работу, первый не сможет выполнять коммиты " +"для синхронных изменений." + +msgid "" +"-- Instance 2\n" +"Ctrl+D" +msgstr "" +"-- Экземпляр 2\n" +"Ctrl+D" + +msgid "" +"-- Instance 1\n" +"tarantool> box.space.sync:replace{2}\n" +"---\n" +"- error: Quorum collection for a synchronous transaction is timed out\n" +"..." +msgstr "" +"-- Экземпляр 1\n" +"tarantool> box.space.sync:replace{2}\n" +"---\n" +"- error: Quorum collection for a synchronous transaction is timed out\n" +"..." + +msgid "" +"The transaction wasn't committed because it failed to achieve the quorum in " +"the given time. The time is a second configuration option:" +msgstr "" +"Транзакция не прошла коммит, поскольку за определенное время не был набран " +"кворум. Время — ещё один параметр конфигурации:" + +msgid "" +"box.cfg{replication_synchro_timeout = }" +msgstr "" +"box.cfg{replication_synchro_timeout = <время в секундах; может иметь тип " +"float>}" + +msgid "" +"It tells how many seconds to wait for a synchronous transaction quorum " +"replication until it is declared failed and is rolled back." +msgstr "" +"Параметр указывает, сколько секунд синхронная транзакция будет ожидать " +"репликации на кворуме. По истечении этого времени транзакция будет отменена." + +msgid "" +"A successful synchronous transaction commit is persisted in the WAL as a " +"special CONFIRM record. The rollbacks are similarly persisted with a " +"ROLLBACK record." +msgstr "" +"Успешные коммиты синхронных транзакций персистентно сохраняются в журнал " +"упреждающей записи (WAL) в виде особых записей CONFIRM. Сообщения об отмене " +"транзакций сохраняются аналогичным образом в виде записей ROLLBACK." + +msgid "" +"The ``timeout`` and ``quorum`` options are not used on replicas. It means if" +" the master dies, the pending synchronous transactions will be kept waiting " +"on the replicas until a new master is elected." +msgstr "" +"Параметры ``timeout`` и ``quorum`` на репликах не используются. Если мастер " +"прекратит работу, синхронные транзакции, которые находятся в обработке на " +"репликах, будут ожидать выборов нового мастера." + +msgid "Tips and tricks" +msgstr "Полезные советы" + +msgid "" +"If a transaction is rolled back, it does not mean the ROLLBACK message " +"reached the replicas. It still can happen that the master node suddenly " +"dies, so the transaction will be committed by the new master. Your " +"application logic should be ready for that." +msgstr "" +"Если транзакция была отменена, это не обязательно значит, что реплики " +"получили сообщение ROLLBACK. Может возникнуть ситуация, когда мастер " +"внезапно прекратит работу, а после этого коммит транзакции будет выполнен " +"новым мастером. Учитывайте это в логике вашего приложения." + +msgid "" +"Synchronous transactions are better to use with full mesh. Then the replicas" +" can talk to each other in case of the master node's death and still confirm" +" some pending transactions." +msgstr "" +"Синхронные транзакции лучше всего использовать в кластерах с полноячеистой " +"топологией (full mesh). В этом случае реплики смогут общаться друг с другом " +"и подтверждать некоторые транзакции, даже если откажет мастер." diff --git a/locale/ru/LC_MESSAGES/reference/reference_rock/vshard/vshard_quick.po b/locale/ru/LC_MESSAGES/how-to/vshard_quick.po similarity index 99% rename from locale/ru/LC_MESSAGES/reference/reference_rock/vshard/vshard_quick.po rename to locale/ru/LC_MESSAGES/how-to/vshard_quick.po index 8c1786d1b1..6267338ff5 100644 --- a/locale/ru/LC_MESSAGES/reference/reference_rock/vshard/vshard_quick.po +++ b/locale/ru/LC_MESSAGES/how-to/vshard_quick.po @@ -1,6 +1,6 @@ -msgid "Quick start guide" -msgstr "Руководство по быстрому запуску" +msgid "Quick start with sharding" +msgstr "Введение в шардирование" msgid "" "For installation instructions, check out the :ref:`vshard installation " diff --git a/locale/ru/LC_MESSAGES/reference/reference_lua/box_ctl/promote.po b/locale/ru/LC_MESSAGES/reference/reference_lua/box_ctl/promote.po index b0f913ab1e..206438e2c8 100644 --- a/locale/ru/LC_MESSAGES/reference/reference_lua/box_ctl/promote.po +++ b/locale/ru/LC_MESSAGES/reference/reference_lua/box_ctl/promote.po @@ -6,7 +6,7 @@ msgid "Wait, then choose new replication leader." msgstr "" msgid "" -"For :doc:`synchronous transactions ` it is " +"For :ref:`synchronous transactions ` it is " "possible that a new leader will be chosen but the transactions of the old " "leader have not been completed. Therefore to finalize the transaction, the " "function ``box.ctl.promote()`` should be called, as mentioned in the notes " diff --git a/locale/ru/LC_MESSAGES/reference/reference_rock/vshard/index.po b/locale/ru/LC_MESSAGES/reference/reference_rock/vshard/index.po index 9aa805e66e..2029f53a54 100644 --- a/locale/ru/LC_MESSAGES/reference/reference_rock/vshard/index.po +++ b/locale/ru/LC_MESSAGES/reference/reference_rock/vshard/index.po @@ -13,9 +13,13 @@ msgstr "" "масштабирование в Tarantool." msgid "" -"Check out the :ref:`Quick start guide ` -- or dive into " -"the complete ``vshard`` documentation:" +"To learn how sharding works in Tarantool, refer to the :ref:`Sharding ` page. " msgstr "" -"Стоит начать с :ref:`Руководства по быстрому запуску ` " -"-- или же сразу переходить к углубленному изучению документации по " -"``vshard``:" +"Узнайте, как работает :ref:`шардирование в Tarantool `." + +msgid "" +"You can also check out the :ref:`Quick start guide ` -- or dive into " +"the ``vshard`` reference:" +msgstr "" +"Стоит также обратиться к :ref:`руководству по быстрому запуску `." +" Ниже приводятся справочники по модулю ``vshard``:" diff --git a/locale/ru/LC_MESSAGES/reference/interactive_console.po b/locale/ru/LC_MESSAGES/reference/tooling/interactive_console.po similarity index 100% rename from locale/ru/LC_MESSAGES/reference/interactive_console.po rename to locale/ru/LC_MESSAGES/reference/tooling/interactive_console.po diff --git a/locale/ru/LC_MESSAGES/book/app_server/luajit_getmetrics.po b/locale/ru/LC_MESSAGES/reference/tooling/luajit_getmetrics.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/app_server/luajit_getmetrics.po rename to locale/ru/LC_MESSAGES/reference/tooling/luajit_getmetrics.po diff --git a/locale/ru/LC_MESSAGES/book/app_server/luajit_memprof.po b/locale/ru/LC_MESSAGES/reference/tooling/luajit_memprof.po similarity index 100% rename from locale/ru/LC_MESSAGES/book/app_server/luajit_memprof.po rename to locale/ru/LC_MESSAGES/reference/tooling/luajit_memprof.po diff --git a/locale/ru/LC_MESSAGES/reference/tarantoolctl.po b/locale/ru/LC_MESSAGES/reference/tooling/tarantoolctl.po similarity index 100% rename from locale/ru/LC_MESSAGES/reference/tarantoolctl.po rename to locale/ru/LC_MESSAGES/reference/tooling/tarantoolctl.po diff --git a/locale/ru/LC_MESSAGES/release/2.5.1.po b/locale/ru/LC_MESSAGES/release/2.5.1.po index a49604c732..1a9b784e60 100644 --- a/locale/ru/LC_MESSAGES/release/2.5.1.po +++ b/locale/ru/LC_MESSAGES/release/2.5.1.po @@ -126,7 +126,7 @@ msgid "" msgstr "" msgid "" -":doc:`Synchronous replication ` can be enabled " +":ref:`Synchronous replication ` can be enabled " "per-space using the ``is_sync`` space option (:tarantool-issue:`4842`)." msgstr "" diff --git a/locale/ru/LC_MESSAGES/release/2.7.1.po b/locale/ru/LC_MESSAGES/release/2.7.1.po index a0c38808dc..c82c1de916 100644 --- a/locale/ru/LC_MESSAGES/release/2.7.1.po +++ b/locale/ru/LC_MESSAGES/release/2.7.1.po @@ -24,7 +24,7 @@ msgstr "" msgid "Notable changes are:" msgstr "" -msgid ":doc:`LuaJIT memory profiler `;" +msgid ":ref:`LuaJIT memory profiler `;" msgstr "" msgid "Expression evaluation for ``replication_synchro_quorum``;" @@ -106,7 +106,7 @@ msgstr "" msgid "" "Introduced the LuaJIT memory profiler (:tarantool-issue:`5442`) and the " "profile parser (:tarantool-issue:`5490`). Read more: " -":doc:`/book/app_server/luajit_memprof`." +":ref:`LuaJIT memory profiler `." msgstr "" msgid "Lua" diff --git a/locale/ru/LC_MESSAGES/release/major-features.po b/locale/ru/LC_MESSAGES/release/major-features.po index f5887e2225..50fc541760 100644 --- a/locale/ru/LC_MESSAGES/release/major-features.po +++ b/locale/ru/LC_MESSAGES/release/major-features.po @@ -52,10 +52,10 @@ msgid "2.7.1" msgstr "2.7.1" msgid "" -":doc:`LuaJIT memory profiler ` (:tarantool-" +":ref:`LuaJIT memory profiler ` (:tarantool-" "issue:`5442`)" msgstr "" -":doc:`Профилировщик памяти LuaJIT ` " +":ref:`Профилировщик памяти LuaJIT ` " "(:tarantool-issue:`5442`)" msgid "" @@ -92,10 +92,10 @@ msgstr "" ":ref:`Метрики платформы LuaJIT ` (:tarantool-issue:`5187`)" msgid "" -":doc:`Automated leader election ` based" +":ref:`Automated leader election ` based" " on Raft algorithm (:tarantool-issue:`1146`)" msgstr "" -":doc:`Автоматические выборы лидера ` на" +":ref:`Автоматические выборы лидера ` на" " основе алгоритма Raft (:tarantool-issue:`1146`)" msgid "" @@ -132,10 +132,10 @@ msgid "2.5.1" msgstr "2.5.1" msgid "" -":doc:`Synchronous replication ` (beta) " +":ref:`Synchronous replication ` (beta) " "(:tarantool-issue:`4842`)" msgstr "" -":doc:`Синхронная репликация ` (бета) " +":ref:`Синхронная репликация ` (бета) " "(:tarantool-issue:`4842`)" msgid ""