Skip to content

Commit 864918b

Browse files
committed
update files 2019年 5月17日 星期五 17时24分27秒 CST
1 parent 169c978 commit 864918b

File tree

1 file changed

+42
-5
lines changed

1 file changed

+42
-5
lines changed

prepared.md

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,47 @@ layout: article
33
title: Using Prepared Statements
44
---
55

6+
使用准备好的陈述
7+
68
Prepared statements have all the usual benefits in Go: security, efficiency,
79
convenience. But the way they're implemented is a little different from what
810
you might be used to, especially with regards to how they interact with some of
911
the internals of `database/sql`.
1012

13+
准备好的陈述在Go中具有所有常见的好处:安全性,效率和便利性。但是它们的实现方式与您可能习惯的方式略有不同,特别是关于它们如何与 `database/sql` 的某些内部进行交互。
14+
1115
Prepared Statements And Connections
1216
===================================
1317

18+
准备好的陈述和连接
19+
1420
At the database level, a prepared statement is bound to a single database
1521
connection. The typical flow is that the client sends a SQL statement with
1622
placeholders to the server for preparation, the server responds with a statement
1723
ID, and then the client executes the statement by sending its ID and parameters.
1824

25+
在数据库级别,预准备语句绑定到单个数据库连接。典型的流程是客户端将带有占位符的SQL语句发送到服务器进行准备,服务器使用语句ID进行响应,然后客户端通过发送其ID和参数来执行该语句。
26+
1927
In Go, however, connections are not exposed directly to the user of the
2028
`database/sql` package. You don't prepare a statement on a connection. You
2129
prepare it on a `DB` or a `Tx`. And `database/sql` has some convenience
2230
behaviors such as automatic retries. For these reasons, the underlying
2331
association between prepared statements and connections, which exists at the
2432
driver level, is hidden from your code.
2533

34+
但是,在Go中,连接不会直接暴露给database / sql包的用户。您没有在连接上准备语句。您在DB或Tx上准备它。并且database / sql具有一些便利行为,例如自动重试。由于这些原因,在驱动程序级别存在的预准备语句和连接之间的底层关联对代码是隐藏的。
35+
2636
Here's how it works:
2737

28-
1. When you prepare a statement, it's prepared on a connection in the pool.
29-
2. The `Stmt` object remembers which connection was used.
38+
1. When you prepare a statement, it's prepared on a connection in the pool.
39+
准备语句时,它是在池中的连接上准备的。
40+
2. The `Stmt` object remembers which connection was used.
41+
Stmt对象会记住使用了哪个连接。
3042
3. When you execute the `Stmt`, it tries to use the connection. If it's not
3143
available because it's closed or busy doing something else, it gets another
3244
connection from the pool *and re-prepares the statement with the database on
33-
another connection.*
45+
another connection.*
46+
执行Stmt时,它会尝试使用该连接。如果由于它已关闭或忙于执行其他操作而无法使用,它将从池中获取另一个连接,并在另一个连接上使用数据库重新准备语句。
3447

3548
Because statements will be re-prepared as needed when their original connection
3649
is busy, it's possible for high-concurrency usage of the database, which may
@@ -39,31 +52,45 @@ This can result in apparent leaks of statements, statements being prepared and
3952
re-prepared more often than you think, and even running into server-side limits
4053
on the number of statements.
4154

55+
因为在原始连接繁忙时将根据需要重新准备语句,所以数据库的高并发使用可能会使很多连接繁忙,从而创建大量预准备语句。这可能导致语句的明显泄漏,正在准备和重新准备的语句比您想象的更频繁,甚至在语句数量上遇到服务器端限制。
56+
4257
Avoiding Prepared Statements
4358
============================
4459

60+
避免准备好的陈述
61+
4562
Go creates prepared statements for you under the covers. A simple
4663
`db.Query(sql, param1, param2)`, for example, works by preparing the sql, then
4764
executing it with the parameters and finally closing the statement.
4865

66+
Go为您创建了准备好的陈述。例如,一个简单的db.Query(sql,param1,param2)通过准备sql,然后使用参数执行它并最终关闭语句来工作。
67+
4968
Sometimes a prepared statement is not what you want, however. There might be
5069
several reasons for this:
5170

