mirror of https://gitee.com/bigwinds/arangodb
parent
5cd9ad7ee1
commit
9b53d3cd45
|
@ -1,6 +1,8 @@
|
|||
devel
|
||||
-----
|
||||
|
||||
* removed `exception` field from transaction error result; users should throw
|
||||
explicit `Error` instances to return custom exceptions (addresses issue #2561)
|
||||
|
||||
v3.2.beta1 (2017-06-12)
|
||||
-----------------------
|
||||
|
|
|
@ -10,13 +10,13 @@ SQL transaction is finished with a *COMMIT* command, or rolled back with a
|
|||
and the commit/rollback of an SQL transaction.
|
||||
|
||||
In ArangoDB, a transaction is always a server-side operation, and is executed
|
||||
on the server in one go, without any client interaction. All operations to be
|
||||
executed inside a transaction need to be known by the server when the transaction
|
||||
on the server in one go, without any client interaction. All operations to be
|
||||
executed inside a transaction need to be known by the server when the transaction
|
||||
is started.
|
||||
|
||||
There are no individual *BEGIN*, *COMMIT* or *ROLLBACK* transaction commands
|
||||
in ArangoDB. Instead, a transaction in ArangoDB is started by providing a
|
||||
description of the transaction to the *db._executeTransaction* JavaScript
|
||||
There are no individual *BEGIN*, *COMMIT* or *ROLLBACK* transaction commands
|
||||
in ArangoDB. Instead, a transaction in ArangoDB is started by providing a
|
||||
description of the transaction to the *db._executeTransaction* JavaScript
|
||||
function:
|
||||
|
||||
```js
|
||||
|
@ -24,7 +24,7 @@ db._executeTransaction(description);
|
|||
```
|
||||
|
||||
This function will then automatically start a transaction, execute all required
|
||||
data retrieval and/or modification operations, and at the end automatically
|
||||
data retrieval and/or modification operations, and at the end automatically
|
||||
commit the transaction. If an error occurs during transaction execution, the
|
||||
transaction is automatically aborted, and all changes are rolled back.
|
||||
|
||||
|
@ -61,7 +61,7 @@ Additionally, *object* can have the following optional attributes:
|
|||
*action*.
|
||||
|
||||
The following attributes can be used for transactions in the RocksDB storage engine:
|
||||
|
||||
|
||||
- *maxTransactionSize*: transaction size limit in bytes
|
||||
- *intermediateCommitSize*: maximum total size of operations after which an intermediate
|
||||
commit is performed automatically
|
||||
|
@ -71,22 +71,22 @@ The following attributes can be used for transactions in the RocksDB storage eng
|
|||
|
||||
### Declaration of collections
|
||||
|
||||
All collections which are to participate in a transaction need to be declared
|
||||
beforehand. This is a necessity to ensure proper locking and isolation.
|
||||
All collections which are to participate in a transaction need to be declared
|
||||
beforehand. This is a necessity to ensure proper locking and isolation.
|
||||
|
||||
Collections can be used in a transaction in write mode or in read-only mode.
|
||||
|
||||
If any data modification operations are to be executed, the collection must be
|
||||
declared for use in write mode. The write mode allows modifying and reading data
|
||||
from the collection during the transaction (i.e. the write mode includes the
|
||||
If any data modification operations are to be executed, the collection must be
|
||||
declared for use in write mode. The write mode allows modifying and reading data
|
||||
from the collection during the transaction (i.e. the write mode includes the
|
||||
read mode).
|
||||
|
||||
Contrary, using a collection in read-only mode will only allow performing
|
||||
Contrary, using a collection in read-only mode will only allow performing
|
||||
read operations on a collection. Any attempt to write into a collection used
|
||||
in read-only mode will make the transaction fail.
|
||||
|
||||
Collections for a transaction are declared by providing them in the *collections*
|
||||
attribute of the object passed to the *_executeTransaction* function. The
|
||||
Collections for a transaction are declared by providing them in the *collections*
|
||||
attribute of the object passed to the *_executeTransaction* function. The
|
||||
*collections* attribute has the sub-attributes *read* and *write*:
|
||||
|
||||
```js
|
||||
|
@ -98,10 +98,10 @@ db._executeTransaction({
|
|||
});
|
||||
```
|
||||
|
||||
*read* and *write* are optional attributes, and only need to be specified if
|
||||
*read* and *write* are optional attributes, and only need to be specified if
|
||||
the operations inside the transactions demand for it.
|
||||
|
||||
The contents of *read* or *write* can each be lists arrays collection names or a
|
||||
The contents of *read* or *write* can each be lists arrays collection names or a
|
||||
single collection name (as a string):
|
||||
|
||||
```js
|
||||
|
@ -115,7 +115,7 @@ db._executeTransaction({
|
|||
|
||||
**Note**: It is currently optional to specify collections for read-only access.
|
||||
Even without specifying them, it is still possible to read from such collections
|
||||
from within a transaction, but with relaxed isolation. Please refer to
|
||||
from within a transaction, but with relaxed isolation. Please refer to
|
||||
[Transactions Locking](../Transactions/LockingAndIsolation.md) for more details.
|
||||
|
||||
In order to make a transaction fail when a non-declared collection is used inside
|
||||
|
@ -153,14 +153,14 @@ db._executeTransaction({
|
|||
write: "users"
|
||||
},
|
||||
action: function () {
|
||||
// all operations go here
|
||||
// all operations go here
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Any valid Javascript code is allowed inside *action* but the code may only
|
||||
access the collections declared in *collections*.
|
||||
*action* may be a Javascript function as shown above, or a string representation
|
||||
*action* may be a Javascript function as shown above, or a string representation
|
||||
of a Javascript function:
|
||||
|
||||
```
|
||||
|
@ -171,10 +171,10 @@ db._executeTransaction({
|
|||
action: "function () { doSomething(); }"
|
||||
});
|
||||
```
|
||||
Please note that any operations specified in *action* will be executed on the
|
||||
server, in a separate scope. Variables will be bound late. Accessing any JavaScript
|
||||
Please note that any operations specified in *action* will be executed on the
|
||||
server, in a separate scope. Variables will be bound late. Accessing any JavaScript
|
||||
variables defined on the client-side or in some other server context from inside
|
||||
a transaction may not work.
|
||||
a transaction may not work.
|
||||
Instead, any variables used inside *action* should be defined inside *action* itself:
|
||||
|
||||
```
|
||||
|
@ -190,9 +190,9 @@ db._executeTransaction({
|
|||
```
|
||||
|
||||
When the code inside the *action* attribute is executed, the transaction is
|
||||
already started and all required locks have been acquired. When the code inside
|
||||
already started and all required locks have been acquired. When the code inside
|
||||
the *action* attribute finishes, the transaction will automatically commit.
|
||||
There is no explicit commit command.
|
||||
There is no explicit commit command.
|
||||
|
||||
To make a transaction abort and roll back all changes, an exception needs to
|
||||
be thrown and not caught inside the transaction:
|
||||
|
@ -205,7 +205,7 @@ db._executeTransaction({
|
|||
action: function () {
|
||||
var db = require("@arangodb").db;
|
||||
db.users.save({ _key: "hello" });
|
||||
// will abort and roll back the transaction
|
||||
// will abort and roll back the transaction
|
||||
throw "doh!";
|
||||
}
|
||||
});
|
||||
|
@ -214,7 +214,7 @@ db._executeTransaction({
|
|||
There is no explicit abort or roll back command.
|
||||
|
||||
As mentioned earlier, a transaction will commit automatically when the end of
|
||||
the *action* function is reached and no exception has been thrown. In this
|
||||
the *action* function is reached and no exception has been thrown. In this
|
||||
case, the user can return any legal JavaScript value from the function:
|
||||
|
||||
```js
|
||||
|
@ -225,16 +225,39 @@ db._executeTransaction({
|
|||
action: function () {
|
||||
var db = require("@arangodb").db;
|
||||
db.users.save({ _key: "hello" });
|
||||
// will commit the transaction and return the value "hello"
|
||||
return "hello";
|
||||
// will commit the transaction and return the value "hello"
|
||||
return "hello";
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Custom exceptions
|
||||
|
||||
One may wish to define custom exceptions inside of a transaction. To have the
|
||||
exception propagate upwards properly, please throw an an instance of base
|
||||
JavaScript `Error` class or a derivative. To specify an error number, include it
|
||||
as the `errorNumber` field. As an example:
|
||||
|
||||
```js
|
||||
db._executeTransaction({
|
||||
collections: {},
|
||||
action: function () {
|
||||
var err = new Error('My error context');
|
||||
err.errorNumber = 1234;
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Note**: In previous versions, custom exceptions which did not have an
|
||||
`Error`-like form were simply converted to strings and exposed in the
|
||||
`exception` field of the returned error. This is no longer the case, as it had
|
||||
the potential to leak unwanted information if improperly used.
|
||||
|
||||
### Examples
|
||||
|
||||
The first example will write 3 documents into a collection named *c1*.
|
||||
The *c1* collection needs to be declared in the *write* attribute of the
|
||||
The first example will write 3 documents into a collection named *c1*.
|
||||
The *c1* collection needs to be declared in the *write* attribute of the
|
||||
*collections* attribute passed to the *executeTransaction* function.
|
||||
|
||||
The *action* attribute contains the actual transaction code to be executed.
|
||||
|
@ -255,7 +278,7 @@ db._executeTransaction({
|
|||
db.c1.save({ _key: "key3" });
|
||||
}
|
||||
});
|
||||
db.c1.count(); // 3
|
||||
db.c1.count(); // 3
|
||||
```
|
||||
|
||||
Aborting the transaction by throwing an exception in the *action* function
|
||||
|
@ -272,21 +295,21 @@ db._executeTransaction({
|
|||
action: function () {
|
||||
var db = require("@arangodb").db;
|
||||
db.c1.save({ _key: "key1" });
|
||||
db.c1.count(); // 1
|
||||
db.c1.count(); // 1
|
||||
db.c1.save({ _key: "key2" });
|
||||
db.c1.count(); // 2
|
||||
db.c1.count(); // 2
|
||||
throw "doh!";
|
||||
}
|
||||
});
|
||||
|
||||
db.c1.count(); // 0
|
||||
db.c1.count(); // 0
|
||||
```
|
||||
|
||||
The automatic rollback is also executed when an internal exception is thrown
|
||||
The automatic rollback is also executed when an internal exception is thrown
|
||||
at some point during transaction execution:
|
||||
|
||||
```js
|
||||
// setup
|
||||
// setup
|
||||
db._create("c1");
|
||||
|
||||
db._executeTransaction({
|
||||
|
@ -296,27 +319,27 @@ db._executeTransaction({
|
|||
action: function () {
|
||||
var db = require("@arangodb").db;
|
||||
db.c1.save({ _key: "key1" });
|
||||
// will throw duplicate a key error, not explicitly requested by the user
|
||||
// will throw duplicate a key error, not explicitly requested by the user
|
||||
db.c1.save({ _key: "key1" });
|
||||
// we'll never get here...
|
||||
// we'll never get here...
|
||||
}
|
||||
});
|
||||
|
||||
db.c1.count(); // 0
|
||||
db.c1.count(); // 0
|
||||
```
|
||||
|
||||
As required by the *consistency* principle, aborting or rolling back a
|
||||
As required by the *consistency* principle, aborting or rolling back a
|
||||
transaction will also restore secondary indexes to the state at transaction
|
||||
start.
|
||||
|
||||
### Cross-collection transactions
|
||||
|
||||
There's also the possibility to run a transaction across multiple collections.
|
||||
There's also the possibility to run a transaction across multiple collections.
|
||||
In this case, multiple collections need to be declared in the *collections*
|
||||
attribute, e.g.:
|
||||
|
||||
```js
|
||||
// setup
|
||||
// setup
|
||||
db._create("c1");
|
||||
db._create("c2");
|
||||
|
||||
|
@ -331,15 +354,15 @@ db._executeTransaction({
|
|||
}
|
||||
});
|
||||
|
||||
db.c1.count(); // 1
|
||||
db.c1.count(); // 1
|
||||
db.c2.count(); // 1
|
||||
```
|
||||
|
||||
Again, throwing an exception from inside the *action* function will make the
|
||||
Again, throwing an exception from inside the *action* function will make the
|
||||
transaction abort and roll back all changes in all collections:
|
||||
|
||||
```js
|
||||
// setup
|
||||
// setup
|
||||
db._create("c1");
|
||||
db._create("c2");
|
||||
|
||||
|
@ -353,13 +376,13 @@ db._executeTransaction({
|
|||
db.c1.save({ _key: "key" + i });
|
||||
db.c2.save({ _key: "key" + i });
|
||||
}
|
||||
db.c1.count(); // 100
|
||||
db.c2.count(); // 100
|
||||
// abort
|
||||
db.c1.count(); // 100
|
||||
db.c2.count(); // 100
|
||||
// abort
|
||||
throw "doh!"
|
||||
}
|
||||
});
|
||||
|
||||
db.c1.count(); // 0
|
||||
db.c2.count(); // 0
|
||||
db.c1.count(); // 0
|
||||
db.c2.count(); // 0
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue