{"id":461350,"date":"2025-05-29T03:00:09","date_gmt":"2025-05-29T03:00:09","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=461350"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=461350","title":{"rendered":"<span>\u0411\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f. SimpleProtocol vs BinaryParameters<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/65c\/8a6\/cfc\/65c8a6cfc470218e38c4070eff096f5e.webp\" alt=\"\u0430\u0440\u0442\u044b \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0438\" title=\"\u0430\u0440\u0442\u044b \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0438\" width=\"1792\" height=\"1024\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/65c\/8a6\/cfc\/65c8a6cfc470218e38c4070eff096f5e.webp 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/65c\/8a6\/cfc\/65c8a6cfc470218e38c4070eff096f5e.webp 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0430\u0440\u0442\u044b \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u042f \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435, \u043a\u0442\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0432 \u0441\u0442\u0435\u043a\u0435 Go + PgBouncer + PostgreSQL, \u0443\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u043d\u044f\u043b\u0438, \u043e \u0447\u0451\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f prepared statements \u0438 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u0432\u0443\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u0432 \u0434\u043b\u044f PostgreSQL: <a href=\"https:\/\/github.com\/lib\/pq\" rel=\"noopener noreferrer nofollow\">lib\/pq<\/a> \u0438 <a href=\"https:\/\/github.com\/jackc\/pgx\" rel=\"noopener noreferrer nofollow\">jackc\/pgx<\/a>.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u2014 \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u0442.<\/p>\n<hr\/>\n<h3>\ud83e\udde8 \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b<\/h3>\n<p>1. \u041e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u2014 PgBouncer<br \/>PgBouncer \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u043f\u0443\u043b \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u043a PostgreSQL \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0438\u0445 \u043c\u0435\u0436\u0434\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432 \u0440\u0430\u0437\u044b \u0431\u043e\u043b\u044c\u0448\u0435. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 3 \u0440\u0435\u0436\u0438\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b PgBouncer \u0441 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\u043c\u0438:<\/p>\n<ul>\n<li>\n<p><code>session<\/code> \u2014 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u043d\u0430 \u0432\u0441\u044e \u0441\u0435\u0441\u0441\u0438\u044e (\u043d\u0430\u0438\u043c\u0435\u043d\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u0435\u043d);<\/p>\n<\/li>\n<li>\n<p><code>transaction<\/code> \u2014 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 (\u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c);<\/p>\n<\/li>\n<li>\n<p><code>statement<\/code> \u2014 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 SQL-\u0437\u0430\u043f\u0440\u043e\u0441 (\u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c, \u043d\u043e \u043c\u043d\u043e\u0433\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439).<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0436\u0438\u043c <code>transaction<\/code>, \u043a\u0430\u043a \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439.<\/p>\n<p>2. \u0421 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u2014 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u044b \u043a Pg<br \/>\u0414\u0440\u0430\u0439\u0432\u0435\u0440\u044b PostgreSQL (\u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0434\u043b\u044f Go) \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 \u0434\u0432\u0430 \u044d\u0442\u0430\u043f\u0430: \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 prepared statement \u0438 \u0435\u0433\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438. \u042d\u0442\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u0442\u0430\u043a \u043a\u0430\u043a SQL-\u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442\u0434\u0435\u043b\u0451\u043d \u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 SQL-\u0438\u043d\u044a\u0435\u043a\u0446\u0438\u0438.<\/p>\n<p>\u041d\u043e \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 PgBouncer \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432\u0442\u043e\u0440\u043e\u0439 \u044d\u0442\u0430\u043f (\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430) \u043d\u0430 <strong>\u0434\u0440\u0443\u0433\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435<\/strong>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 <strong>\u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043e \u0440\u0430\u043d\u0435\u0435 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u043c statement<\/strong>, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443.<\/p>\n<p>\u042f \u0441\u043e\u0437\u0434\u0430\u043b <a href=\"https:\/\/github.com\/Sereger\/experiments\/tree\/master\/pgdrivers\" rel=\"noopener noreferrer nofollow\">\u043f\u0430\u043f\u043e\u0447\u043a\u0443 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"bash\">make start-env  # \u043f\u043e\u0434\u043d\u044f\u0442\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0432 docker compose go run main.go --mode lib\/pq --problem # \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u043c lib\/pq #out: \u2705 query executed successfully \u2705 query executed successfully \u274c query failed: pq: bind message supplies 17 parameters, but prepared statement \"\" requires 23 \u2705 query executed successfully \u2705 query executed successfully \u274c query failed: pq: bind message supplies 25 parameters, but prepared statement \"\" requires 27 \u274c query failed: pq: bind message supplies 22 parameters, but prepared statement \"\" requires 27 \u274c query failed: pq: bind message supplies 5 parameters, but prepared statement \"\" requires 27 \u274c query failed: pq: bind message supplies 6 parameters, but prepared statement \"\" requires 31 \u274c query failed: pq: bind message supplies 31 parameters, but prepared statement \"\" requires 6  go run main.go --mode jackc\/pgx --problem # \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u043c lib\/pq #out \u274c query failed: ERROR: prepared statement \"stmtcache_9380f4d2e1a2b142f7fe0abcac4e988bc2e5743c200e941d\" already exists (SQLSTATE 42P05) \u2705 query executed successfully \u274c query failed: ERROR: prepared statement \"stmtcache_962730cffc37e0a1a08d9043dbe66bb5fa1ad53cfbffb8c5\" does not exist (SQLSTATE 26000) \u2705 query executed successfully \u274c query failed: ERROR: prepared statement \"stmtcache_377d3096921449e3e4893ab85c5416441e35cbc0c0bd2959\" already exists (SQLSTATE 42P05) \u2705 query executed successfully \u2705 query executed successfully \u274c query failed: ERROR: prepared statement \"stmtcache_9380f4d2e1a2b142f7fe0abcac4e988bc2e5743c200e941d\" already exists (SQLSTATE 42P05) \u274c query failed: ERROR: prepared statement \"stmtcache_377d3096921449e3e4893ab85c5416441e35cbc0c0bd2959\" already exists (SQLSTATE 42P05) \u2705 query executed successfully  <\/code><\/pre>\n<hr\/>\n<h3>\u26a1 SimpleProtocol<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u043f\u043e\u0438\u0441\u043a\u0430\u0442\u044c, \u043a\u0430\u043a \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0434\u043b\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 jackc\/pgx, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0440\u043e\u0434\u0435 <a href=\"https:\/\/habr.com\/ru\/companies\/avito\/articles\/461935\/\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0439<\/a>, \u0433\u0434\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c <code>PreferSimpleProtocol<\/code>.<\/p>\n<p>\u0427\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435? \u041f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u043d\u0430\u0447\u0430\u0432 \u0441 <a href=\"https:\/\/www.postgresql.org\/docs\/current\/protocol-flow.html#PROTOCOL-FLOW-SIMPLE-QUERY\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 PostgreSQL<\/a> (<a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/current\/protocol-flow#PROTOCOL-FLOW-SIMPLE-QUERY\" rel=\"noopener noreferrer nofollow\">\u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c<\/a>) \u0438 \u043a\u043e\u0434\u0430 \u0432 <a href=\"https:\/\/github.com\/jackc\/pgx\/blob\/v5.7.5\/conn.go#L553\" rel=\"noopener noreferrer nofollow\">pgx<\/a> (\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0432 \u043a\u043e\u0434\u0435 \u043d\u0438\u0436\u0435 \u0443\u0436\u0435 \u043c\u043e\u0438):<\/p>\n<pre><code class=\"go\">func (c *Conn) execSimpleProtocol(ctx context.Context, sql string, arguments []any) (commandTag pgconn.CommandTag, err error) { if len(arguments) &gt; 0 {  \/\/ \u0432 sanitizeForSimpleQuery \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \/\/ \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 sql, err = c.sanitizeForSimpleQuery(sql, arguments...) if err != nil { return pgconn.CommandTag{}, err } }  \/\/ \u0417\u0434\u0435\u0441\u044c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435, \u043a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0442\u0443\u0442 \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f, \u0442.\u043a. \/\/ \u0432 sanitizeForSimpleQuery \u0432\u0441\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0443\u0436\u0435 \u0431\u044b\u043b\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u0437\u0430\u043f\u0440\u043e\u0441. mrr := c.pgConn.Exec(ctx, sql)  for mrr.NextResult() { commandTag, _ = mrr.ResultReader().Close() } err = mrr.Close() return commandTag, err } <\/code><\/pre>\n<p><code>PreferSimpleProtocol<\/code> \u043f\u0440\u043e\u0441\u0442\u043e \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043a\u0430\u043a \u0435\u0441\u043b\u0438 \u0431\u044b \u0432\u044b \u0435\u0451 \u043f\u0438\u0441\u0430\u043b\u0438 \u0432 psql. SQL-\u0438\u043d\u044a\u0435\u043a\u0446\u0438\u0438 \u0437\u0434\u0435\u0441\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b, \u0435\u0441\u043b\u0438 \u043d\u0435\u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043d\u0430\u0448\u0435\u043c \u0441\u0442\u0435\u043d\u0434\u0435:<\/p>\n<pre><code class=\"bash\">go run main.go --mode jackc\/pgx \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully <\/code><\/pre>\n<hr\/>\n<h3>\u26a1 BinaryParameters<\/h3>\n<p>\u0414\u0440\u0430\u0439\u0432\u0435\u0440 <a href=\"https:\/\/github.com\/lib\/pq\/blob\/v1.10.9\/conn.go#L939\" rel=\"noopener noreferrer nofollow\">lib\/pq<\/a> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>binary_parameters=yes<\/code> \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f (dsn). \u042d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u0447\u0435\u043c SimpleProtocol: \u0437\u0434\u0435\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/www.postgresql.org\/docs\/current\/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY\" rel=\"noopener noreferrer nofollow\">\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b<\/a> (<a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/current\/protocol-flow#PROTOCOL-FLOW-EXT-QUERY\" rel=\"noopener noreferrer nofollow\">\u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c<\/a>) \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 <a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/current\/protocol-flow#PROTOCOL-FLOW-PIPELINING\" rel=\"noopener noreferrer nofollow\">pipelining<\/a> (<a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/current\/protocol-flow#PROTOCOL-FLOW-PIPELINING\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f<\/a>)\u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0430\u043a\u0435\u0442\u0435, \u0447\u0442\u043e \u043c\u044b \u0438 \u0432\u0438\u0434\u0438\u043c <a href=\"https:\/\/github.com\/lib\/pq\/blob\/v1.10.9\/conn.go#L1750\" rel=\"noopener noreferrer nofollow\">\u0432 \u043a\u043e\u0434\u0435 lib\/pq<\/a> (\u0434\u0430\u043b\u0435\u0435 \u0432 \u043a\u043e\u0434\u0435 \u043c\u043e\u0438 + \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438).<\/p>\n<pre><code class=\"go\">func (cn *conn) sendBinaryModeQuery(query string, args []driver.Value) { if len(args) &gt;= 65536 { errorf(\"got %d parameters but PostgreSQL only supports 65535 parameters\", len(args)) }     \/\/ \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Parse, \/\/ \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f &lt;https:\/\/www.postgresql.org\/docs\/current\/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-PARSE&gt; b := cn.writeBuf('P')  b.byte(0) \/\/ unnamed statement &lt;- \u044d\u0442\u043e \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439, \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u043d\u0430 \u043d\u0435\u0433\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 b.string(query) b.int16(0)  \/\/ \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Bind &lt;https:\/\/www.postgresql.org\/docs\/current\/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-BIND&gt; b.next('B') b.int16(0) \/\/ unnamed portal and statement cn.sendBinaryParameters(b, args) b.bytes(colFmtDataAllText)  \/\/ \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Describe &lt;https:\/\/www.postgresql.org\/docs\/current\/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-DESCRIBE&gt; b.next('D')  b.byte('P') b.byte(0) \/\/ unnamed portal  \/\/ \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Execute &lt;https:\/\/www.postgresql.org\/docs\/current\/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-EXECUTE&gt; b.next('E') b.byte(0) b.int32(0)  \/\/ \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Sync &lt;https:\/\/www.postgresql.org\/docs\/current\/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-SYNC&gt; b.next('S') cn.send(b) } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, <code>binary_parameters<\/code> \u0432 lib\/pq \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u0430\u043d\u0434, \u043e\u0434\u043d\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c, \u0447\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u0443\u044e \u0440\u0430\u043d\u0435\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443. \u041f\u0440\u043e\u0441\u0442\u043e \u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u0441\u0442\u0435\u043d\u0434\u0443 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0451 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"bash\">go run main.go --mode lib\/pq \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully <\/code><\/pre>\n<hr\/>\n<h3>\u26a1 \u0418 \u0441\u043d\u043e\u0432\u0430 pgx<\/h3>\n<p>\u0425\u043e\u0442\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b (\u043f\u043e \u043c\u043e\u0435\u043c\u0443 \u0441\u0443\u0431\u044a\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e) \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f simple protocol,\u0443 jackc\/pgx \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0439 \u0430\u043d\u0430\u043b\u043e\u0433 <code>binary_parameters<\/code> , \u0430 \u0438\u043c\u0435\u043d\u043d\u043e <a href=\"https:\/\/github.com\/jackc\/pgx\/blob\/v5.7.5\/conn.go#L200-L201\" rel=\"noopener noreferrer nofollow\">ExecMode<\/a> (\u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0432 5\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 pgx, 2022 \u0433\u043e\u0434). \u041f\u043e-\u0441\u0443\u0442\u0438, \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 (<a href=\"https:\/\/github.com\/jackc\/pgx\/blob\/v5.7.5\/pgconn\/pgconn.go#L1143\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043a\u043e\u0434<\/a>):<\/p>\n<pre><code class=\"go\">func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) *ResultReader { result := pgConn.execExtendedPrefix(ctx, paramValues) if result.closed { return result }  \/\/ \u0437\u043d\u0430\u043a\u043e\u043c\u0430\u044f \u043d\u0430\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Parse pgConn.frontend.SendParse(&amp;pgproto3.Parse{Query: sql, ParameterOIDs: paramOIDs}) \/\/ \u043f\u043e\u0442\u043e\u043c Bind pgConn.frontend.SendBind(&amp;pgproto3.Bind{ParameterFormatCodes: paramFormats, Parameters: paramValues, ResultFormatCodes: resultFormats})   \/\/ Describe, Execute \u0438 Sync \u043f\u0440\u044f\u0447\u0443\u0442\u0441\u044f \u0443\u0436\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 pgConn.execExtendedSuffix(result)  return result }  func (pgConn *PgConn) execExtendedSuffix(result *ResultReader) { pgConn.frontend.SendDescribe(&amp;pgproto3.Describe{ObjectType: 'P'}) pgConn.frontend.SendExecute(&amp;pgproto3.Execute{}) pgConn.frontend.SendSync(&amp;pgproto3.Sync{})  err := pgConn.flushWithPotentialWriteReadDeadlock() if err != nil { pgConn.asyncClose() result.concludeCommand(CommandTag{}, err) pgConn.contextWatcher.Unwatch() result.closed = true pgConn.unlock() return }  result.readUntilRowDescription() } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c pgx \u043e\u0442\u0432\u043e\u0451\u0432\u044b\u0432\u0430\u0435\u0442 \u043e\u0447\u043a\u0438 \u0440\u0435\u043f\u0443\u0442\u0430\u0446\u0438\u0438, \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u043d\u044b\u0435 \u0441 SimpleProtocol. \u0410 \u0434\u0430\u043b\u0435\u0435 \u0434\u0430\u0436\u0435 \u0432\u044b\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u043f\u0435\u0440\u0435\u0434, \u043d\u043e \u043e\u0431\u043e \u0432\u0441\u0435\u043c \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443.<\/p>\n<p>\u0421\u043d\u043e\u0432\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0441\u0442\u0435\u043d\u0434\u0435:<\/p>\n<pre><code class=\"bash\">go run main.go --mode exec   \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully <\/code><\/pre>\n<hr\/>\n<h3>\ud83d\udeab &#171;\u0411\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f&#187; \u0441\u0442\u0430\u0442\u044c\u044f?<\/h3>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0432 \u0438\u0442\u043e\u0433\u0435 \u043e\u043d\u0430 \u00ab\u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f\u00bb? \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 <code>jackc\/pgx<\/code> \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0438 \u0432\u0441\u0451 \u0443 \u0432\u0430\u0441 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c. \u0412\u0441\u0451 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0432 2023 \u0433\u043e\u0434\u0443 \u0432 PgBouncer <a href=\"https:\/\/www.postgresql.org\/about\/news\/pgbouncer-1210-released-now-with-prepared-statements-2735\/\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 prepared statements<\/a>.<\/p>\n<p>\u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430 \u0441\u0442\u0435\u043d\u0434\u0435. \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438, \u044f \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u0434\u043b\u044f PgBouncer \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>MAX_PREPARED_STATEMENTS<\/code>, \u0440\u0430\u0432\u043d\u043e\u0435 0 (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u2014 200). \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0442\u0435\u043d\u0434 \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"bash\">make stop-env # \u0435\u0441\u043b\u0438 \u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0438 make start-env-with-ps # \u0437\u0430\u043f\u0443\u0441\u043a \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441 MAX_PREPARED_STATEMENTS=200 go run main.go --mode jackc\/pgx --problem # \u0440\u0430\u043d\u0435\u0435 \u0442\u0430\u043a\u043e\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043b \u043a \u043e\u0448\u0438\u0431\u043a\u0435 \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully <\/code><\/pre>\n<p>\u041b\u043e\u0433\u0438\u0447\u043d\u043e \u043e\u0436\u0438\u0434\u0430\u0442\u044c, \u0447\u0442\u043e \u0441 \u0432\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 prepared statements \u0432 PgBouncer \u0432\u0441\u0451 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0441 <code>lib\/pq<\/code> \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432&#8230; \u043d\u043e \u043d\u0435\u0442.<\/p>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e lib\/pq <strong>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <\/strong><a href=\"https:\/\/github.com\/lib\/pq\/blob\/v1.10.9\/conn.go#L1756\" rel=\"noopener noreferrer nofollow\"><strong>\u043d\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 prepared statements<\/strong><\/a>, \u0447\u0442\u043e \u043c\u0435\u0448\u0430\u0435\u0442 PgBouncer \u0438\u0445 \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"go\">func (cn *conn) sendBinaryModeQuery(query string, args []driver.Value) {   ...  b := cn.writeBuf('P')  b.byte(0) \/\/ unnamed statement b.string(query) b.int16(0)    ... } <\/code><\/pre>\n<p>\u0418\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f:<\/p>\n<pre><code class=\"bash\"># \u0440\u0430\u043d\u0435\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 `make start-env-with-ps` go run main.go --mode lib\/pq --problem \u274c query failed: pq: bind message supplies 32 parameters, but prepared statement \"\" requires 8 \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u274c query failed: pq: bind message supplies 17 parameters, but prepared statement \"\" requires 34 \u274c query failed: pq: bind message supplies 31 parameters, but prepared statement \"\" requires 27 \u2705 query executed successfully \u274c query failed: pq: bind message supplies 5 parameters, but prepared statement \"\" requires 17 \u2705 query executed successfully \u274c query failed: pq: bind message supplies 33 parameters, but prepared statement \"\" requires 32 <\/code><\/pre>\n<p>\u0422\u0430\u043a \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u0432\u044b \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0434\u0440\u0430\u0439\u0432\u0435\u0440 lib\/pq \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 PgBouncer, \u0442\u043e <code>binary_parameters=yes<\/code> \u0432\u0430\u043c \u0432\u0441\u0435 \u0435\u0449\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c.<\/p>\n<hr\/>\n<h3>\ud83d\udccc PS<\/h3>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u0441\u0442\u0430\u0442\u044c\u044f \u0432\u044b\u0448\u043b\u0430 \u043d\u0435 \u0442\u0430\u043a\u043e\u0439 \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439, \u043a\u0430\u043a \u0437\u0430\u044f\u0432\u043b\u0435\u043d\u043e \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435. \u0413\u043e\u0442\u043e\u0432\u044f \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0434\u043b\u044f \u0441\u0442\u0430\u0442\u044c\u0438, \u044f \u043d\u0435 \u0437\u043d\u0430\u043b \u043f\u0440\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, \u0441\u0434\u0435\u043b\u0430\u043d\u043d\u044b\u0435 \u0432 PgBouncer 3 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434, \u0442\u0430\u043a \u0447\u0442\u043e, \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0434\u043b\u044f \u043c\u0435\u043d\u044f, \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439. \u0422\u0430\u043a \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u0436\u0435  \u0431\u044b\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u2014 \u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043b\u0430\u0439\u043a, <s>\u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u043d\u0430 \u043a\u0430\u043d\u0430\u043b<\/s>. \u0421\u043f\u0430\u0441\u0438\u0431\u043e, \u0447\u0442\u043e \u0434\u043e\u0447\u0438\u0442\u0430\u043b\u0438 \u0434\u043e \u043a\u043e\u043d\u0446\u0430!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/913754\/\"> https:\/\/habr.com\/ru\/articles\/913754\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\">\n<div><figcaption>\u0430\u0440\u0442\u044b \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u042f \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435, \u043a\u0442\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0432 \u0441\u0442\u0435\u043a\u0435 Go + PgBouncer + PostgreSQL, \u0443\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u043d\u044f\u043b\u0438, \u043e \u0447\u0451\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u0442\u0430\u0442\u044c\u044f \u2014 \u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f prepared statements \u0438 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u0432\u0443\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u0432 \u0434\u043b\u044f PostgreSQL: <a href=\"https:\/\/github.com\/lib\/pq\" rel=\"noopener noreferrer nofollow\">lib\/pq<\/a> \u0438 <a href=\"https:\/\/github.com\/jackc\/pgx\" rel=\"noopener noreferrer nofollow\">jackc\/pgx<\/a>.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u2014 \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u0442.<\/p>\n<hr\/>\n<h3>\ud83e\udde8 \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b<\/h3>\n<p>1. \u041e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u2014 PgBouncer<br \/>PgBouncer \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u043f\u0443\u043b \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u043a PostgreSQL \u0438 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0438\u0445 \u043c\u0435\u0436\u0434\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432 \u0440\u0430\u0437\u044b \u0431\u043e\u043b\u044c\u0448\u0435. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 3 \u0440\u0435\u0436\u0438\u043c\u0430 \u0440\u0430\u0431\u043e\u0442\u044b PgBouncer \u0441 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\u043c\u0438:<\/p>\n<ul>\n<li>\n<p><code>session<\/code> \u2014 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c \u043d\u0430 \u0432\u0441\u044e \u0441\u0435\u0441\u0441\u0438\u044e (\u043d\u0430\u0438\u043c\u0435\u043d\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u0435\u043d);<\/p>\n<\/li>\n<li>\n<p><code>transaction<\/code> \u2014 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 (\u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c);<\/p>\n<\/li>\n<li>\n<p><code>statement<\/code> \u2014 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 SQL-\u0437\u0430\u043f\u0440\u043e\u0441 (\u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c, \u043d\u043e \u043c\u043d\u043e\u0433\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439).<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0436\u0438\u043c <code>transaction<\/code>, \u043a\u0430\u043a \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439.<\/p>\n<p>2. \u0421 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u2014 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u044b \u043a Pg<br \/>\u0414\u0440\u0430\u0439\u0432\u0435\u0440\u044b PostgreSQL (\u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0434\u043b\u044f Go) \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432 \u0434\u0432\u0430 \u044d\u0442\u0430\u043f\u0430: \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 prepared statement \u0438 \u0435\u0433\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438. \u042d\u0442\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u0442\u0430\u043a \u043a\u0430\u043a SQL-\u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442\u0434\u0435\u043b\u0451\u043d \u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 SQL-\u0438\u043d\u044a\u0435\u043a\u0446\u0438\u0438.<\/p>\n<p>\u041d\u043e \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 PgBouncer \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432\u0442\u043e\u0440\u043e\u0439 \u044d\u0442\u0430\u043f (\u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430) \u043d\u0430 <strong>\u0434\u0440\u0443\u0433\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435<\/strong>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 <strong>\u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043e \u0440\u0430\u043d\u0435\u0435 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u043c statement<\/strong>, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443.<\/p>\n<p>\u042f \u0441\u043e\u0437\u0434\u0430\u043b <a href=\"https:\/\/github.com\/Sereger\/experiments\/tree\/master\/pgdrivers\" rel=\"noopener noreferrer nofollow\">\u043f\u0430\u043f\u043e\u0447\u043a\u0443 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438<\/a>, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043a\u0430\u0447\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"bash\">make start-env  # \u043f\u043e\u0434\u043d\u044f\u0442\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0432 docker compose go run main.go --mode lib\/pq --problem # \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u043c lib\/pq #out: \u2705 query executed successfully \u2705 query executed successfully \u274c query failed: pq: bind message supplies 17 parameters, but prepared statement \"\" requires 23 \u2705 query executed successfully \u2705 query executed successfully \u274c query failed: pq: bind message supplies 25 parameters, but prepared statement \"\" requires 27 \u274c query failed: pq: bind message supplies 22 parameters, but prepared statement \"\" requires 27 \u274c query failed: pq: bind message supplies 5 parameters, but prepared statement \"\" requires 27 \u274c query failed: pq: bind message supplies 6 parameters, but prepared statement \"\" requires 31 \u274c query failed: pq: bind message supplies 31 parameters, but prepared statement \"\" requires 6  go run main.go --mode jackc\/pgx --problem # \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u043c lib\/pq #out \u274c query failed: ERROR: prepared statement \"stmtcache_9380f4d2e1a2b142f7fe0abcac4e988bc2e5743c200e941d\" already exists (SQLSTATE 42P05) \u2705 query executed successfully \u274c query failed: ERROR: prepared statement \"stmtcache_962730cffc37e0a1a08d9043dbe66bb5fa1ad53cfbffb8c5\" does not exist (SQLSTATE 26000) \u2705 query executed successfully \u274c query failed: ERROR: prepared statement \"stmtcache_377d3096921449e3e4893ab85c5416441e35cbc0c0bd2959\" already exists (SQLSTATE 42P05) \u2705 query executed successfully \u2705 query executed successfully \u274c query failed: ERROR: prepared statement \"stmtcache_9380f4d2e1a2b142f7fe0abcac4e988bc2e5743c200e941d\" already exists (SQLSTATE 42P05) \u274c query failed: ERROR: prepared statement \"stmtcache_377d3096921449e3e4893ab85c5416441e35cbc0c0bd2959\" already exists (SQLSTATE 42P05) \u2705 query executed successfully  <\/code><\/pre>\n<hr\/>\n<h3>\u26a1 SimpleProtocol<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u043f\u043e\u0438\u0441\u043a\u0430\u0442\u044c, \u043a\u0430\u043a \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u043e\u0431\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0434\u043b\u044f \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 jackc\/pgx, \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432\u0440\u043e\u0434\u0435 <a href=\"https:\/\/habr.com\/ru\/companies\/avito\/articles\/461935\/\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0439<\/a>, \u0433\u0434\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c <code>PreferSimpleProtocol<\/code>.<\/p>\n<p>\u0427\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435? \u041f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u043d\u044f\u0442\u044c, \u043d\u0430\u0447\u0430\u0432 \u0441 <a href=\"https:\/\/www.postgresql.org\/docs\/current\/protocol-flow.html#PROTOCOL-FLOW-SIMPLE-QUERY\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 PostgreSQL<\/a> (<a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/current\/protocol-flow#PROTOCOL-FLOW-SIMPLE-QUERY\" rel=\"noopener noreferrer nofollow\">\u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c<\/a>) \u0438 \u043a\u043e\u0434\u0430 \u0432 <a href=\"https:\/\/github.com\/jackc\/pgx\/blob\/v5.7.5\/conn.go#L553\" rel=\"noopener noreferrer nofollow\">pgx<\/a> (\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0432 \u043a\u043e\u0434\u0435 \u043d\u0438\u0436\u0435 \u0443\u0436\u0435 \u043c\u043e\u0438):<\/p>\n<pre><code class=\"go\">func (c *Conn) execSimpleProtocol(ctx context.Context, sql string, arguments []any) (commandTag pgconn.CommandTag, err error) { if len(arguments) &gt; 0 {  \/\/ \u0432 sanitizeForSimpleQuery \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u044d\u043a\u0440\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \/\/ \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 sql, err = c.sanitizeForSimpleQuery(sql, arguments...) if err != nil { return pgconn.CommandTag{}, err } }  \/\/ \u0417\u0434\u0435\u0441\u044c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435, \u043a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0442\u0443\u0442 \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f, \u0442.\u043a. \/\/ \u0432 sanitizeForSimpleQuery \u0432\u0441\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0443\u0436\u0435 \u0431\u044b\u043b\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u0437\u0430\u043f\u0440\u043e\u0441. mrr := c.pgConn.Exec(ctx, sql)  for mrr.NextResult() { commandTag, _ = mrr.ResultReader().Close() } err = mrr.Close() return commandTag, err } <\/code><\/pre>\n<p><code>PreferSimpleProtocol<\/code> \u043f\u0440\u043e\u0441\u0442\u043e \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043a\u0430\u043a \u0435\u0441\u043b\u0438 \u0431\u044b \u0432\u044b \u0435\u0451 \u043f\u0438\u0441\u0430\u043b\u0438 \u0432 psql. SQL-\u0438\u043d\u044a\u0435\u043a\u0446\u0438\u0438 \u0437\u0434\u0435\u0441\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b, \u0435\u0441\u043b\u0438 \u043d\u0435\u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043d\u0430\u0448\u0435\u043c \u0441\u0442\u0435\u043d\u0434\u0435:<\/p>\n<pre><code class=\"bash\">go run main.go --mode jackc\/pgx \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully <\/code><\/pre>\n<hr\/>\n<h3>\u26a1 BinaryParameters<\/h3>\n<p>\u0414\u0440\u0430\u0439\u0432\u0435\u0440 <a href=\"https:\/\/github.com\/lib\/pq\/blob\/v1.10.9\/conn.go#L939\" rel=\"noopener noreferrer nofollow\">lib\/pq<\/a> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>binary_parameters=yes<\/code> \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f (dsn). \u042d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u0447\u0435\u043c SimpleProtocol: \u0437\u0434\u0435\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/www.postgresql.org\/docs\/current\/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY\" rel=\"noopener noreferrer nofollow\">\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b<\/a> (<a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/current\/protocol-flow#PROTOCOL-FLOW-EXT-QUERY\" rel=\"noopener noreferrer nofollow\">\u043d\u0430 \u0440\u0443\u0441\u0441\u043a\u043e\u043c<\/a>) \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 <a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/current\/protocol-flow#PROTOCOL-FLOW-PIPELINING\" rel=\"noopener noreferrer nofollow\">pipelining<\/a> (<a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/current\/protocol-flow#PROTOCOL-FLOW-PIPELINING\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044f<\/a>)\u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u0430\u043d\u0434 \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0430\u043a\u0435\u0442\u0435, \u0447\u0442\u043e \u043c\u044b \u0438 \u0432\u0438\u0434\u0438\u043c <a href=\"https:\/\/github.com\/lib\/pq\/blob\/v1.10.9\/conn.go#L1750\" rel=\"noopener noreferrer nofollow\">\u0432 \u043a\u043e\u0434\u0435 lib\/pq<\/a> (\u0434\u0430\u043b\u0435\u0435 \u0432 \u043a\u043e\u0434\u0435 \u043c\u043e\u0438 + \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438).<\/p>\n<pre><code class=\"go\">func (cn *conn) sendBinaryModeQuery(query string, args []driver.Value) { if len(args) &gt;= 65536 { errorf(\"got %d parameters but PostgreSQL only supports 65535 parameters\", len(args)) }     \/\/ \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Parse, \/\/ \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f &lt;https:\/\/www.postgresql.org\/docs\/current\/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-PARSE&gt; b := cn.writeBuf('P')  b.byte(0) \/\/ unnamed statement &lt;- \u044d\u0442\u043e \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439, \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u043d\u0430 \u043d\u0435\u0433\u043e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 b.string(query) b.int16(0)  \/\/ \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Bind &lt;https:\/\/www.postgresql.org\/docs\/current\/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-BIND&gt; b.next('B') b.int16(0) \/\/ unnamed portal and statement cn.sendBinaryParameters(b, args) b.bytes(colFmtDataAllText)  \/\/ \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Describe &lt;https:\/\/www.postgresql.org\/docs\/current\/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-DESCRIBE&gt; b.next('D')  b.byte('P') b.byte(0) \/\/ unnamed portal  \/\/ \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Execute &lt;https:\/\/www.postgresql.org\/docs\/current\/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-EXECUTE&gt; b.next('E') b.byte(0) b.int32(0)  \/\/ \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Sync &lt;https:\/\/www.postgresql.org\/docs\/current\/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-SYNC&gt; b.next('S') cn.send(b) } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, <code>binary_parameters<\/code> \u0432 lib\/pq \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u0430\u043d\u0434, \u043e\u0434\u043d\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c, \u0447\u0442\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u0443\u044e \u0440\u0430\u043d\u0435\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443. \u041f\u0440\u043e\u0441\u0442\u043e \u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u0441\u0442\u0435\u043d\u0434\u0443 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0451 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"bash\">go run main.go --mode lib\/pq \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully <\/code><\/pre>\n<hr\/>\n<h3>\u26a1 \u0418 \u0441\u043d\u043e\u0432\u0430 pgx<\/h3>\n<p>\u0425\u043e\u0442\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b (\u043f\u043e \u043c\u043e\u0435\u043c\u0443 \u0441\u0443\u0431\u044a\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e) \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f simple protocol,\u0443 jackc\/pgx \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0439 \u0430\u043d\u0430\u043b\u043e\u0433 <code>binary_parameters<\/code> , \u0430 \u0438\u043c\u0435\u043d\u043d\u043e <a href=\"https:\/\/github.com\/jackc\/pgx\/blob\/v5.7.5\/conn.go#L200-L201\" rel=\"noopener noreferrer nofollow\">ExecMode<\/a> (\u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0432 5\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 pgx, 2022 \u0433\u043e\u0434). \u041f\u043e-\u0441\u0443\u0442\u0438, \u043e\u043d \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 (<a href=\"https:\/\/github.com\/jackc\/pgx\/blob\/v5.7.5\/pgconn\/pgconn.go#L1143\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043a\u043e\u0434<\/a>):<\/p>\n<pre><code class=\"go\">func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats []int16, resultFormats []int16) *ResultReader { result := pgConn.execExtendedPrefix(ctx, paramValues) if result.closed { return result }  \/\/ \u0437\u043d\u0430\u043a\u043e\u043c\u0430\u044f \u043d\u0430\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0430 Parse pgConn.frontend.SendParse(&amp;pgproto3.Parse{Query: sql, ParameterOIDs: paramOIDs}) \/\/ \u043f\u043e\u0442\u043e\u043c Bind pgConn.frontend.SendBind(&amp;pgproto3.Bind{ParameterFormatCodes: paramFormats, Parameters: paramValues, ResultFormatCodes: resultFormats})   \/\/ Describe, Execute \u0438 Sync \u043f\u0440\u044f\u0447\u0443\u0442\u0441\u044f \u0443\u0436\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 pgConn.execExtendedSuffix(result)  return result }  func (pgConn *PgConn) execExtendedSuffix(result *ResultReader) { pgConn.frontend.SendDescribe(&amp;pgproto3.Describe{ObjectType: 'P'}) pgConn.frontend.SendExecute(&amp;pgproto3.Execute{}) pgConn.frontend.SendSync(&amp;pgproto3.Sync{})  err := pgConn.flushWithPotentialWriteReadDeadlock() if err != nil { pgConn.asyncClose() result.concludeCommand(CommandTag{}, err) pgConn.contextWatcher.Unwatch() result.closed = true pgConn.unlock() return }  result.readUntilRowDescription() } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c pgx \u043e\u0442\u0432\u043e\u0451\u0432\u044b\u0432\u0430\u0435\u0442 \u043e\u0447\u043a\u0438 \u0440\u0435\u043f\u0443\u0442\u0430\u0446\u0438\u0438, \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u043d\u044b\u0435 \u0441 SimpleProtocol. \u0410 \u0434\u0430\u043b\u0435\u0435 \u0434\u0430\u0436\u0435 \u0432\u044b\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u043f\u0435\u0440\u0435\u0434, \u043d\u043e \u043e\u0431\u043e \u0432\u0441\u0435\u043c \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443.<\/p>\n<p>\u0421\u043d\u043e\u0432\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0441\u0442\u0435\u043d\u0434\u0435:<\/p>\n<pre><code class=\"bash\">go run main.go --mode exec   \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully <\/code><\/pre>\n<hr\/>\n<h3>\ud83d\udeab &#171;\u0411\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f&#187; \u0441\u0442\u0430\u0442\u044c\u044f?<\/h3>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0432 \u0438\u0442\u043e\u0433\u0435 \u043e\u043d\u0430 \u00ab\u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f\u00bb? \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 <code>jackc\/pgx<\/code> \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0438 \u0432\u0441\u0451 \u0443 \u0432\u0430\u0441 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c. \u0412\u0441\u0451 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0432 2023 \u0433\u043e\u0434\u0443 \u0432 PgBouncer <a href=\"https:\/\/www.postgresql.org\/about\/news\/pgbouncer-1210-released-now-with-prepared-statements-2735\/\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 prepared statements<\/a>.<\/p>\n<p>\u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043d\u0430 \u0441\u0442\u0435\u043d\u0434\u0435. \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438, \u044f \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u0434\u043b\u044f PgBouncer \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 <code>MAX_PREPARED_STATEMENTS<\/code>, \u0440\u0430\u0432\u043d\u043e\u0435 0 (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u2014 200). \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0441\u0442\u0435\u043d\u0434 \u0441\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"bash\">make stop-env # \u0435\u0441\u043b\u0438 \u0440\u0430\u043d\u0435\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0438 make start-env-with-ps # \u0437\u0430\u043f\u0443\u0441\u043a \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0441 MAX_PREPARED_STATEMENTS=200 go run main.go --mode jackc\/pgx --problem # \u0440\u0430\u043d\u0435\u0435 \u0442\u0430\u043a\u043e\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043b \u043a \u043e\u0448\u0438\u0431\u043a\u0435 \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully \u2705 query executed successfully <\/code><\/pre>\n<p>\u041b\u043e\u0433\u0438\u0447\u043d\u043e \u043e\u0436\u0438\u0434\u0430\u0442\u044c, \u0447\u0442\u043e \u0441 \u0432\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 prepared statements \u0432 PgBouncer \u0432\u0441\u0451 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0441 <code>lib\/pq<\/code> \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432&#8230; \u043d\u043e \u043d\u0435\u0442.<\/p>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e lib\/pq <strong>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 <\/strong><a href=\"https:\/\/github.com\/lib\/pq\/blob\/v1.10.9\/conn.go#L1756\" rel=\"noopener noreferrer nofollow\"><strong>\u043d\u0435\u0438\u043c\u0435\u043d\u043e<\/strong><\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-461350","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/461350","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=461350"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/461350\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=461350"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=461350"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=461350"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}