71+
但是,有时准备好的陈述不是你想要的。可能有以下几种原因:
72+
5273
1. The database doesn't support prepared statements. When using the MySQL
5374
driver, for example, you can connect to MemSQL and Sphinx, because they
5475
support the MySQL wire protocol. But they don't support the "binary" protocol
55-
that includes prepared statements, so they can fail in confusing ways.
76+
that includes prepared statements, so they can fail in confusing ways.
77+
78+
数据库不支持预准备语句。例如,当使用MySQL驱动程序时,您可以连接到MemSQL和Sphinx,因为它们支持MySQL线程协议。但是它们不支持包含预准备语句的“二进制”协议,因此它们可能会以混乱的方式失​​败。
5679
2. The statements aren't reused enough to make them worthwhile, and security
5780
issues are handled in other ways, so performance overhead is undesired. An
5881
example of this can be seen at the
59-
[VividCortex blog](https://vividcortex.com/blog/2014/11/19/analyzing-prepared-statement-performance-with-vividcortex/).
82+
[VividCortex blog](https://vividcortex.com/blog/2014/11/19/analyzing-prepared-statement-performance-with-vividcortex/).
83+
84+
这些语句的重用不足以使它们变得有价值,并且安全问题以其他方式处理,因此不希望出现性能开销。可以在VividCortex博客上看到这方面的一个例子。
6085

6186
If you don't want to use a prepared statement, you need to use `fmt.Sprint()` or
6287
similar to assemble the SQL, and pass this as the only argument to `db.Query()`
6388
or `db.QueryRow()`. And your driver needs to support plaintext query execution,
6489
which is added in Go 1.1 via the `Execer` and `Queryer` interfaces,
6590
[documented here](http://golang.org/pkg/database/sql/driver/#Execer).
6691

92+
如果您不想使用预准备语句,则需要使用 `fmt.Sprint()` 或类似语法来组装SQL,并将其作为 `db.Query()``db.QueryRow()` 的唯一参数传递。并且您的驱动程序需要支持明文查询执行,这是通过此处记录的 `Execer``Queryer` 接口在Go 1.1中添加的。
93+
6794
Prepared Statements in Transactions
6895
===================================
6996

@@ -72,20 +99,28 @@ it, so the earlier cautions about repreparing do not apply. When
7299
you operate on a `Tx` object, your actions map directly to the one and only one
73100
connection underlying it.
74101

102+
在Tx中创建的预处理语句仅与其绑定,因此之前关于重新表示的警告不适用。当您对Tx对象进行操作时,您的操作将直接映射到其下的唯一连接。
103+
75104
This also means that prepared statements created inside a `Tx` can't be used
76105
separately from it. Likewise, prepared statements created on a `DB` can't be
77106
used within a transaction, because they will be bound to a different connection.
78107

108+
这也意味着在Tx中创建的预处理语句不能与它分开使用。同样,在DB上创建的预准备语句不能在事务中使用,因为它们将绑定到不同的连接。
109+
79110
To use a prepared statement prepared outside the transaction in a `Tx`, you can use
80111
`Tx.Stmt()`, which will create a new transaction-specific statement from the one
81112
prepared outside the transaction. It does this by taking an existing prepared statement,
82113
setting the connection to that of the transaction and repreparing all statements every
83114
time they are executed. This behavior and its implementation are undesirable and there's
84115
even a TODO in the `database/sql` source code to improve it; we advise against using this.
85116

117+
要在Tx中使用在事务外部准备的预准备语句,可以使用Tx.Stmt(),它将从事务外部准备的语句创建新的特定于事务的语句。它通过获取现有的预准备语句,将连接设置为事务的连接并在每次执行时重新表示所有语句来完成此操作。这种行为及其实现是不可取的,在数据​​库/ sql源代码中甚至还有一个TODO来改进它;我们建议不要使用它。
118+
86119
Caution must be exercised when working with prepared statements in
87120
transactions. Consider the following example:
88121

122+
在交易中处理准备好的报表时必须谨慎行事。请考虑以下示例:
123+
89124
<pre class="prettyprint lang-go">
90125
tx, err := db.Begin()
91126
if err != nil {
@@ -118,6 +153,8 @@ underlying connection, rendering the connection state inconsistent.
118153
If you use Go 1.4 or older, you should make sure the statement is always closed before the transaction is
119154
committed or rolled back. [This issue](https://github.com/golang/go/issues/4459) was fixed in Go 1.4 by [CR 131650043](https://codereview.appspot.com/131650043).
120155

156+
在Go 1.4关闭之前,* sql.Tx将与之关联的连接释放回池中,但是在已经发生的情况下执行了对准备好的语句的延迟调用Close,这可能导致并发访问底层连接,从而呈现连接状态不一致。如果使用Go 1.4或更早版本,则应确保在提交或回滚事务之前始终关闭该语句。 CR 131650043在Go 1.4中修复了此问题。
157+
121158
Parameter Placeholder Syntax
122159
============================
123160

0 commit comments

Comments
 (0)