

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Neptune 中的 Gremlin 事务
<a name="access-graph-gremlin-transactions"></a>

Gremlin [事务](transactions.md)的执行上下文有多种。在与 Gremlin 结合使用时，务必了解您所处的上下文及其影响：
+ **`Script-based`** – 使用基于文本的 Gremlin 字符串发出请求，如下所示：
  + 使用 Java 驱动程序和 `Client.submit({{string}})`。
  + 使用 Gremlin 控制台和 `:remote connect`。
  + 使用 HTTP API。
+ **`Bytecode-based`** – 请求是使用 [Gremlin 语言变体](https://tinkerpop.apache.org/docs/current/reference/#gremlin-drivers-variants) (GLV) 中典型的序列化的 Gremlin 字节码发出的。

  例如，使用 Java 驱动程序 `g = traversal().withRemote({{...}})`。

对于上述任一上下文，都有额外的上下文，即请求以无会话或绑定到会话的形式发送。

**注意**  
 Gremlin 事务必须始终提交或回滚，这样才能释放服务器端资源。如果在事务过程中出现错误，请务必重试整个事务，而不仅仅是失败的特定请求。

## 无会话请求
<a name="access-graph-gremlin-transactions-sessionless"></a>

 无会话时，请求等同于单个事务。

对于脚本来说，这意味着在单个请求中发送的一条或多条 Gremlin 语句将作为单个事务提交或回滚。例如：

```
Cluster cluster = Cluster.open();
Client client = cluster.connect(); // sessionless
// 3 vertex additions in one request/transaction:
client.submit("g.addV();g.addV();g.addV()").all().get();
```

对于字节码，会对从 `g` 生成和执行的每个遍历发出无会话请求：

```
GraphTraversalSource g = traversal().withRemote({{...}});

// 3 vertex additions in three individual requests/transactions:
g.addV().iterate();
g.addV().iterate();
g.addV().iterate();

// 3 vertex additions in one single request/transaction:
g.addV().addV().addV().iterate();
```

## 绑定到会话的请求
<a name="access-graph-gremlin-transactions-session-bound"></a>

绑定到会话时，可以在单个事务的上下文中应用多个请求。

对于脚本来说，这意味着没有必要将所有图形操作串联成单个嵌入式字符串值：

```
Cluster cluster = Cluster.open();
Client client = cluster.connect(sessionName); // session
try {
    // 3 vertex additions in one request/transaction:
    client.submit("g.addV();g.addV();g.addV()").all().get();
} finally {
    client.close();
}

try {
    // 3 vertex additions in three requests, but one transaction:
    client.submit("g.addV()").all().get(); // starts a new transaction with the same sessionName
    client.submit("g.addV()").all().get();
    client.submit("g.addV()").all().get();
} finally {
    client.close();
}
```

对于基于脚本的会话，关闭客户端并`client.close()`提交事务。基于脚本的会话中没有明确的回滚命令可用。要强制回滚，您可以通过发出查询（例如`g.inject(0).fail('rollback')`在关闭客户端之前）来导致事务失败。

**注意**  
像这样的`g.inject(0).fail('rollback')`查询用来故意抛出错误以强制回滚，但在客户端上会产生异常。在关闭客户端之前，捕获并丢弃生成的异常。

对于字节码，可以显式控制事务并透明地管理会话。Gremlin 语言变体 (GLV) 支持 Gremlin 对事务执行 `commit()` 或 `rollback()` 的 `tx()` 语法，如下所示：

```
GraphTraversalSource g = traversal().withRemote(conn);

Transaction tx = g.tx();

// Spawn a GraphTraversalSource from the Transaction.
// Traversals spawned from gtx are executed within a single transaction.
GraphTraversalSource gtx = tx.begin();
try {
    gtx.addV('person').iterate();
    gtx.addV('software').iterate();

    tx.commit();
} finally {
    if (tx.isOpen()) {
        tx.rollback();
    }
}
```

尽管上面的示例是用 Java 编写的，但您也可以在其他语言中使用此`tx()`语法。[有关特定语言的事务语法，请参阅 Java、Pyth [on](https://tinkerpop.apache.org/docs/current/reference/#gremlin-python-transactions)、[Javascri](https://tinkerpop.apache.org/docs/current/reference/#gremlin-javascript-transactions) pt [、](https://tinkerpop.apache.org/docs/current/reference/#gremlin-java-transactions)[.NET](https://tinkerpop.apache.org/docs/current/reference/#gremlin-dotnet-transactions) 和 Go 的 Apache TinkerPop 文档的 “事务” 部分。](https://tinkerpop.apache.org/docs/current/reference/#gremlin-go-transactions)

**警告**  
无会话只读查询在 [SNAPSHOT](transactions-isolation-levels.md) 隔离下执行，但在显式事务中运行的只读查询则在 [SERIALIZABLE](transactions-isolation-levels.md) 隔离下执行。与在 `SNAPSHOT` 隔离下运行的只读查询不同，在 `SERIALIZABLE` 隔离下执行的只读查询会产生更高的开销，并且可能阻塞并发写入或被并发写入阻塞。

## 字节码提交和回滚的超时行为
<a name="access-graph-gremlin-transactions-commit-rollback-timeout"></a>

在`tx()`语法中使用基于字节码的事务时，`commit()`和`rollback()`操作不受查询超时设置的约束。通过设置的全局`neptune_query_timeout`参数和每个查询的超时值均不`evaluationTimeout`适用于这些操作。在服务器上`commit()`，在没有时间限制的情况下`rollback()`运行，直到它们完成或遇到错误。

在客户端，直到服务器做出响应，Gremlin 驱动程序`tx.commit()`和`tx.rollback()`调用才会完成。根据语言的不同，这可能表现为阻塞调用或未解决的异步操作。没有驱动程序提供限制这些调用的内置超时设置。有关这些事务功能的并发行为的详细信息，请查阅您的特定 Gremlin 语言变体的 API 文档。

**重要**  
如果`commit()`或`rollback()`调用所花费的时间比预期的长，则可能会因并发事务的锁争用而被阻止。有关锁冲突的更多信息，请参阅[使用 Lock-Wait 超时解决冲突](transactions-neptune.md#transactions-neptune-conflicts)。

如果您需要限制应用程序等待`commit()`或的时间`rollback()`，则可以使用所用语言的并发功能来应用客户端超时。如果触发客户端超时，服务器将继续处理该操作。服务器端操作会保留一个工作线程，直到它完成。在客户端超时后，关闭连接并创建一个新连接，而不是重复使用现有连接，因为事务状态不确定。

### Server-side 交易清理
<a name="access-graph-gremlin-transactions-server-side-cleanup"></a>

如果客户端在不提交或回滚的情况下断开连接或放弃事务，Neptune 会使用服务器端机制最终清理孤立的事务：
+  Bytecode-based 会@@ **话超时** — 闲置时间超过最大会话生命周期（10 分钟）的会话将被关闭，所有未完成的事务都将被回滚。
+ **连接空闲超时** — Neptune 关闭空闲了大约 20 分钟的 WebSocket 连接。连接关闭后，服务器会回滚与该连接关联的所有未完成的事务。

这些清理机制是安全网。我们建议您在处理完事务后始终明确提交或回滚事务。