英文:
In CockroachDB, how do batches and transactions interact?
问题
你应该在什么时候使用批处理,什么时候使用事务?我可以将事务嵌入到批处理中吗?批处理中可以包含事务吗?
英文:
When should I use batches and when should I use transactions? Can I embed a transaction in a batch? A batch in a transaction?
答案1
得分: 8
一个_batch_是一组操作,作为一个单元一起发送到服务器以提高效率。它相当于从不同线程发送相同操作的单独请求。批处理中的请求可能会无序执行,并且批处理中的某些操作可能成功,而其他操作可能失败。
在Go中,可以使用批处理对象DB.B
创建批处理,并且必须将其传递给DB.Run()
。例如:
err := db.Run(db.B.Put("a", "1").Put("b", "2"))
等同于:
_, err1 := db.Put("a", "1")
_, err2 := db.Put("b", "2")
_事务_定义了一系列一致且原子的操作。事务保证与系统中的所有其他操作一致性:除非事务提交,否则无法看到事务的结果。由于事务可能需要重试,因此事务由函数对象(通常是闭包)定义,可以多次调用。
在Go中,可以使用DB.Tx方法创建事务。闭包的*client.Tx
参数实现了与DB
类似的接口;在事务中,您必须在此对象上执行所有操作,而不是在原始DB上执行。如果函数返回错误,事务将被中止;否则,它将提交。以下是先前示例的事务版本(但请参阅下面的更高效版本):
err := db.Tx(func(tx *client.Tx) error {
err := tx.Put("a", "1")
if err != nil {
return err
}
return tx.Put("b", "2")
})
先前的示例在开始“b”写入之前等待“a”写入完成,然后在提交事务之前等待“b”写入完成。通过在事务中使用批处理,可以使其更高效。Tx.B
是一个批处理对象,就像DB.B
一样。在事务中,可以使用Tx.Run
或Tx.Commit
运行批处理。只有当批处理中的所有其他操作都成功时,Tx.Commit
才会提交事务,并且比让事务在闭包返回时自动提交更高效。在事务中,始终将最后一个操作作为由Tx.Commit
执行的批处理是一个好习惯:
err := db.Tx(func(tx *client.Tx) error {
return tx.Commit(tx.B.Put("a", "1").Put("b", "2"))
})
英文:
A batch is a collection of operations that are sent to the server as a single unit for efficiency. It is equivalent to sending the same operations as individual requests from different threads. Requests in a batch may be executed out of order, and it's possible for some operations in a batch to succeed while others fail.
In Go, batches are created with the batcher object DB.B
, and must be passed to DB.Run()
. For example:
err := db.Run(db.B.Put("a", "1").Put("b", "2"))
is equivalent to:
_, err1 := db.Put("a", "1")
_, err2 := db.Put("b", "2")
A transaction defines a consistent and atomic sequence of operations. Transactions guarantee consistency with respect to all other operations in the system: the results of a transaction cannot be seen unless and until the transaction is committed. Since transactions may need to be retried, transactions are defined by function objects (typically closures) which may be called multiple times.
In Go, transactions are created with the DB.Tx method. The *client.Tx
parameter to the closure implements a similar interface to DB
; inside the transaction you must perform all your operations on this object instead of the original DB. If your function returns an error, the transaction will be aborted; otherwise it will commit. Here is a transactional version of the previous example (but see below for a more efficient version):
err := db.Tx(func(tx *client.Tx) error {
err := tx.Put("a", "1")
if err != nil {
return err
}
return tx.Put("b", "2")
})
The previous example waits for the "a" write to complete before starting the "b" write, and then waits for the "b" write to complete before committing the transaction. It is possible to make this more efficient by using batches inside the transaction. Tx.B
is a batcher object, just like DB.B
. In a transaction, you can run batches with either Tx.Run
or Tx.Commit
. Tx.Commit
will commit the transaction if and only if all other operations in the batch succeed, and is more efficient than letting the transaction commit automatically when the closure returns. It is a good practice to always make the last operation in a transaction a batch executed by Tx.Commit
:
err := db.Tx(func(tx *client.Tx) error {
return tx.Commit(tx.B.Put("a", "1").Put("b", "2"))
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论