Thread
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
pgbench: Fix assertion failure with multiple \syncpipeline in pipeline mode.
- 5bc251b28839 17.8 landed
- 00e64e35c8bd 18.2 landed
- 4aa0ac05765e 19 (unreleased) landed
-
pgbench: Add --continue-on-error option.
- 0ab208fa505c 19 (unreleased) landed
-
Fix "inconsistent DLL linkage" warning on Windows MSVC
- a3ea5330fcf4 19 (unreleased) cited
-
pgbench: Fix error reporting in readCommandResponse().
- 7d7e81d1e6b8 13.23 landed
- cb21e1f92fb3 14.20 landed
- bdccb6302871 15.15 landed
- 36c4d30c8f24 16.11 landed
- a912118c6055 17.7 landed
- 29aabbc43269 18.1 landed
- 19d4f9ffc207 19 (unreleased) landed
-
pgbench: Fix assertion failure with retriable errors in pipeline mode.
- 704f517711b4 15.15 landed
- 8b2e290bde21 16.11 landed
- f39d9164b70a 17.7 landed
- c736808e03b7 18.1 landed
- 8bb174295e89 19 (unreleased) landed
-
Allow pgbench to retry in some cases.
- 4a39f87acd6e 15.0 cited
-
Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-05-10T13:45:31Z
Hi hackers, I would like to suggest adding a new option to pgbench, which enables the client to continue processing transactions even if some errors occur during a transaction. Currently, a client stops sending requests when its transaction is aborted due to reasons other than serialization failures or deadlocks. I think in some cases, especially when using custom scripts, the client should be able to rollback the failed transaction and start a new one. For example, my custom script (insert_to_unique_column.sql) follows: ``` CREATE TABLE IF NOT EXISTS test (col1 serial, col2 int unique); INSERT INTO test (col2) VALUES (random(0, 50000)); ``` Assume we need to continuously apply load to the server using 5 clients for a certain period of time. However, a client sometimes stops when its transaction in my custom script is aborted due to a check constraint violation. As a result, the load on the server is lower than expected, which is the problem I want to address. The proposed new option solves this problem. When --continue-client-on-abort is set to true, the client rolls back the failed transaction and starts a new one. This allows all 5 clients to continuously apply load to the server, even if some transactions fail. ``` % bin/pgbench -d postgres -f ../insert_to_unique_column.sql -T 10 --failures-detailed --continue-client-on-error transaction type: ../custom_script_insert.sql scaling factor: 1 query mode: simple number of clients: 1 number of threads: 1 maximum number of tries: 1 duration: 10 s number of transactions actually processed: 33552 number of failed transactions: 21901 (39.495%) number of serialization failures: 0 (0.000%) number of deadlock failures: 0 (0.000%) number of other failures: 21901 (39.495%) latency average = 0.180 ms (including failures) initial connection time = 2.857 ms tps = 3356.092385 (without initial connection time) ``` I have attached the patch. I would appreciate your feedback. Best regards, Rintaro Ikeda NTT DATA Corporation Japan
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Stepan Neretin <slpmcf@gmail.com> — 2025-05-10T15:02:06Z
On Sat, May 10, 2025 at 8:45 PM ikedarintarof <ikedarintarof@oss.nttdata.com> wrote: > Hi hackers, > > I would like to suggest adding a new option to pgbench, which enables > the client to continue processing transactions even if some errors occur > during a transaction. > Currently, a client stops sending requests when its transaction is > aborted due to reasons other than serialization failures or deadlocks. I > think in some cases, especially when using custom scripts, the client > should be able to rollback the failed transaction and start a new one. > > For example, my custom script (insert_to_unique_column.sql) follows: > ``` > CREATE TABLE IF NOT EXISTS test (col1 serial, col2 int unique); > INSERT INTO test (col2) VALUES (random(0, 50000)); > ``` > Assume we need to continuously apply load to the server using 5 clients > for a certain period of time. However, a client sometimes stops when its > transaction in my custom script is aborted due to a check constraint > violation. As a result, the load on the server is lower than expected, > which is the problem I want to address. > > The proposed new option solves this problem. When > --continue-client-on-abort is set to true, the client rolls back the > failed transaction and starts a new one. This allows all 5 clients to > continuously apply load to the server, even if some transactions fail. > > ``` > % bin/pgbench -d postgres -f ../insert_to_unique_column.sql -T 10 > --failures-detailed --continue-client-on-error > transaction type: ../custom_script_insert.sql > scaling factor: 1 > query mode: simple > number of clients: 1 > number of threads: 1 > maximum number of tries: 1 > duration: 10 s > number of transactions actually processed: 33552 > number of failed transactions: 21901 (39.495%) > number of serialization failures: 0 (0.000%) > number of deadlock failures: 0 (0.000%) > number of other failures: 21901 (39.495%) > latency average = 0.180 ms (including failures) > initial connection time = 2.857 ms > tps = 3356.092385 (without initial connection time) > ``` > > I have attached the patch. I would appreciate your feedback. > > Best regards, > > Rintaro Ikeda > NTT DATA Corporation Japan Hi Rintaro, Thanks for the patch and explanation. I understand your goal is to ensure that pgbench clients continue running even when some transactions fail due to application-level errors (e.g., constraint violations), especially when running custom scripts. However, I wonder if the intended behavior can't already be achieved using standard SQL constructs — specifically ON CONFLICT or careful transaction structure. For example, your sample script: CREATE TABLE IF NOT EXISTS test (col1 serial, col2 int unique); INSERT INTO test (col2) VALUES (random(0, 50000)); can be rewritten as: \setrandom val 0 50000 INSERT INTO test (col2) VALUES (:val) ON CONFLICT DO NOTHING; This avoids transaction aborts entirely in the presence of uniqueness violations and ensures the client continues to issue load without interruption. In many real-world benchmarking scenarios, this is the preferred and simplest approach. So from that angle, could you elaborate on specific cases where this SQL-level workaround wouldn't be sufficient? Are there error types you intend to handle that cannot be gracefully avoided or recovered from using SQL constructs like ON CONFLICT, or SAVEPOINT/ROLLBACK TO? Best regards, Stepan Neretin
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Matthias van de Meent <boekewurm+postgres@gmail.com> — 2025-05-11T12:06:49Z
> On Sat, May 10, 2025 at 8:45 PM ikedarintarof <ikedarintarof@oss.nttdata.com> wrote: >> >> Hi hackers, >> >> I would like to suggest adding a new option to pgbench, which enables >> the client to continue processing transactions even if some errors occur >> during a transaction. >> Currently, a client stops sending requests when its transaction is >> aborted due to reasons other than serialization failures or deadlocks. I >> think in some cases, especially when using custom scripts, the client >> should be able to rollback the failed transaction and start a new one. >> >> For example, my custom script (insert_to_unique_column.sql) follows: >> ``` >> CREATE TABLE IF NOT EXISTS test (col1 serial, col2 int unique); >> INSERT INTO test (col2) VALUES (random(0, 50000)); >> ``` >> Assume we need to continuously apply load to the server using 5 clients >> for a certain period of time. However, a client sometimes stops when its >> transaction in my custom script is aborted due to a check constraint >> violation. As a result, the load on the server is lower than expected, >> which is the problem I want to address. >> >> The proposed new option solves this problem. When >> --continue-client-on-abort is set to true, the client rolls back the >> failed transaction and starts a new one. This allows all 5 clients to >> continuously apply load to the server, even if some transactions fail. +1. I've had similar cases before too, where I'd wanted pgbench to continue creating load on the server even if a transaction failed server-side for any reason. Sometimes, I'd even want that type of load. On Sat, 10 May 2025 at 17:02, Stepan Neretin <slpmcf@gmail.com> wrote: > INSERT INTO test (col2) VALUES (random(0, 50000)); > > can be rewritten as: > > \setrandom val 0 50000 > INSERT INTO test (col2) VALUES (:val) ON CONFLICT DO NOTHING; That won't test the same execution paths, so an option to explicitly rollback or ignore failed transactions (rather than stopping the benchmark) would be a nice feature. With e.g. ON CONFLICT DO NOTHING you'll have much higher workload if there are many conflicting entries, as that triggers and catches per-row errors, rather than per-statement. E.g. INSERT INTO ... SELECT ...multiple rows could conflict on multiple rows, but will fail on the first conflict. DO NOTHING would cause full execution of the SELECT statement, which has an inherently different performance profile. > This avoids transaction aborts entirely in the presence of uniqueness violations and ensures the client continues to issue load without interruption. In many real-world benchmarking scenarios, this is the preferred and simplest approach. > > So from that angle, could you elaborate on specific cases where this SQL-level workaround wouldn't be sufficient? Are there error types you intend to handle that cannot be gracefully avoided or recovered from using SQL constructs like ON CONFLICT, or SAVEPOINT/ROLLBACK TO? The issue isn't necessarily whether you can construct SQL scripts that don't raise such errors (indeed, it's possible to do so for nearly any command; you can run pl/pgsql procedures or DO blocks which catch and ignore errors), but rather whether we can make pgbench function in a way that can keep load on the server even when it notices an error. Kind regards, Matthias van de Meent Neon (https://neon.tech)
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Stepan Neretin <slpmcf@gmail.com> — 2025-05-11T17:51:13Z
On Sun, May 11, 2025 at 7:07 PM Matthias van de Meent < boekewurm+postgres@gmail.com> wrote: > > On Sat, May 10, 2025 at 8:45 PM ikedarintarof < > ikedarintarof@oss.nttdata.com> wrote: > >> > >> Hi hackers, > >> > >> I would like to suggest adding a new option to pgbench, which enables > >> the client to continue processing transactions even if some errors occur > >> during a transaction. > >> Currently, a client stops sending requests when its transaction is > >> aborted due to reasons other than serialization failures or deadlocks. I > >> think in some cases, especially when using custom scripts, the client > >> should be able to rollback the failed transaction and start a new one. > >> > >> For example, my custom script (insert_to_unique_column.sql) follows: > >> ``` > >> CREATE TABLE IF NOT EXISTS test (col1 serial, col2 int unique); > >> INSERT INTO test (col2) VALUES (random(0, 50000)); > >> ``` > >> Assume we need to continuously apply load to the server using 5 clients > >> for a certain period of time. However, a client sometimes stops when its > >> transaction in my custom script is aborted due to a check constraint > >> violation. As a result, the load on the server is lower than expected, > >> which is the problem I want to address. > >> > >> The proposed new option solves this problem. When > >> --continue-client-on-abort is set to true, the client rolls back the > >> failed transaction and starts a new one. This allows all 5 clients to > >> continuously apply load to the server, even if some transactions fail. > > +1. I've had similar cases before too, where I'd wanted pgbench to > continue creating load on the server even if a transaction failed > server-side for any reason. Sometimes, I'd even want that type of > load. > > On Sat, 10 May 2025 at 17:02, Stepan Neretin <slpmcf@gmail.com> wrote: > > INSERT INTO test (col2) VALUES (random(0, 50000)); > > > > can be rewritten as: > > > > \setrandom val 0 50000 > > INSERT INTO test (col2) VALUES (:val) ON CONFLICT DO NOTHING; > > That won't test the same execution paths, so an option to explicitly > rollback or ignore failed transactions (rather than stopping the > benchmark) would be a nice feature. > With e.g. ON CONFLICT DO NOTHING you'll have much higher workload if > there are many conflicting entries, as that triggers and catches > per-row errors, rather than per-statement. E.g. INSERT INTO ... SELECT > ...multiple rows could conflict on multiple rows, but will fail on the > first conflict. DO NOTHING would cause full execution of the SELECT > statement, which has an inherently different performance profile. > > > This avoids transaction aborts entirely in the presence of uniqueness > violations and ensures the client continues to issue load without > interruption. In many real-world benchmarking scenarios, this is the > preferred and simplest approach. > > > > So from that angle, could you elaborate on specific cases where this > SQL-level workaround wouldn't be sufficient? Are there error types you > intend to handle that cannot be gracefully avoided or recovered from using > SQL constructs like ON CONFLICT, or SAVEPOINT/ROLLBACK TO? > > The issue isn't necessarily whether you can construct SQL scripts that > don't raise such errors (indeed, it's possible to do so for nearly any > command; you can run pl/pgsql procedures or DO blocks which catch and > ignore errors), but rather whether we can make pgbench function in a > way that can keep load on the server even when it notices an error. > > Kind regards, > > Matthias van de Meent > Neon (https://neon.tech) > Hi Matthias, Thanks for your detailed explanation — it really helped clarify the usefulness of the patch. I agree that the feature is indeed valuable, and it's great to see it being pushed forward. Regarding the patch code, I noticed that there are duplicate case entries in the command-line option handling (specifically for case 18 or case ESTATUS_OTHER_SQL_ERROR, the continue-client-on-error option). These duplicated cases can be merged to simplify the logic and reduce redundancy. Best regards, Stepan Neretin
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
rintaro.ikeda@nttdata.com — 2025-05-13T03:49:53Z
Hi Stepan and Matthias, Thank you both for your replies. I agree with Matthias's detailed explanation regarding the purpose of the patch. > Regarding the patch code, I noticed that there are duplicate case > entries in the command-line option handling (specifically for case 18 > or case ESTATUS_OTHER_SQL_ERROR, the continue-client-on-error option). > These duplicated cases can be merged to simplify the logic and reduce > redundancy. I also appreciate you for pointing out my mistakes in the previous version of the patch. I fixed the duplicated lines. I’ve attached the updated patch. Best regards, Rintaro Ikeda >> On Sat, May 10, 2025 at 8:45 PM ikedarintarof > <ikedarintarof@oss.nttdata.com> wrote: >>> >>> Hi hackers, >>> >>> I would like to suggest adding a new option to pgbench, which > enables >>> the client to continue processing transactions even if some errors > occur >>> during a transaction. >>> Currently, a client stops sending requests when its transaction is >>> aborted due to reasons other than serialization failures or > deadlocks. I >>> think in some cases, especially when using custom scripts, the > client >>> should be able to rollback the failed transaction and start a new > one. >>> >>> For example, my custom script (insert_to_unique_column.sql) > follows: >>> ``` >>> CREATE TABLE IF NOT EXISTS test (col1 serial, col2 int unique); >>> INSERT INTO test (col2) VALUES (random(0, 50000)); >>> ``` >>> Assume we need to continuously apply load to the server using 5 > clients >>> for a certain period of time. However, a client sometimes stops > when its >>> transaction in my custom script is aborted due to a check > constraint >>> violation. As a result, the load on the server is lower than > expected, >>> which is the problem I want to address. >>> >>> The proposed new option solves this problem. When >>> --continue-client-on-abort is set to true, the client rolls back > the >>> failed transaction and starts a new one. This allows all 5 clients > to >>> continuously apply load to the server, even if some transactions > fail. > > +1. I've had similar cases before too, where I'd wanted pgbench to > continue creating load on the server even if a transaction failed > server-side for any reason. Sometimes, I'd even want that type of > load. > > On Sat, 10 May 2025 at 17:02, Stepan Neretin <slpmcf@gmail.com> wrote: >> INSERT INTO test (col2) VALUES (random(0, 50000)); >> >> can be rewritten as: >> >> \setrandom val 0 50000 >> INSERT INTO test (col2) VALUES (:val) ON CONFLICT DO NOTHING; > > That won't test the same execution paths, so an option to explicitly > rollback or ignore failed transactions (rather than stopping the > benchmark) would be a nice feature. > With e.g. ON CONFLICT DO NOTHING you'll have much higher workload if > there are many conflicting entries, as that triggers and catches > per-row errors, rather than per-statement. E.g. INSERT INTO ... SELECT > ...multiple rows could conflict on multiple rows, but will fail on the > first conflict. DO NOTHING would cause full execution of the SELECT > statement, which has an inherently different performance profile. > >> This avoids transaction aborts entirely in the presence of > uniqueness violations and ensures the client continues to issue load > without interruption. In many real-world benchmarking scenarios, this > is the preferred and simplest approach. >> >> So from that angle, could you elaborate on specific cases where this > SQL-level workaround wouldn't be sufficient? Are there error types you > intend to handle that cannot be gracefully avoided or recovered from > using SQL constructs like ON CONFLICT, or SAVEPOINT/ROLLBACK TO? > > The issue isn't necessarily whether you can construct SQL scripts that > don't raise such errors (indeed, it's possible to do so for nearly any > command; you can run pl/pgsql procedures or DO blocks which catch and > ignore errors), but rather whether we can make pgbench function in a > way that can keep load on the server even when it notices an error. > > Kind regards, > > Matthias van de Meent > Neon (https://urldefense.com/v3/__https://neon.tech__;!!GCTRfqYYOYGmgK_z!92h3wOeDsDRQ1abfcL8-tRZqrAQ0w5RXwLNofOa_guIgDHdYknrizKqUGkvSn1_OU-xzMRv2halvtpUX7BFE8e3aPO_1-CZDhQ$ ) Hi Matthias, Thanks for your detailed explanation — it really helped clarify the usefulness of the patch. I agree that the feature is indeed valuable, and it's great to see it being pushed forward. Regarding the patch code, I noticed that there are duplicate case entries in the command-line option handling (specifically for case 18 or case ESTATUS_OTHER_SQL_ERROR, the continue-client-on-error option). These duplicated cases can be merged to simplify the logic and reduce redundancy. Best regards, Stepan Neretin
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Dilip Kumar <dilipbalaut@gmail.com> — 2025-05-13T05:56:52Z
On Tue, May 13, 2025 at 9:20 AM <Rintaro.Ikeda@nttdata.com> wrote: > I also appreciate you for pointing out my mistakes in the previous version of the patch. I fixed the duplicated lines. I’ve attached the updated patch. > This is a useful feature, so +1 from my side. Here are some initial comments on the patch while having a quick look. 1. You need to update the stats for this new counter in the "accumStats()" function. 2. IMHO, " continue-on-error " is more user-friendly than "continue-client-on-error". 3. There are a lot of whitespace errors, so those can be fixed. You can just try to apply using git am, and it will report those whitespace warnings. And for fixing, you can just use "--whitespace=fix" along with git am. -- Regards, Dilip Kumar EnterpriseDB: http://www.enterprisedb.com
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Srinath Reddy Sadipiralla <srinath2133@gmail.com> — 2025-05-14T09:08:53Z
Hi, On Tue, May 13, 2025 at 11:27 AM Dilip Kumar <dilipbalaut@gmail.com> wrote: > On Tue, May 13, 2025 at 9:20 AM <Rintaro.Ikeda@nttdata.com> wrote: > > I also appreciate you for pointing out my mistakes in the previous > version of the patch. I fixed the duplicated lines. I’ve attached the > updated patch. > > > This is a useful feature, so +1 from my side. Here are some initial > comments on the patch while having a quick look. > > 1. You need to update the stats for this new counter in the > "accumStats()" function. > > 2. IMHO, " continue-on-error " is more user-friendly than > "continue-client-on-error". > > 3. There are a lot of whitespace errors, so those can be fixed. You > can just try to apply using git am, and it will report those > whitespace warnings. And for fixing, you can just use > "--whitespace=fix" along with git am. > Hi, +1 for the idea. I’ve reviewed and tested the patch. Aside from Dilip’s feedback and the missing usage information for this option, the patch LGTM. Here's the diff for the missing usage information for this option and as Dilip mentioned updating the new counter in the "accumStats()" function. diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index baaf1379be2..20d456bc4b9 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -959,6 +959,8 @@ usage(void) " --log-prefix=PREFIX prefix for transaction time log file\n" " (default: \"pgbench_log\")\n" " --max-tries=NUM max number of tries to run transaction (default: 1)\n" + " --continue-client-on-error\n" + " Continue and retry transactions that failed due to errors other than serialization or deadlocks.\n" " --progress-timestamp use Unix epoch timestamps for progress\n" " --random-seed=SEED set random seed (\"time\", \"rand\", integer)\n" " --sampling-rate=NUM fraction of transactions to log (e.g., 0.01 for 1%%)\n" @@ -1522,6 +1524,9 @@ accumStats(StatsData *stats, bool skipped, double lat, double lag, case ESTATUS_DEADLOCK_ERROR: stats->deadlock_failures++; break; + case ESTATUS_OTHER_SQL_ERROR: + stats->other_sql_failures++; + break; default: /* internal error which should never occur */ pg_fatal("unexpected error status: %d", estatus); -- Thanks, Srinath Reddy Sadipiralla EDB: https://www.enterprisedb.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-06-02T14:21:28Z
Hi, hakers. > On Tue, May 13, 2025 at 11:27 AM Dilip Kumar <dilipbalaut@gmail.com <mailto:dilipbalaut@gmail.com>> wrote: >> >> 1. You need to update the stats for this new counter in the >> "accumStats()" function. >> >> 2. IMHO, " continue-on-error " is more user-friendly than >> "continue-client-on-error". >> >> 3. There are a lot of whitespace errors, so those can be fixed. You >> can just try to apply using git am, and it will report those >> whitespace warnings. And for fixing, you can just use >> "--whitespace=fix" along with git am. > On May 14, 2025, at 18:08, Srinath Reddy Sadipiralla <srinath2133@gmail.com> wrote: > > Here's the diff for the missing usage information for this option and as Dilip mentioned updating the new counter in the "accumStats()" function. Thank you very much for the helpful comments, and apologies for my delayed reply. I've updated the patch based on your suggestions: - Modified name of the option. - Added the missing explanation. - Updated the new counter in the `accumStats()` function as pointed out. - Fixed the whitespace issues. Additionally, I've included documentation for the new option. I'm submitting this updated patch to the current CommitFest. Best Regards, Rintaro Ikeda  > On May 14, 2025, at 18:08, Srinath Reddy Sadipiralla <srinath2133@gmail.com> wrote: > > > Hi, > > On Tue, May 13, 2025 at 11:27 AM Dilip Kumar <dilipbalaut@gmail.com <mailto:dilipbalaut@gmail.com>> wrote: >> On Tue, May 13, 2025 at 9:20 AM <Rintaro.Ikeda@nttdata.com <mailto:Rintaro.Ikeda@nttdata.com>> wrote: >> > I also appreciate you for pointing out my mistakes in the previous version of the patch. I fixed the duplicated lines. I’ve attached the updated patch. >> > >> This is a useful feature, so +1 from my side. Here are some initial >> comments on the patch while having a quick look. >> >> 1. You need to update the stats for this new counter in the >> "accumStats()" function. >> >> 2. IMHO, " continue-on-error " is more user-friendly than >> "continue-client-on-error". >> >> 3. There are a lot of whitespace errors, so those can be fixed. You >> can just try to apply using git am, and it will report those >> whitespace warnings. And for fixing, you can just use >> "--whitespace=fix" along with git am. > > > Hi, +1 for the idea. I’ve reviewed and tested the patch. Aside from Dilip’s feedback and the missing usage information for this option, the patch LGTM. > > Here's the diff for the missing usage information for this option and as Dilip mentioned updating the new counter in the "accumStats()" function. > > diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c > index baaf1379be2..20d456bc4b9 100644 > --- a/src/bin/pgbench/pgbench.c > +++ b/src/bin/pgbench/pgbench.c > @@ -959,6 +959,8 @@ usage(void) > " --log-prefix=PREFIX prefix for transaction time log file\n" > " (default: \"pgbench_log\")\n" > " --max-tries=NUM max number of tries to run transaction (default: 1)\n" > + " --continue-client-on-error\n" > + " Continue and retry transactions that failed due to errors other than serialization or deadlocks.\n" > " --progress-timestamp use Unix epoch timestamps for progress\n" > " --random-seed=SEED set random seed (\"time\", \"rand\", integer)\n" > " --sampling-rate=NUM fraction of transactions to log (e.g., 0.01 for 1%%)\n" > @@ -1522,6 +1524,9 @@ accumStats(StatsData *stats, bool skipped, double lat, double lag, > case ESTATUS_DEADLOCK_ERROR: > stats->deadlock_failures++; > break; > + case ESTATUS_OTHER_SQL_ERROR: > + stats->other_sql_failures++; > + break; > default: > /* internal error which should never occur */ > pg_fatal("unexpected error status: %d", estatus); > -- > Thanks, > Srinath Reddy Sadipiralla > EDB: https://www.enterprisedb.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-06-02T14:36:16Z
Hi, Hackers. I've attached the patch that I failed to include in my previous email. (I'm still a bit confused about how to attach files using the standard Mail client on macOS.) Best Regards, Rintaro Ikeda
-
RE: Suggestion to add --continue-client-on-abort option to pgbench
Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-06-04T12:57:14Z
Dear Ikeda-san, Thanks for starting the new thread! I have never known the issue before I heard at PGConf.dev. Few comments: 1. This parameter seems a type of benchmark option. So should we set benchmarking_option_set as well? 2. Not sure, but exit-on-abort seems a similar option. What if both are specified? Is it allowed? 3. Can you consider a test case for the new parameter? Best regards, Hayato Kuroda FUJITSU LIMITED
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-06-08T14:59:49Z
Dear Kuroda-san, hackers, On 2025/06/04 21:57, Hayato Kuroda (Fujitsu) wrote: > Dear Ikeda-san, > > Thanks for starting the new thread! I have never known the issue before I heard at > PGConf.dev. > > Few comments: > > 1. > This parameter seems a type of benchmark option. So should we set > benchmarking_option_set as well? > > 2. > Not sure, but exit-on-abort seems a similar option. What if both are specified? > Is it allowed? > > 3. > Can you consider a test case for the new parameter? > > Best regards, > Hayato Kuroda > FUJITSU LIMITED > > Thank you for your valuable comment! 1. I should've also set benchmarking_option_set. I've modified it accordingly. 2. The exit-on-abort option and continue-on-error option are mutually exclusive. Therefore, I've updated the patch to throw a FATAL error when two options are set simultaneously. Corresponding explanation was also added. (I'm wondering the name of parameter should be continue-on-abort so that users understand the two option are mutually exclusive.) 3. I've added the test. Additionally, I modified the patch so that st->state does not transition to CSTATE_RETRY when a transaction fails and continue-on-error option is enabled. In the previous patch, we retry the failed transaction up to max-try times, which is unnecessary for our purpose: clients does not exit when its transactions fail. I've attached the updated patch. v3-0001-Add-continue-on-error-option-to-pgbench.patch is identical to v4-0001-Add-continue-on-error-option-to-pgbench.patch. The v4-0002 patch is the diff from the previous patch. Best regards, Rintaro Ikeda
-
RE: Suggestion to add --continue-client-on-abort option to pgbench
Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-06-09T09:34:03Z
Dear Ikeda-san, Thanks for updating the patch! > 1. I should've also set benchmarking_option_set. I've modified it accordingly. Confirmed it has been fixed. Thanks. > 2. The exit-on-abort option and continue-on-error option are mutually exclusive. > Therefore, I've updated the patch to throw a FATAL error when two options are > set simultaneously. Corresponding explanation was also added. > (I'm wondering the name of parameter should be continue-on-abort so that users > understand the two option are mutually exclusive.) Make sense, +1. Here are new comments. 01. build failure According to the cfbot [1], the documentation cannot be built. IIUC </para> seemed to be missed here: ``` + <para> + Note that this option can not be used together with + <option>--exit-on-abort</option>. + </listitem> + </varlistentry> ``` 02. patch separation How about separating the patch series like: 0001 - contains option handling and retry part, and documentation 0002 - contains accumulation/reporting part 0003 - contains tests. I hope above style is more helpful for reviewers. 03. documentation ``` + Note that this option can not be used together with + <option>--exit-on-abort</option>. ``` I feel we should add the similar description in `exit-on-abort` part. 04. documentation ``` + Client rolls back the failed transaction and starts a new one when its + transaction fails due to the reason other than the deadlock and + serialization failure. This allows all clients specified with -c option + to continuously apply load to the server, even if some transactions fail. ``` I feel the description contains bit redundant part and misses the default behavior. How about: ``` <para> Clients survive when their transactions are aborted, and they continue their run. Without the option, clients exit when transactions they run are aborted. </para> <para> Note that serialization failures or deadlock failures do not abort the client, so they are not affected by this option. See <xref linkend="failures-and-retries"/> for more information. </para> ``` 05. StatsData ``` + * When continue-on-error option is specified, + * failed (the number of failed transactions) = + * 'other_sql_failures' (they got a error when continue-on-error option + * was specified). ``` Let me confirm one point; can serialization_failures and deadlock_failures be counted when continue-on-error is true? If so, the comment seems not correct for me. The formula can be 'serialization_failures' + 'deadlock_failures' + 'deadlock_failures' in the case. 06. StatsData Another point; can other_sql_failures be counted when the continue-on-error is NOT specified? I feel it should be... 06. usage() Added line is too long. According to program_help_ok(), the output by help should be less than 80. 07. Please run pgindent/pgperltidy, I got some diffs. [1]: https://cirrus-ci.com/task/5210061275922432 Best regards, Hayato Kuroda FUJITSU LIMITED -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-06-13T15:24:53Z
On Mon, 9 Jun 2025 09:34:03 +0000 "Hayato Kuroda (Fujitsu)" <kuroda.hayato@fujitsu.com> wrote: > > 2. The exit-on-abort option and continue-on-error option are mutually exclusive. > > Therefore, I've updated the patch to throw a FATAL error when two options are > > set simultaneously. Corresponding explanation was also added. I don't think that's right since "abort" and "error" are different concept in pgbench. (Here, "abort" refers to the termination of a client, not a transaction abort.) The --exit-on-abort option forces to exit pgbench immediately when any client is aborted due to some error. When the --continue-on-error option is not set, SQL errors other than deadlock or serialization error cause a client to be aborted. On the other hand, when the option is set, clients are not aborted due to any SQL errors; instead they continue to run after them. However, clients can still be aborted for other reasons, such as connection failures or meta-command errors (e.g., \set x 1/0). In these cases, the --exit-on-abort option remains useful even when --continue-on-error is enabled. > > (I'm wondering the name of parameter should be continue-on-abort so that users > > understand the two option are mutually exclusive.) For the same reason as above, I believe --continue-on-error is a more accurate description of the option's behavior. > 02. patch separation > How about separating the patch series like: > > 0001 - contains option handling and retry part, and documentation > 0002 - contains accumulation/reporting part > 0003 - contains tests. > > I hope above style is more helpful for reviewers. I'm not sure whether it's necessary to split the patch, as the change doesn't seem very complex. However, the current separation appears inconsistent. For example, patch 0001 modifies canRetryError(), but patch 0002 reverts that change, and so on. > > 04. documentation > ``` > + Client rolls back the failed transaction and starts a new one when its > + transaction fails due to the reason other than the deadlock and > + serialization failure. This allows all clients specified with -c option > + to continuously apply load to the server, even if some transactions fail. > ``` > > I feel the description contains bit redundant part and misses the default behavior. > How about: > ``` > <para> > Clients survive when their transactions are aborted, and they continue > their run. Without the option, clients exit when transactions they run > are aborted. > </para> > <para> > Note that serialization failures or deadlock failures do not abort the > client, so they are not affected by this option. > See <xref linkend="failures-and-retries"/> for more information. > </para> > ``` I think we can make it clearer as follows: Allows clients to continue their run even if an SQL statement fails due to errors other than serialization or deadlock. Without this option, the client is aborted after such errors. Note that serialization and deadlock failures never cause the client to be aborted, so they are not affected by this option. See <xref linkend="failures-and-retries"/> for more information. That said, a review by a native English speaker would still be appreciated. Also, we would need to update several parts of the documentation. For example, the "Failures and Serialization/Deadlock Retries" section should be revised to describe the behavior change. In addition, we should update the explanations of output result examples and logging, the description of the --failures-detailed option, and so on. If transactions are not retried after SQL errors other than serialization or deadlock, this should also be explicitly documented. > 05. StatsData > ``` > + * When continue-on-error option is specified, > + * failed (the number of failed transactions) = > + * 'other_sql_failures' (they got a error when continue-on-error option > + * was specified). > ``` > > Let me confirm one point; can serialization_failures and deadlock_failures be > counted when continue-on-error is true? If so, the comment seems not correct for me. > The formula can be 'serialization_failures' + 'deadlock_failures' + 'deadlock_failures' > in the case. +1 > 06. StatsData > Another point; can other_sql_failures be counted when the continue-on-error is NOT > specified? I feel it should be... We could do that. However, if an SQL error other than a serialization or deadlock error occurs when --continue-on-error is not set, pgbench will be aborted midway and the printed results will be incomplete. Therefore, this might not make much sense. > 06. usage() > Added line is too long. According to program_help_ok(), the output by help should > be less than 80. +1 Here are additional comments from me. @@ -4548,6 +4570,8 @@ getResultString(bool skipped, EStatus estatus) return "serialization"; case ESTATUS_DEADLOCK_ERROR: return "deadlock"; + case ESTATUS_OTHER_SQL_ERROR: + return "error (except serialization/deadlock)"; Strings returned by getResultString() are printed in the "time" field of the log when both the -l and --failures-detailed options are set. Therefore, they should be single words that do not contain any space characters. I wonder if something like "other" or "other_sql_error" would be appropriate. @@ -4099,6 +4119,7 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) * can retry the error. */ st->state = timer_exceeded ? CSTATE_FINISHED : + continue_on_error ? CSTATE_FAILURE : doRetry(st, &now) ? CSTATE_RETRY : CSTATE_FAILURE; } else This fix is not necessary because doRetry() (and canRetryError(), which is called within it) will return false when continue_on_error is set (after applying patch 0002). case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: st->estatus = getSQLErrorStatus(PQresultErrorField(res, PG_DIAG_SQLSTATE)); if (canRetryError(st->estatus)) { if (verbose_errors) commandError(st, PQerrorMessage(st->con)); goto error; } /* fall through */ default: /* anything else is unexpected */ pg_log_error("client %d script %d aborted in command %d query %d: %s", st->id, st->use_file, st->command, qrynum, PQerrorMessage(st->con)); goto error; } When an SQL error other than a serialization or deadlock error occurs, an error message is output via pg_log_error in this code path. However, I think this should be reported only when verbose_errors is set, similar to how serialization and deadlock errors are handled when --continue-on-error is enabled Best regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
RE: Suggestion to add --continue-client-on-abort option to pgbench
Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-06-17T03:47:00Z
Dear Nagata-san, > > > 2. The exit-on-abort option and continue-on-error option are mutually > exclusive. > > > Therefore, I've updated the patch to throw a FATAL error when two options > are > > > set simultaneously. Corresponding explanation was also added. > > I don't think that's right since "abort" and "error" are different concept in pgbench. > (Here, "abort" refers to the termination of a client, not a transaction abort.) > > The --exit-on-abort option forces to exit pgbench immediately when any client is > aborted > due to some error. When the --continue-on-error option is not set, SQL errors > other than > deadlock or serialization error cause a client to be aborted. On the other hand, > when the option > is set, clients are not aborted due to any SQL errors; instead they continue to run > after them. > However, clients can still be aborted for other reasons, such as connection > failures or > meta-command errors (e.g., \set x 1/0). In these cases, the --exit-on-abort option > remains > useful even when --continue-on-error is enabled. To clarify: another approach is that allow --continue-on-error option to continue running even when clients meet such errors. Which one is better? > > 02. patch separation > > How about separating the patch series like: > > > > 0001 - contains option handling and retry part, and documentation > > 0002 - contains accumulation/reporting part > > 0003 - contains tests. > > > > I hope above style is more helpful for reviewers. > > I'm not sure whether it's necessary to split the patch, as the change doesn't seem > very > complex. However, the current separation appears inconsistent. For example, > patch 0001 > modifies canRetryError(), but patch 0002 reverts that change, and so on. Either way is fine for me if they are changed from the current method. > > > > > 04. documentation > > ``` > > + Client rolls back the failed transaction and starts a new one when its > > + transaction fails due to the reason other than the deadlock and > > + serialization failure. This allows all clients specified with -c option > > + to continuously apply load to the server, even if some transactions > fail. > > ``` > > > > I feel the description contains bit redundant part and misses the default > behavior. > > How about: > > ``` > > <para> > > Clients survive when their transactions are aborted, and they continue > > their run. Without the option, clients exit when transactions they run > > are aborted. > > </para> > > <para> > > Note that serialization failures or deadlock failures do not abort the > > client, so they are not affected by this option. > > See <xref linkend="failures-and-retries"/> for more information. > > </para> > > ``` > > I think we can make it clearer as follows: I do not have confident for English, native speaker is needed.... > > 06. usage() > > Added line is too long. According to program_help_ok(), the output by help > should > > be less than 80. > > +1 FYI - I posted a patch which adds the test. You can apply and confirm how the function says. [1]: https://www.postgresql.org/message-id/OSCPR01MB1496610451F5896375B2562E6F56BA%40OSCPR01MB14966.jpnprd01.prod.outlook.com Best regards, Hayato Kuroda FUJITSU LIMITED
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-06-17T07:28:28Z
On Tue, 17 Jun 2025 03:47:00 +0000 "Hayato Kuroda (Fujitsu)" <kuroda.hayato@fujitsu.com> wrote: > Dear Nagata-san, > > > > > 2. The exit-on-abort option and continue-on-error option are mutually > > exclusive. > > > > Therefore, I've updated the patch to throw a FATAL error when two options > > are > > > > set simultaneously. Corresponding explanation was also added. > > > > I don't think that's right since "abort" and "error" are different concept in pgbench. > > (Here, "abort" refers to the termination of a client, not a transaction abort.) > > > > The --exit-on-abort option forces to exit pgbench immediately when any client is > > aborted > > due to some error. When the --continue-on-error option is not set, SQL errors > > other than > > deadlock or serialization error cause a client to be aborted. On the other hand, > > when the option > > is set, clients are not aborted due to any SQL errors; instead they continue to run > > after them. > > However, clients can still be aborted for other reasons, such as connection > > failures or > > meta-command errors (e.g., \set x 1/0). In these cases, the --exit-on-abort option > > remains > > useful even when --continue-on-error is enabled. > > To clarify: another approach is that allow --continue-on-error option to continue > running even when clients meet such errors. Which one is better? It might be worth discussing which types of errors this option should allow pgbench to continue after. On my understand the current patch's goal is to allow only SQL level errors like comstraint violations. It seems good because this could simulate behaviour of applications that ignore or retry such errors (although they are not retried in the current patch). Perhaps, it makes sense to allow to continue after some network errors because it would enable benchmarks usign a cluster system as a cloud service that could report a temporary error during a failover. It might be worth discussing which types of errors this option should allow pgbench to continue after. As I understand it, the current patch aims to allow continuation only after SQL-level errors, such as constraint violations. That seems reasonable, as it can simulate the behavior of applications that ignore or retry such errors (even though retries are not implemented in the current patch). Perhaps it also makes sense to allow continuation after certain network errors, as this would enable benchmarking with cluster systems or cloud services, which might report temporary errors during a failover. We would need additional work to properly detect and handle network errors, though. However, I'm not sure it's reasonable to allow continuation after other types of errors, such as misuse of meta-commands or unexpected errors during their execution, since these wouldn't simulate any real application behavior and would more likely indicate a failure in the benchmarking process itself. Best regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-06-17T07:35:28Z
On Tue, 17 Jun 2025 16:28:28 +0900 Yugo Nagata <nagata@sraoss.co.jp> wrote: > On Tue, 17 Jun 2025 03:47:00 +0000 > "Hayato Kuroda (Fujitsu)" <kuroda.hayato@fujitsu.com> wrote: > > > Dear Nagata-san, > > > > > > > 2. The exit-on-abort option and continue-on-error option are mutually > > > exclusive. > > > > > Therefore, I've updated the patch to throw a FATAL error when two options > > > are > > > > > set simultaneously. Corresponding explanation was also added. > > > > > > I don't think that's right since "abort" and "error" are different concept in pgbench. > > > (Here, "abort" refers to the termination of a client, not a transaction abort.) > > > > > > The --exit-on-abort option forces to exit pgbench immediately when any client is > > > aborted > > > due to some error. When the --continue-on-error option is not set, SQL errors > > > other than > > > deadlock or serialization error cause a client to be aborted. On the other hand, > > > when the option > > > is set, clients are not aborted due to any SQL errors; instead they continue to run > > > after them. > > > However, clients can still be aborted for other reasons, such as connection > > > failures or > > > meta-command errors (e.g., \set x 1/0). In these cases, the --exit-on-abort option > > > remains > > > useful even when --continue-on-error is enabled. > > > > To clarify: another approach is that allow --continue-on-error option to continue > > running even when clients meet such errors. Which one is better? > > It might be worth discussing which types of errors this option should allow pgbench > to continue after. On my understand the current patch's goal is to allow only SQL > level errors like comstraint violations. It seems good because this could simulate > behaviour of applications that ignore or retry such errors (although they are not > retried in the current patch). Perhaps, it makes sense to allow to continue after > some network errors because it would enable benchmarks usign a cluster system as a > cloud service that could report a temporary error during a failover. I apologize for accidentally leaving the draft paragraph just above in my previous post. Please ignore it. > It might be worth discussing which types of errors this option should allow pgbench to > continue after. > > As I understand it, the current patch aims to allow continuation only after SQL-level > errors, such as constraint violations. That seems reasonable, as it can simulate the > behavior of applications that ignore or retry such errors (even though retries are not > implemented in the current patch). > > Perhaps it also makes sense to allow continuation after certain network errors, as this > would enable benchmarking with cluster systems or cloud services, which might report > temporary errors during a failover. We would need additional work to properly detect > and handle network errors, though. > > However, I'm not sure it's reasonable to allow continuation after other types of errors, > such as misuse of meta-commands or unexpected errors during their execution, since these > wouldn't simulate any real application behavior and would more likely indicate a failure > in the benchmarking process itself. > > Best regards, > Yugo Nagata > > -- > Yugo Nagata <nagata@sraoss.co.jp> > > -- Yugo Nagata <nagata@sraoss.co.jp>
-
RE: Suggestion to add --continue-client-on-abort option to pgbench
Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-06-26T05:45:12Z
Dear Nagata-san, > As I understand it, the current patch aims to allow continuation only after > SQL-level > errors, such as constraint violations. That seems reasonable, as it can simulate > the > behavior of applications that ignore or retry such errors (even though retries are > not > implemented in the current patch). Yes, no one has objections to retry in this case. This is a main part of the proposal. > However, I'm not sure it's reasonable to allow continuation after other types of > errors, > such as misuse of meta-commands or unexpected errors during their execution, > since these > wouldn't simulate any real application behavior and would more likely indicate a > failure > in the benchmarking process itself. I have a concern for \gset metacommand. According to the doc and source code, \gset assumed that executed command surely returns a tuple: ``` if (meta == META_GSET && ntuples != 1) { /* under \gset, report the error */ pg_log_error("client %d script %d command %d query %d: expected one row, got %d", st->id, st->use_file, st->command, qrynum, PQntuples(res)); st->estatus = ESTATUS_META_COMMAND_ERROR; goto error; } ``` But sometimes the SQL may not be able to return tuples or return multiple ones due to the concurrent transactions. I feel retrying the transaction is very useful in this case. Anyway, we must confirm the opinion from the proposer. [1]: https://github.com/ryogrid/tpcc_like_with_pgbench Best regards, Hayato Kuroda FUJITSU LIMITED -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-06-26T09:47:33Z
On Thu, 26 Jun 2025 05:45:12 +0000 "Hayato Kuroda (Fujitsu)" <kuroda.hayato@fujitsu.com> wrote: > Dear Nagata-san, > > > As I understand it, the current patch aims to allow continuation only after > > SQL-level > > errors, such as constraint violations. That seems reasonable, as it can simulate > > the > > behavior of applications that ignore or retry such errors (even though retries are > > not > > implemented in the current patch). > > Yes, no one has objections to retry in this case. This is a main part of the proposal., As I understand it, the proposed --continue-on-error option does not retry the transaction in any case; it simply gives up on the transaction. That is, when an SQL-level error occurs, the transaction is reported as "failed" rather than "retried", and the random state is discarded. > > > However, I'm not sure it's reasonable to allow continuation after other types of > > errors, > > such as misuse of meta-commands or unexpected errors during their execution, > > since these > > wouldn't simulate any real application behavior and would more likely indicate a > > failure > > in the benchmarking process itself. > > I have a concern for \gset metacommand. > According to the doc and source code, \gset assumed that executed command surely > returns a tuple: > > ``` > if (meta == META_GSET && ntuples != 1) > { > /* under \gset, report the error */ > pg_log_error("client %d script %d command %d query %d: expected one row, got %d", > st->id, st->use_file, st->command, qrynum, PQntuples(res)); > st->estatus = ESTATUS_META_COMMAND_ERROR; > goto error; > } > ``` > > But sometimes the SQL may not be able to return tuples or return multiple ones due > to the concurrent transactions. I feel retrying the transaction is very useful > in this case. You can use \aset command instead to avoid the error of pgbench. If the query doesn't return any row, a subsecuent SQL command trying to use the varialbe will fail, but this would be ignored without terminating the benchmark when the --coneinue-on-error option enabled. > Anyway, we must confirm the opinion from the proposer. +1 Best regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-06-27T05:06:24Z
Hi, Thank you very much for your valuable comments and kind advice. I'm currently working on revising the previous patch based on the feedback received. I would like to share my thoughts regarding the conditions under which the --continue-on-error option should initiate a new transaction or a new connection. In my opinion, when the --continue-on-error option is enabled, pgbench clients does not need to start new transactions after network errors and other errors except for SQL-level errors. Network errors are relatively rare, except in failover scenarios. Outside of failover, any network issues should be resolved rather than worked around. In the context of failover, the key metric is not TPS, but system downtime. While one might infer the timing of a failover by observing by using --progress option, you can easily determine the downtime by executing simple SQL query such as `psql -c 'SELECT 1` every second. On 2025/06/26 18:47, Yugo Nagata wrote: > On Thu, 26 Jun 2025 05:45:12 +0000 > "Hayato Kuroda (Fujitsu)" <kuroda.hayato@fujitsu.com> wrote: > >> Dear Nagata-san, >> >>> As I understand it, the current patch aims to allow continuation only >>> after >>> SQL-level >>> errors, such as constraint violations. That seems reasonable, as it >>> can simulate >>> the >>> behavior of applications that ignore or retry such errors (even >>> though retries are >>> not >>> implemented in the current patch). >> >> Yes, no one has objections to retry in this case. This is a main part >> of the proposal., > > As I understand it, the proposed --continue-on-error option does not > retry the transaction > in any case; it simply gives up on the transaction. That is, when an > SQL-level error occurs, > the transaction is reported as "failed" rather than "retried", and the > random state is discarded. Retrying the failed transaction is not necessary when the transaction failed due to SQL-level errors. Unlike real-world applications, pgbench does not need to complete specific transaction successfully. In the case of unique constraint violations, retrying the same transaction will likely to result in the same error again. I want to hear your thoughts on this. Best regards, Rintaro Ikeda
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-06-27T06:17:11Z
On Fri, 27 Jun 2025 14:06:24 +0900 ikedarintarof <ikedarintarof@oss.nttdata.com> wrote: > Hi, > > Thank you very much for your valuable comments and kind advice. I'm > currently working on revising the previous patch based on the feedback > received. I would like to share my thoughts regarding the conditions > under which the --continue-on-error option should initiate a new > transaction or a new connection. > > In my opinion, when the --continue-on-error option is enabled, pgbench > clients does not need to start new transactions after network errors and > other errors except for SQL-level errors. +1 I agree that --continue-on-error prevents pgbench from terminating only when SQL-level errors occur, and does not change the behavior in the case of other types of errors, including network errors. > > As I understand it, the proposed --continue-on-error option does not > > retry the transaction > > in any case; it simply gives up on the transaction. That is, when an > > SQL-level error occurs, > > the transaction is reported as "failed" rather than "retried", and the > > random state is discarded. > > Retrying the failed transaction is not necessary when the transaction > failed due to SQL-level errors. Unlike real-world applications, pgbench > does not need to complete specific transaction successfully. In the case > of unique constraint violations, retrying the same transaction will > likely to result in the same error again. Agreed. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
RE: Suggestion to add --continue-client-on-abort option to pgbench
Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-06-27T10:59:09Z
Dear Nagata-san, Ikeda-san, > > In my opinion, when the --continue-on-error option is enabled, pgbench > > clients does not need to start new transactions after network errors and > > other errors except for SQL-level errors. > > +1 > > I agree that --continue-on-error prevents pgbench from terminating only when > SQL-level errors occur, and does not change the behavior in the case of other > types of errors, including network errors. OK, so let's do like that. BTW, initially we were discussing the combination of --continue-on-error and --exit-on-abort. What it the conclusion? I feel the Nagata-san's point [1] is valid in this approach. > > > As I understand it, the proposed --continue-on-error option does not > > > retry the transaction > > > in any case; it simply gives up on the transaction. That is, when an > > > SQL-level error occurs, > > > the transaction is reported as "failed" rather than "retried", and the > > > random state is discarded. > > > > Retrying the failed transaction is not necessary when the transaction > > failed due to SQL-level errors. Unlike real-world applications, pgbench > > does not need to complete specific transaction successfully. In the case > > of unique constraint violations, retrying the same transaction will > > likely to result in the same error again. I intended here that clients could throw away the failed transaction and start new one again in the case. I hope we are on the same page... [1]: https://www.postgresql.org/message-id/20250614002453.5c72f2ec80864d840150a642%40sraoss.co.jp Best regards, Hayato Kuroda FUJITSU LIMITED
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-06-30T06:02:36Z
On Fri, 27 Jun 2025 10:59:09 +0000 "Hayato Kuroda (Fujitsu)" <kuroda.hayato@fujitsu.com> wrote: > > > Retrying the failed transaction is not necessary when the transaction > > > failed due to SQL-level errors. Unlike real-world applications, pgbench > > > does not need to complete specific transaction successfully. In the case > > > of unique constraint violations, retrying the same transaction will > > > likely to result in the same error again. > > I intended here that clients could throw away the failed transaction and start > new one again in the case. I hope we are on the same page... Could I confirm what you mean by "start new one"? In the current pgbench, when a query raises an error (a deadlock or serialization failure), it can be retried using the same random state. This typically means the query will be retried with the same parameter values. On the other hand, when the query ultimately fails (possibly after some retries), the transaction is marked as a "failure", and the next transaction starts with a new random state (i.e., with new parameter values). Therefore, if a query fails due to a unique constraint violation and is retried with the same parameters, it will keep failing on each retry. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-07-01T08:43:18Z
Hi, I've updated the previous patch based on your feedback. Below is a summary of the changes from v4 to v5: 1. (v5-0001) Added documentation and removed some code paths in response to the comments. 2. (v5-0001) Modified the condition to transition from CSTATE_WAIT_RESULT to CSTATE_ERROR, instead of adding a condition in canRetryError(), which had enabled clients continue after its transaction failed. This is because, when the --continue-on-error option is set, clients do not retry failed transactions but start new ones. 3. (v5-0002) Renamed the enumerator TSTATUS_OTHER_ERROR, which could be mistakenly interpreted as being related to other SQL errors. It represents an unknown transaction status, so it has been renamed to TSTATUS_UNKNOWN_ERROR. On 2025/06/14 0:24, Yugo Nagata wrote: > case PGRES_NONFATAL_ERROR: > case PGRES_FATAL_ERROR: > st->estatus = getSQLErrorStatus(PQresultErrorField(res, > PG_DIAG_SQLSTATE)); > if (canRetryError(st->estatus)) > { > if (verbose_errors) > commandError(st, PQerrorMessage(st->con)); > goto error; > } > /* fall through */ > > default: > /* anything else is unexpected */ > pg_log_error("client %d script %d aborted in command %d query %d: %s", > st->id, st->use_file, st->command, qrynum, > PQerrorMessage(st->con)); > goto error; > } > > When an SQL error other than a serialization or deadlock error occurs, an error message is > output via pg_log_error in this code path. However, I think this should be reported only > when verbose_errors is set, similar to how serialization and deadlock errors are handled when > --continue-on-error is enabled I think the error message logged via pg_log_error is useful when verbose_errors is not specified, because it informs users that the client has exited. Without it, users may not notice that something went wrong. On 2025/06/27 19:59, Hayato Kuroda (Fujitsu) wrote: > BTW, initially we were discussing the combination of --continue-on-error and > --exit-on-abort. What it the conclusion? > I feel the Nagata-san's point [1] is valid in this approach. I agree with the conclusion. I've removed the code path that prohibited using --continue-on-error and --exit-on-abort options together. On 2025/06/30 15:02, Yugo Nagata wrote: > On Fri, 27 Jun 2025 10:59:09 +0000 > "Hayato Kuroda (Fujitsu)" <kuroda.hayato@fujitsu.com> wrote: > >>>> Retrying the failed transaction is not necessary when the transaction >>>> failed due to SQL-level errors. Unlike real-world applications, pgbench >>>> does not need to complete specific transaction successfully. In the case >>>> of unique constraint violations, retrying the same transaction will >>>> likely to result in the same error again. >> >> I intended here that clients could throw away the failed transaction and start >> new one again in the case. I hope we are on the same page... > > Could I confirm what you mean by "start new one"? > > In the current pgbench, when a query raises an error (a deadlock or > serialization failure), it can be retried using the same random state. > This typically means the query will be retried with the same parameter values. > > On the other hand, when the query ultimately fails (possibly after some retries), > the transaction is marked as a "failure", and the next transaction starts with a > new random state (i.e., with new parameter values). > > Therefore, if a query fails due to a unique constraint violation and is retried > with the same parameters, it will keep failing on each retry. Thank you for your explanation. I understand it as you described. I've also attached a schematic diagram of the state machine. I hope it will help clarify the behavior of pgbench. Red arrows represent the transition of state when SQL command fails and --continue-on-error option is specified. Best Regards, Rintaro Ikeda -
RE: Suggestion to add --continue-client-on-abort option to pgbench
Hayato Kuroda (Fujitsu) <kuroda.hayato@fujitsu.com> — 2025-07-04T13:01:12Z
Dear Ikeda-san, Nagata-san, Thanks for updating the patch! > > Could I confirm what you mean by "start new one"? > > > > In the current pgbench, when a query raises an error (a deadlock or > > serialization failure), it can be retried using the same random state. > > This typically means the query will be retried with the same parameter values. > > > > On the other hand, when the query ultimately fails (possibly after some retries), > > the transaction is marked as a "failure", and the next transaction starts with a > > new random state (i.e., with new parameter values). > > > > Therefore, if a query fails due to a unique constraint violation and is retried > > with the same parameters, it will keep failing on each retry. > > Thank you for your explanation. I understand it as you described. I've also > attached a schematic diagram of the state machine. I hope it will help clarify > the behavior of pgbench. Red arrows represent the transition of state when SQL > command fails and --continue-on-error option is specified. Thanks for the diagram, it's quite helpful. Let me share my understanding and opinion. The terminology "retry" is being used for the transition CSTATE_ERROR->CSTATE_RETRY, and here the random state would be restored to be the begining: ``` /* * Reset the random state as they were at the beginning of the * transaction. */ st->cs_func_rs = st->random_state; ``` In --continue-on-error case, the transaction CSTATE_WAIT_RESULT->CSTATE_ERROR can happen even the reason of failure is not serialization and deadlock. Ultimately the pass will reach ...->CSTATE_END_TX->CSTATE_CHOOSE_SCRIPT, the beginning of the state machine. cs_func_rs is not overwritten in the route so that different random value would be generated, or even another script may be chosen. Is it correct? And I feel this behavior is OK. Most likely failure here is the unique constraint violation. Clients should roll the dice again otherwise it would face the same error again. Below are my comments for the latest patch. 01. ``` $ git am ../patches/pgbench/v5-0001-Add-continue-on-error-opt ion-to-pgbench.patch Applying: When the option is set, client rolls back the failed transaction and... .git/rebase-apply/patch:65: trailing whitespace. <literal>serialization</literal>, <literal>deadlock</literal>, or .git/rebase-apply/patch:139: trailing whitespace. <option>--max-tries</option> option is not equal to 1 and warning: 2 lines add whitespace errors. ``` I got warnings when I applied the patch. Please fix it. 02. ``` + * 'serialization_failures' + 'deadlock_failures' + + * 'other_sql_failures' (they got a error when continue-on-error option ``` The first line has the tab, but it should be normal blank. 03. ``` + else if (continue_on_error | canRetryError(st->estatus)) ``` I feel "|" should be "||". 04. ``` <term><replaceable>retries</replaceable></term> <listitem> <para> number of retries after serialization or deadlock errors (zero unless <option>--max-tries</option> is not equal to one) </para> </listitem> ``` To confirm; --continue-on-error won't be counted here because it is not "retry", in other words, it does not reach CSTATE_RETRY, right? Best regards, Hayato Kuroda FUJITSU LIMITED -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-07-04T15:03:56Z
Hi, On Tue, 1 Jul 2025 17:43:18 +0900 Rintaro Ikeda <ikedarintarof@oss.nttdata.com> wrote: > I've updated the previous patch based on your feedback. Below is a summary of > the changes from v4 to v5: Thank you for updating the patch. > On 2025/06/14 0:24, Yugo Nagata wrote: > > case PGRES_NONFATAL_ERROR: > > case PGRES_FATAL_ERROR: > > st->estatus = getSQLErrorStatus(PQresultErrorField(res, > > PG_DIAG_SQLSTATE)); > > if (canRetryError(st->estatus)) > > { > > if (verbose_errors) > > commandError(st, PQerrorMessage(st->con)); > > goto error; > > } > > /* fall through */ > > > > default: > > /* anything else is unexpected */ > > pg_log_error("client %d script %d aborted in command %d query %d: %s", > > st->id, st->use_file, st->command, qrynum, > > PQerrorMessage(st->con)); > > goto error; > > } > > > > When an SQL error other than a serialization or deadlock error occurs, an error message is > > output via pg_log_error in this code path. However, I think this should be reported only > > when verbose_errors is set, similar to how serialization and deadlock errors are handled when > > --continue-on-error is enabled > > I think the error message logged via pg_log_error is useful when verbose_errors > is not specified, because it informs users that the client has exited. Without > it, users may not notice that something went wrong. However, if a large number of errors occur, this could result in a significant increase in stderr output during the benchmark. Users can still notice that something went wrong by checking the “number of other failures” reported after the run, and I assume that in most cases, when --continue-on-error is enabled, users aren’t particularly interested in seeing individual error messages as they happen. It’s true that seeing error messages during the benchmark might be useful in some cases, but the same could be said for serialization or deadlock errors, and that’s exactly what the --verbose-errors option is for. Here are some comments on the patch. (1) } - else if (canRetryError(st->estatus)) + else if (continue_on_error | canRetryError(st->estatus)) st->state = CSTATE_ERROR; else st->state = CSTATE_ABORTED; Due to this change, when --continue-on-error is enabled, st->state is set to CSTATE_ERROR regardless of the type of error returned by readCommandResponse. When the error is not ESTATUS_OTHER_SQL_ERROR, e.g. ESTATUS_META_COMMAND_ERROR due to a failure of \gset with query returning more the one row. Therefore, this should be like: else if ((st->estatus == ESTATUS_OTHER_SQL_ERROR && continue_on_error) || canRetryError(st->estatus)) (2) + " --continue-on-error continue processing transations after a trasaction fails\n" "trasaction" is a typo and including "transaction" twice looks a bit redundant. Instead using the word "transaction", how about: "--continue-on-error continue running after an SQL error" ? This version is shorter, avoids repetition, and describes well the actual behavior when SQL statements fail. As for the comments: (3) - * A failed transaction is defined as unsuccessfully retried transactions. + * A failed transaction is defined as unsuccessfully retried transactions + * unless continue-on-error option is specified. * It can be one of two types: * * failed (the number of failed transactions) = @@ -411,6 +412,12 @@ typedef struct StatsData * 'deadlock_failures' (they got a deadlock error and were not * successfully retried). * + * When continue-on-error option is specified, + * failed (the number of failed transactions) = + * 'serialization_failures' + 'deadlock_failures' + + * 'other_sql_failures' (they got a error when continue-on-error option + * was specified). + * To explain explicitly that there are two definitions of failed transactions depending on the situation, how about: """ A failed transaction is counted differently depending on whether the --continue-on-error option is specified. Without --continue-on-error: failed (the number of failed transactions) = 'serialization_failures' (they got a serialization error and were not successfully retried) + 'deadlock_failures' (they got a deadlock error and were not successfully retried). When --continue-on-error is specified: failed (number of failed transactions) = 'serialization_failures' + 'deadlock_failures' + 'other_sql_failures' (they got some other SQL error; the transaction was not retried and counted as failed due to --continue-on-error). """ (4) + int64 other_sql_failures; /* number of failed transactions for + * reasons other than + * serialization/deadlock failure , which + * is enabled if --continue-on-error is + * used */ Is "counted" is more proper than "enabled" here? Af for the documentations: (5) The next line reports the number of failed transactions due to - serialization or deadlock errors (see <xref linkend="failures-and-retries"/> - for more information). + serialization or deadlock errors by default (see + <xref linkend="failures-and-retries"/> for more information). Would it be more readable to simply say: "The next line reports the number of failed transactions (see ... for more information), since definition of "failed transaction" has become a bit messy? (6) connection with the database server was lost or the end of script was reached without completing the last transaction. In addition, if execution of an SQL or meta command fails for reasons other than serialization or deadlock errors, - the client is aborted. Otherwise, if an SQL command fails with serialization or - deadlock errors, the client is not aborted. In such cases, the current - transaction is rolled back, which also includes setting the client variables - as they were before the run of this transaction (it is assumed that one - transaction script contains only one transaction; see - <xref linkend="transactions-and-scripts"/> for more information). + the client is aborted by default. However, if the --continue-on-error option + is specified, the client does not abort and proceeds to the next transaction + regardless of the error. This case is reported as other failures in the output. + Otherwise, if an SQL command fails with serialization or deadlock errors, the + client is not aborted. In such cases, the current transaction is rolled back, + which also includes setting the client variables as they were before the run + of this transaction (it is assumed that one transaction script contains only + one transaction; see <xref linkend="transactions-and-scripts"/> for more information). To emphasize the default behavior, I wonder it would be better to move "by default" to the beginning of the statements; like "By default, if execution of an SQL or meta command fails for reasons other than serialization or deadlock errors, the client is aborted." How about quoting "other failures"? like: "These cases are reported as "other failures" in the output." Also, I feel the meaning of "Otherwise" has becomes somewhat unclear since the explanation of --continue-on-error was added between the sentences So, how about clarifying that "the clients are not aborted due to serializable/deadlock even without --continue-on-error". For example; "On contrast, if an SQL command fails with serialization or deadlock errors, the client is not aborted even without <option>--continue-on-error</option>. Instead, the current transaction is rolled back, which also includes setting the client variables as they were before the run of this transaction (it is assumed that one transaction script contains only one transaction; see <xref linkend="transactions-and-scripts"/> for more information)." (7) The main report contains the number of failed transactions. If the - <option>--max-tries</option> option is not equal to 1, the main report also + <option>--max-tries</option> option is not equal to 1 and + <option>--continue-on-error</option> is not specified, the main report also contains statistics related to retries: the total number of retried Is that true? The retreis statitics would be included even without --continue-on-error. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-07-04T15:22:39Z
On Fri, 4 Jul 2025 13:01:12 +0000 "Hayato Kuroda (Fujitsu)" <kuroda.hayato@fujitsu.com> wrote: > Thanks for the diagram, it's quite helpful. Let me share my understanding and opinion. > > The terminology "retry" is being used for the transition CSTATE_ERROR->CSTATE_RETRY, > and here the random state would be restored to be the begining: > > ``` > /* > * Reset the random state as they were at the beginning of the > * transaction. > */ > st->cs_func_rs = st->random_state; > ``` Yes. The random state is reset in the CSTATE_RETRY state, which then transitions directly to CSTATE_START_COMMAND. > In --continue-on-error case, the transaction CSTATE_WAIT_RESULT->CSTATE_ERROR > can happen even the reason of failure is not serialization and deadlock. > Ultimately the pass will reach ...->CSTATE_END_TX->CSTATE_CHOOSE_SCRIPT, the > beginning of the state machine. cs_func_rs is not overwritten in the route so > that different random value would be generated, or even another script may be > chosen. Is it correct? Yes, that matches my understanding. > 04. > ``` > <term><replaceable>retries</replaceable></term> > <listitem> > <para> > number of retries after serialization or deadlock errors > (zero unless <option>--max-tries</option> is not equal to one) > </para> > </listitem> > ``` > > To confirm; --continue-on-error won't be counted here because it is not "retry", > in other words, it does not reach CSTATE_RETRY, right? Right. Transactions marked as failure due to --continue-on-error are not retried and should not counted here. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-07-09T14:58:32Z
Hi, Thank you for the kind comments. I've updated the previous patch. Below is a summary of the changes: 1. The code path and documentation have been corrected based on your feedback. 2. The following message is now suppressed by default. Instead, an error message is added when a client aborts during SQL execution. (v6-0003-Suppress-xxx.patch) ``` if (verbose_errors) pg_log_error("client %d script %d aborted in command %d query %d: %s", st->id, st->use_file, st->command, qrynum, PQerrorMessage(st->con)); ``` On 2025/07/04 22:01, Hayato Kuroda (Fujitsu) wrote: >>> Could I confirm what you mean by "start new one"? >>> >>> In the current pgbench, when a query raises an error (a deadlock or >>> serialization failure), it can be retried using the same random state. >>> This typically means the query will be retried with the same parameter values. >>> >>> On the other hand, when the query ultimately fails (possibly after some retries), >>> the transaction is marked as a "failure", and the next transaction starts with a >>> new random state (i.e., with new parameter values). >>> >>> Therefore, if a query fails due to a unique constraint violation and is retried >>> with the same parameters, it will keep failing on each retry. >> >> Thank you for your explanation. I understand it as you described. I've also >> attached a schematic diagram of the state machine. I hope it will help clarify >> the behavior of pgbench. Red arrows represent the transition of state when SQL >> command fails and --continue-on-error option is specified. > > Thanks for the diagram, it's quite helpful. Let me share my understanding and opinion. > > The terminology "retry" is being used for the transition CSTATE_ERROR->CSTATE_RETRY, > and here the random state would be restored to be the begining: > > ``` > /* > * Reset the random state as they were at the beginning of the > * transaction. > */ > st->cs_func_rs = st->random_state; > ``` > > In --continue-on-error case, the transaction CSTATE_WAIT_RESULT->CSTATE_ERROR > can happen even the reason of failure is not serialization and deadlock. > Ultimately the pass will reach ...->CSTATE_END_TX->CSTATE_CHOOSE_SCRIPT, the > beginning of the state machine. cs_func_rs is not overwritten in the route so > that different random value would be generated, or even another script may be > chosen. Is it correct? Yes, I believe that’s correct. > > 01. > ``` > $ git am ../patches/pgbench/v5-0001-Add-continue-on-error-opt > ion-to-pgbench.patch > Applying: When the option is set, client rolls back the failed transaction and... > .git/rebase-apply/patch:65: trailing whitespace. > <literal>serialization</literal>, <literal>deadlock</literal>, or > .git/rebase-apply/patch:139: trailing whitespace. > <option>--max-tries</option> option is not equal to 1 and > warning: 2 lines add whitespace errors. > ``` > > I got warnings when I applied the patch. Please fix it. It's been fixed. > > 02. > ``` > + * 'serialization_failures' + 'deadlock_failures' + > + * 'other_sql_failures' (they got a error when continue-on-error option > ``` > The first line has the tab, but it should be normal blank. I hadn't noticed it. It's fixed. > 03. > ``` > + else if (continue_on_error | canRetryError(st->estatus)) > ``` > > I feel "|" should be "||". Thank you for pointing out. Fixed it. > 04. > ``` > <term><replaceable>retries</replaceable></term> > <listitem> > <para> > number of retries after serialization or deadlock errors > (zero unless <option>--max-tries</option> is not equal to one) > </para> > </listitem> > ``` > > To confirm; --continue-on-error won't be counted here because it is not "retry", > in other words, it does not reach CSTATE_RETRY, right? Yes. I agree with Nagata-san [1] — --continue-on-error is not considered a "retry" because it doesn't reach CSTATE_RETRY. On 2025/07/05 0:03, Yugo Nagata wrote: >>> case PGRES_NONFATAL_ERROR: >>> case PGRES_FATAL_ERROR: >>> st->estatus = getSQLErrorStatus(PQresultErrorField(res, >>> PG_DIAG_SQLSTATE)); >>> if (canRetryError(st->estatus)) >>> { >>> if (verbose_errors) >>> commandError(st, PQerrorMessage(st->con)); >>> goto error; >>> } >>> /* fall through */ >>> >>> default: >>> /* anything else is unexpected */ >>> pg_log_error("client %d script %d aborted in command %d query %d: %s", >>> st->id, st->use_file, st->command, qrynum, >>> PQerrorMessage(st->con)); >>> goto error; >>> } >>> >>> When an SQL error other than a serialization or deadlock error occurs, an error message is >>> output via pg_log_error in this code path. However, I think this should be reported only >>> when verbose_errors is set, similar to how serialization and deadlock errors are handled when >>> --continue-on-error is enabled >> >> I think the error message logged via pg_log_error is useful when verbose_errors >> is not specified, because it informs users that the client has exited. Without >> it, users may not notice that something went wrong. > > However, if a large number of errors occur, this could result in a significant increase > in stderr output during the benchmark. > > Users can still notice that something went wrong by checking the “number of other failures” > reported after the run, and I assume that in most cases, when --continue-on-error is enabled, > users aren’t particularly interested in seeing individual error messages as they happen. > > It’s true that seeing error messages during the benchmark might be useful in some cases, but > the same could be said for serialization or deadlock errors, and that’s exactly what the > --verbose-errors option is for. I understand your concern. The condition for calling pg_log_error() was modified to reduce stderr output. Additionally, an error message was added for cases where some clients aborted while executing SQL commands, similar to other code paths that transition to st->state = CSTATE_ABORTED, as shown in the example below: ``` pg_log_error("client %d aborted while establishing connection", st->id); st->state = CSTATE_ABORTED; ``` > Here are some comments on the patch. > > (1) > > } > - else if (canRetryError(st->estatus)) > + else if (continue_on_error | canRetryError(st->estatus)) > st->state = CSTATE_ERROR; > else > st->state = CSTATE_ABORTED; > > Due to this change, when --continue-on-error is enabled, st->state is set to > CSTATE_ERROR regardless of the type of error returned by readCommandResponse. > When the error is not ESTATUS_OTHER_SQL_ERROR, e.g. ESTATUS_META_COMMAND_ERROR > due to a failure of \gset with query returning more the one row. > > Therefore, this should be like: > > else if ((st->estatus == ESTATUS_OTHER_SQL_ERROR && continue_on_error) || > canRetryError(st->estatus)) > Thanks for pointing that out — I’ve corrected it. > (2) > > + " --continue-on-error continue processing transations after a trasaction fails\n" > > "trasaction" is a typo and including "transaction" twice looks a bit redundant. > Instead using the word "transaction", how about: > > "--continue-on-error continue running after an SQL error" ? > > This version is shorter, avoids repetition, and describes well the actual behavior when > SQL statements fail. Fixed it. > (3) > > - * A failed transaction is defined as unsuccessfully retried transactions. > + * A failed transaction is defined as unsuccessfully retried transactions > + * unless continue-on-error option is specified. > * It can be one of two types: > * > * failed (the number of failed transactions) = > @@ -411,6 +412,12 @@ typedef struct StatsData > * 'deadlock_failures' (they got a deadlock error and were not > * successfully retried). > * > + * When continue-on-error option is specified, > + * failed (the number of failed transactions) = > + * 'serialization_failures' + 'deadlock_failures' + > + * 'other_sql_failures' (they got a error when continue-on-error option > + * was specified). > + * > > To explain explicitly that there are two definitions of failed transactions > depending on the situation, how about: > > """ > A failed transaction is counted differently depending on whether > the --continue-on-error option is specified. > > Without --continue-on-error: > > failed (the number of failed transactions) = > 'serialization_failures' (they got a serialization error and were not > successfully retried) + > 'deadlock_failures' (they got a deadlock error and were not > successfully retried). > > When --continue-on-error is specified: > > failed (number of failed transactions) = > 'serialization_failures' + 'deadlock_failures' + > 'other_sql_failures' (they got some other SQL error; the transaction was > not retried and counted as failed due to > --continue-on-error). > """ Thank you for your suggestion. I modified it accordingly. > (4) > + int64 other_sql_failures; /* number of failed transactions for > + * reasons other than > + * serialization/deadlock failure , which > + * is enabled if --continue-on-error is > + * used */ > > Is "counted" is more proper than "enabled" here? Fixed. > > Af for the documentations: > (5) > The next line reports the number of failed transactions due to > - serialization or deadlock errors (see <xref linkend="failures-and-retries"/> > - for more information). > + serialization or deadlock errors by default (see > + <xref linkend="failures-and-retries"/> for more information). > > Would it be more readable to simply say: > "The next line reports the number of failed transactions (see ... for more information), > since definition of "failed transaction" has become a bit messy? > I fixed it to the simple explanation. > (6) > connection with the database server was lost or the end of script was reached > without completing the last transaction. In addition, if execution of an SQL > or meta command fails for reasons other than serialization or deadlock errors, > - the client is aborted. Otherwise, if an SQL command fails with serialization or > - deadlock errors, the client is not aborted. In such cases, the current > - transaction is rolled back, which also includes setting the client variables > - as they were before the run of this transaction (it is assumed that one > - transaction script contains only one transaction; see > - <xref linkend="transactions-and-scripts"/> for more information). > + the client is aborted by default. However, if the --continue-on-error option > + is specified, the client does not abort and proceeds to the next transaction > + regardless of the error. This case is reported as other failures in the output. > + Otherwise, if an SQL command fails with serialization or deadlock errors, the > + client is not aborted. In such cases, the current transaction is rolled back, > + which also includes setting the client variables as they were before the run > + of this transaction (it is assumed that one transaction script contains only > + one transaction; see <xref linkend="transactions-and-scripts"/> for more information). > > To emphasize the default behavior, I wonder it would be better to move "by default" > to the beginning of the statements; like > > "By default, if execution of an SQL or meta command fails for reasons other than > serialization or deadlock errors, the client is aborted." > > How about quoting "other failures"? like: > > "These cases are reported as "other failures" in the output." > > Also, I feel the meaning of "Otherwise" has becomes somewhat unclear since the > explanation of --continue-on-error was added between the sentences So, how about > clarifying that "the clients are not aborted due to serializable/deadlock even without > --continue-on-error". For example; > > "On contrast, if an SQL command fails with serialization or deadlock errors, the > client is not aborted even without <option>--continue-on-error</option>. > Instead, the current transaction is rolled back, which also includes setting > the client variables as they were before the run of this transaction > (it is assumed that one transaction script contains only > one transaction; see <xref linkend="transactions-and-scripts"/> for more information)." > I've modified according to your suggestion. > (7) > The main report contains the number of failed transactions. If the > - <option>--max-tries</option> option is not equal to 1, the main report also > + <option>--max-tries</option> option is not equal to 1 and > + <option>--continue-on-error</option> is not specified, the main report also > contains statistics related to retries: the total number of retried > > Is that true? > The retreis statitics would be included even without --continue-on-error. That was wrong. I corrected it. [1] https://www.postgresql.org/message-id/20250705002239.27e6e5a4ba22c047ac2fa16a%40sraoss.co.jp Regards, Rintaro Ikeda -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-07-10T09:17:01Z
On Wed, 9 Jul 2025 23:58:32 +0900 Rintaro Ikeda <ikedarintarof@oss.nttdata.com> wrote: > Hi, > > Thank you for the kind comments. > > I've updated the previous patch. Thank you for updating the patch! > > However, if a large number of errors occur, this could result in a significant increase > > in stderr output during the benchmark. > > > > Users can still notice that something went wrong by checking the “number of other failures” > > reported after the run, and I assume that in most cases, when --continue-on-error is enabled, > > users aren’t particularly interested in seeing individual error messages as they happen. > > > > It’s true that seeing error messages during the benchmark might be useful in some cases, but > > the same could be said for serialization or deadlock errors, and that’s exactly what the > > --verbose-errors option is for. > > > I understand your concern. The condition for calling pg_log_error() was modified > to reduce stderr output. > Additionally, an error message was added for cases where some clients aborted > while executing SQL commands, similar to other code paths that transition to > st->state = CSTATE_ABORTED, as shown in the example below: > > ``` > pg_log_error("client %d aborted while establishing connection", st->id); > st->state = CSTATE_ABORTED; > ``` default: /* anything else is unexpected */ - pg_log_error("client %d script %d aborted in command %d query %d: %s", - st->id, st->use_file, st->command, qrynum, - PQerrorMessage(st->con)); + if (verbose_errors) + pg_log_error("client %d script %d aborted in command %d query %d: %s", + st->id, st->use_file, st->command, qrynum, + PQerrorMessage(st->con)); goto error; } Thanks to this fix, error messages caused by SQL errors are now output only when --verbose-errors is enable. However, the comment describes the condition as "unexpected", and the message states that the client was "aborted". This does not seems accurate, since clients are not aborted due to SQL errors when --continue-on-errors is enabled. I think the error message should be emitted using commandError() when both --coneinut-on-errors and --verbose-errors are specified, like this; case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: st->estatus = getSQLErrorStatus(PQresultErrorField(res, PG_DIAG_SQLSTATE)); if (continue_on_error || canRetryError(st->estatus)) { if (verbose_errors) commandError(st, PQerrorMessage(st->con)); goto error; } /* fall through */ In addition, the error message in the "default" case should be shown regardless of the --verbose-errors since it represents an unexpected situation and should always reported. Finally, I believe this fix should be included in patch 0001 rather than 0003, as it would be a part of the implementation of --continiue-on-error. As of 0003: + { + pg_log_error("client %d aborted while executing SQL commands", st->id); st->state = CSTATE_ABORTED; + } break; I understand that the patch is not directly related to --continue-on-error, similar to 0002, and that it aims to improve the error message to indicate that the client was aborted due to some error during readCommandResponse(). However, this message doesn't seem entirely accurate, since the error is not always caused by an SQL command failure itself. For example, it could also be due to a failure of the \gset meta-command. In addition, this fix causes error messages to be emitted twice. For example, if \gset fails, the following similar messages are printed: pgbench: error: client 0 script 0 command 0 query 0: expected one row, got 0 pgbench: error: client 0 aborted while executing SQL commands Even worse, if an unexpected error occurs in readCommandResponse() (i.e., the default case), the following messages are emitted, both indicating that the client was aborted; pgbench: error: client 0 script 0 aborted in command ... query ... pgbench: error: client 0 aborted while executing SQL commands I feel this is a bit redundant. Therefore, if we are to improve these messages to indicate explicitly that the client was aborted, I would suggest modifying the error messages in readCommandResponse() rather than adding a new one in advanceConnectionState(). I've attached patch 0003 incorporating my suggestion. What do you think? Additionally, the patch 0001 includes the fix that was originally part of your proposed 0003, as previously discussed. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-07-13T14:15:24Z
Hi, On 2025/07/10 18:17, Yugo Nagata wrote: > On Wed, 9 Jul 2025 23:58:32 +0900 > Rintaro Ikeda <ikedarintarof@oss.nttdata.com> wrote: > >> Hi, >> >> Thank you for the kind comments. >> >> I've updated the previous patch. > > Thank you for updating the patch! > >>> However, if a large number of errors occur, this could result in a significant increase >>> in stderr output during the benchmark. >>> >>> Users can still notice that something went wrong by checking the “number of other failures” >>> reported after the run, and I assume that in most cases, when --continue-on-error is enabled, >>> users aren’t particularly interested in seeing individual error messages as they happen. >>> >>> It’s true that seeing error messages during the benchmark might be useful in some cases, but >>> the same could be said for serialization or deadlock errors, and that’s exactly what the >>> --verbose-errors option is for. >> >> >> I understand your concern. The condition for calling pg_log_error() was modified >> to reduce stderr output. >> Additionally, an error message was added for cases where some clients aborted >> while executing SQL commands, similar to other code paths that transition to >> st->state = CSTATE_ABORTED, as shown in the example below: >> >> ``` >> pg_log_error("client %d aborted while establishing connection", st->id); >> st->state = CSTATE_ABORTED; >> ``` > > default: > /* anything else is unexpected */ > - pg_log_error("client %d script %d aborted in command %d query %d: %s", > - st->id, st->use_file, st->command, qrynum, > - PQerrorMessage(st->con)); > + if (verbose_errors) > + pg_log_error("client %d script %d aborted in command %d query %d: %s", > + st->id, st->use_file, st->command, qrynum, > + PQerrorMessage(st->con)); > goto error; > } > > Thanks to this fix, error messages caused by SQL errors are now output only when > --verbose-errors is enable. However, the comment describes the condition as "unexpected", > and the message states that the client was "aborted". This does not seems accurate, since > clients are not aborted due to SQL errors when --continue-on-errors is enabled. > > I think the error message should be emitted using commandError() when both > --coneinut-on-errors and --verbose-errors are specified, like this; > > case PGRES_NONFATAL_ERROR: > case PGRES_FATAL_ERROR: > st->estatus = getSQLErrorStatus(PQresultErrorField(res, > PG_DIAG_SQLSTATE)); > if (continue_on_error || canRetryError(st->estatus)) > { > if (verbose_errors) > commandError(st, PQerrorMessage(st->con)); > goto error; > } > /* fall through */ > > In addition, the error message in the "default" case should be shown regardless > of the --verbose-errors since it represents an unexpected situation and should > always reported. > > Finally, I believe this fix should be included in patch 0001 rather than 0003, > as it would be a part of the implementation of --continiue-on-error. > > > As of 0003: > > + { > + pg_log_error("client %d aborted while executing SQL commands", st->id); > st->state = CSTATE_ABORTED; > + } > break; > > I understand that the patch is not directly related to --continue-on-error, similar to 0002, > and that it aims to improve the error message to indicate that the client was aborted due to > some error during readCommandResponse(). > > However, this message doesn't seem entirely accurate, since the error is not always caused > by an SQL command failure itself. For example, it could also be due to a failure of the \gset > meta-command. > > In addition, this fix causes error messages to be emitted twice. For example, if \gset fails, > the following similar messages are printed: > > pgbench: error: client 0 script 0 command 0 query 0: expected one row, got 0 > pgbench: error: client 0 aborted while executing SQL commands > > Even worse, if an unexpected error occurs in readCommandResponse() (i.e., the default case), > the following messages are emitted, both indicating that the client was aborted; > > pgbench: error: client 0 script 0 aborted in command ... query ... > pgbench: error: client 0 aborted while executing SQL commands > > I feel this is a bit redundant. > > Therefore, if we are to improve these messages to indicate explicitly that the client > was aborted, I would suggest modifying the error messages in readCommandResponse() rather > than adding a new one in advanceConnectionState(). > > I've attached patch 0003 incorporating my suggestion. What do you think? Thank you very much for the updated patch! I reviewed 0003 and it looks great - the error message become easier to understand. I noticed one small thing I’d like to discuss. I'm not sure that users clearly understand which aborted in the following error message, the client or the script. > pgbench: error: client 0 script 0 aborted in command ... query ... Since the code path always results in a client abort, I wonder if the following message might be clearer: > pgbench: error: client 0 aborted in script 0 command ... query ... Regards, Rintaro Ikeda -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-07-15T02:16:40Z
Hi, On Sun, 13 Jul 2025 23:15:24 +0900 Rintaro Ikeda <ikedarintarof@oss.nttdata.com> wrote: > I noticed one small thing I’d like to discuss. I'm not sure that users clearly > understand which aborted in the following error message, the client or the script. > > pgbench: error: client 0 script 0 aborted in command ... query ... > > Since the code path always results in a client abort, I wonder if the following > message might be clearer: > > pgbench: error: client 0 aborted in script 0 command ... query ... Indeed, it seems clearer to explicitly state that it is the client that was aborted. I've attached an updated patch that replaces the remaining message mentioned above with a call to commandFailed(). With this change, the output in such situations will now be: "client 0 aborted in command 0 (SQL) of script 0; ...." Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-07-16T12:35:01Z
Hi, On 2025/07/15 11:16, Yugo Nagata wrote: >> I noticed one small thing I’d like to discuss. I'm not sure that users clearly >> understand which aborted in the following error message, the client or the script. >>> pgbench: error: client 0 script 0 aborted in command ... query ... >> >> Since the code path always results in a client abort, I wonder if the following >> message might be clearer: >>> pgbench: error: client 0 aborted in script 0 command ... query ... > > Indeed, it seems clearer to explicitly state that it is the client that > was aborted. > > I've attached an updated patch that replaces the remaining message mentioned > above with a call to commandFailed(). With this change, the output in such > situations will now be: > > "client 0 aborted in command 0 (SQL) of script 0; ...." Thank you for updating the patch! When I executed a custom script that may raise a unique constraint violation, I got the following output: > pgbench: error: client 0 script 0 aborted in command 1 query 0: ERROR: duplicate key value violates unique constraint "test_col2_key" I think we should also change the error message in pg_log_error. I modified the patch v8-0003 as follows: @@ -3383,8 +3383,8 @@ readCommandResponse(CState *st, MetaCommand meta, char *varprefix) default: /* anything else is unexpected */ - pg_log_error("client %d script %d aborted in command %d query %d: %s", - st->id, st->use_file, st->command, qrynum, + pg_log_error("client %d aborted in command %d query %d of script %d: %s", + st->id, st->command, qrynum, st->use_file, PQerrorMessage(st->con)); goto error; } With this change, the output now is like this: > pgbench: error: client 0 aborted in command 1 query 0 of script 0: ERROR: duplicate key value violates unique constraint "test_col2_key" I want hear your thoughts. Also, let me ask one question. In this case, I directly modified your commit in the v8-0003 patch. Is that the right way to update the patch? Regards, Rintaro Ikeda -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-07-16T13:49:57Z
On Wed, 16 Jul 2025 21:35:01 +0900 Rintaro Ikeda <ikedarintarof@oss.nttdata.com> wrote: > Hi, > > On 2025/07/15 11:16, Yugo Nagata wrote: > >> I noticed one small thing I’d like to discuss. I'm not sure that users clearly > >> understand which aborted in the following error message, the client or the script. > >>> pgbench: error: client 0 script 0 aborted in command ... query ... > >> > >> Since the code path always results in a client abort, I wonder if the following > >> message might be clearer: > >>> pgbench: error: client 0 aborted in script 0 command ... query ... > > > > Indeed, it seems clearer to explicitly state that it is the client that > > was aborted. > > > > I've attached an updated patch that replaces the remaining message mentioned > > above with a call to commandFailed(). With this change, the output in such > > situations will now be: > > > > "client 0 aborted in command 0 (SQL) of script 0; ...." > > Thank you for updating the patch! > > When I executed a custom script that may raise a unique constraint violation, I > got the following output: > > pgbench: error: client 0 script 0 aborted in command 1 query 0: ERROR: > duplicate key value violates unique constraint "test_col2_key" I'm sorry. I must have failed to attach the correct patch in my previous post. As a result, patch v8 was actually the same as v7, and the message in question was not modified as intended. > > I think we should also change the error message in pg_log_error. I modified the > patch v8-0003 as follows: > @@ -3383,8 +3383,8 @@ readCommandResponse(CState *st, MetaCommand meta, char > *varprefix) > > default: > /* anything else is unexpected */ > - pg_log_error("client %d script %d aborted in > command %d query %d: %s", > - st->id, st->use_file, > st->command, qrynum, > + pg_log_error("client %d aborted in command %d > query %d of script %d: %s", > + st->id, st->command, > qrynum, st->use_file, > PQerrorMessage(st->con)); > goto error; > } > > With this change, the output now is like this: > > pgbench: error: client 0 aborted in command 1 query 0 of script 0: ERROR: > duplicate key value violates unique constraint "test_col2_key" > > I want hear your thoughts. My idea is to modify this as follows; default: /* anything else is unexpected */ - pg_log_error("client %d script %d aborted in command %d query %d: %s", - st->id, st->use_file, st->command, qrynum, - PQerrorMessage(st->con)); + commandFailed(st, "SQL", PQerrorMessage(st->con)); goto error; } This fix is originally planned to be included in patch v8, but was missed. It is now included in the attached patch, v10. With this change, the output becomes: pgbench: error: client 0 aborted in command 0 (SQL) of script 0; ERROR: duplicate key value violates unique constraint "t2_pkey" Although there is a slight difference, the message is essentially the same as your proposal. Also, I believe the use of commandFailed() makes the code simpler and more consistent. What do you think? > Also, let me ask one question. In this case, I directly modified your commit in > the v8-0003 patch. Is that the right way to update the patch? I’m not sure if that’s the best way, but I think modifying the patch directly is a valid way to propose an alternative approach during discussion, as long as the original patch is respected. It can often help clarify suggestions. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-07-18T08:07:53Z
Hi, On 2025/07/16 22:49, Yugo Nagata wrote: >> I think we should also change the error message in pg_log_error. I modified the >> patch v8-0003 as follows: >> @@ -3383,8 +3383,8 @@ readCommandResponse(CState *st, MetaCommand meta, char >> *varprefix) >> >> default: >> /* anything else is unexpected */ >> - pg_log_error("client %d script %d aborted in >> command %d query %d: %s", >> - st->id, st->use_file, >> st->command, qrynum, >> + pg_log_error("client %d aborted in command %d >> query %d of script %d: %s", >> + st->id, st->command, >> qrynum, st->use_file, >> PQerrorMessage(st->con)); >> goto error; >> } >> >> With this change, the output now is like this: >>> pgbench: error: client 0 aborted in command 1 query 0 of script 0: ERROR: >> duplicate key value violates unique constraint "test_col2_key" >> >> I want hear your thoughts. > > My idea is to modify this as follows; > > default: > /* anything else is unexpected */ > - pg_log_error("client %d script %d aborted in command %d query %d: %s", > - st->id, st->use_file, st->command, qrynum, > - PQerrorMessage(st->con)); > + commandFailed(st, "SQL", PQerrorMessage(st->con)); > goto error; > } > > This fix is originally planned to be included in patch v8, but was missed. > It is now included in the attached patch, v10. > > With this change, the output becomes: > > pgbench: error: client 0 aborted in command 0 (SQL) of script 0; > ERROR: duplicate key value violates unique constraint "t2_pkey" > > Although there is a slight difference, the message is essentially the same as > your proposal. Also, I believe the use of commandFailed() makes the code simpler > and more consistent. > > What do you think? > Thank you for the new patch! I think Nagata-san's v10 patch is a clear improvement over my v9 patch. I'm happy with the changes. >> Also, let me ask one question. In this case, I directly modified your commit in >> the v8-0003 patch. Is that the right way to update the patch? > > I’m not sure if that’s the best way, but I think modifying the patch directly is a > valid way to propose an alternative approach during discussion, as long as the original > patch is respected. It can often help clarify suggestions. I understand that. Thank you. Regards, Rintaro Ikeda -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-07-22T08:49:49Z
On Fri, 18 Jul 2025 17:07:53 +0900 Rintaro Ikeda <ikedarintarof@oss.nttdata.com> wrote: > Hi, > > On 2025/07/16 22:49, Yugo Nagata wrote: > >> I think we should also change the error message in pg_log_error. I modified the > >> patch v8-0003 as follows: > >> @@ -3383,8 +3383,8 @@ readCommandResponse(CState *st, MetaCommand meta, char > >> *varprefix) > >> > >> default: > >> /* anything else is unexpected */ > >> - pg_log_error("client %d script %d aborted in > >> command %d query %d: %s", > >> - st->id, st->use_file, > >> st->command, qrynum, > >> + pg_log_error("client %d aborted in command %d > >> query %d of script %d: %s", > >> + st->id, st->command, > >> qrynum, st->use_file, > >> PQerrorMessage(st->con)); > >> goto error; > >> } > >> > >> With this change, the output now is like this: > >>> pgbench: error: client 0 aborted in command 1 query 0 of script 0: ERROR: > >> duplicate key value violates unique constraint "test_col2_key" > >> > >> I want hear your thoughts. > > > > My idea is to modify this as follows; > > > > default: > > /* anything else is unexpected */ > > - pg_log_error("client %d script %d aborted in command %d query %d: %s", > > - st->id, st->use_file, st->command, qrynum, > > - PQerrorMessage(st->con)); > > + commandFailed(st, "SQL", PQerrorMessage(st->con)); > > goto error; > > } > > > > This fix is originally planned to be included in patch v8, but was missed. > > It is now included in the attached patch, v10. > > > > With this change, the output becomes: > > > > pgbench: error: client 0 aborted in command 0 (SQL) of script 0; > > ERROR: duplicate key value violates unique constraint "t2_pkey" > > > > Although there is a slight difference, the message is essentially the same as > > your proposal. Also, I believe the use of commandFailed() makes the code simpler > > and more consistent. > > > > What do you think? > > > > Thank you for the new patch! I think Nagata-san's v10 patch is a clear > improvement over my v9 patch. I'm happy with the changes. Thank you. I believe the patches implement the expected behavior, include appropriste doc and test modification, are in good shape overall, so if there are no objections, I'll mark this as Read-for-Committer. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-07-24T03:44:40Z
On Tue, 22 Jul 2025 17:49:49 +0900 Yugo Nagata <nagata@sraoss.co.jp> wrote: > On Fri, 18 Jul 2025 17:07:53 +0900 > Rintaro Ikeda <ikedarintarof@oss.nttdata.com> wrote: > > > Hi, > > > > On 2025/07/16 22:49, Yugo Nagata wrote: > > >> I think we should also change the error message in pg_log_error. I modified the > > >> patch v8-0003 as follows: > > >> @@ -3383,8 +3383,8 @@ readCommandResponse(CState *st, MetaCommand meta, char > > >> *varprefix) > > >> > > >> default: > > >> /* anything else is unexpected */ > > >> - pg_log_error("client %d script %d aborted in > > >> command %d query %d: %s", > > >> - st->id, st->use_file, > > >> st->command, qrynum, > > >> + pg_log_error("client %d aborted in command %d > > >> query %d of script %d: %s", > > >> + st->id, st->command, > > >> qrynum, st->use_file, > > >> PQerrorMessage(st->con)); > > >> goto error; > > >> } > > >> > > >> With this change, the output now is like this: > > >>> pgbench: error: client 0 aborted in command 1 query 0 of script 0: ERROR: > > >> duplicate key value violates unique constraint "test_col2_key" > > >> > > >> I want hear your thoughts. > > > > > > My idea is to modify this as follows; > > > > > > default: > > > /* anything else is unexpected */ > > > - pg_log_error("client %d script %d aborted in command %d query %d: %s", > > > - st->id, st->use_file, st->command, qrynum, > > > - PQerrorMessage(st->con)); > > > + commandFailed(st, "SQL", PQerrorMessage(st->con)); > > > goto error; > > > } > > > > > > This fix is originally planned to be included in patch v8, but was missed. > > > It is now included in the attached patch, v10. > > > > > > With this change, the output becomes: > > > > > > pgbench: error: client 0 aborted in command 0 (SQL) of script 0; > > > ERROR: duplicate key value violates unique constraint "t2_pkey" > > > > > > Although there is a slight difference, the message is essentially the same as > > > your proposal. Also, I believe the use of commandFailed() makes the code simpler > > > and more consistent. > > > > > > What do you think? > > > > > > > Thank you for the new patch! I think Nagata-san's v10 patch is a clear > > improvement over my v9 patch. I'm happy with the changes. > > Thank you. > > I believe the patches implement the expected behavior, include appropriste doc and test > modification, are in good shape overall, so if there are no objections, > I'll mark this as Read-for-Committer. I've updated the CF status to Ready for Committer. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Jakub Wartak <jakub.wartak@enterprisedb.com> — 2025-09-16T08:34:03Z
On Thu, Jul 24, 2025 at 5:44 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > I believe the patches implement the expected behavior, include appropriste doc and test > > modification, are in good shape overall, so if there are no objections, > > I'll mark this as Read-for-Committer. > > I've updated the CF status to Ready for Committer. Thanks for working on it! As Matthias, Dilip, Srinath and many others pointed out it would be a very nice and helpful addition to pgbench. I've just used it out of necessity and it worked as advertised for me and it even adds a cool-looking "XXX failed" when used with -P progress meter: progress: 1.0 s, 0.0 tps, lat 0.000 ms stddev 0.000, 3854 failed progress: 2.0 s, 0.0 tps, lat 0.000 ms stddev 0.000, 3796 failed -J.
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-09-17T16:52:46Z
On Tue, Sep 16, 2025 at 5:34 PM Jakub Wartak <jakub.wartak@enterprisedb.com> wrote: > > On Thu, Jul 24, 2025 at 5:44 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > > > > I believe the patches implement the expected behavior, include appropriste doc and test > > > modification, are in good shape overall, so if there are no objections, > > > I'll mark this as Read-for-Committer. > > > > I've updated the CF status to Ready for Committer. Since this patch is marked as ready for committer, I've started reviewing it. The patch basically looks good to me. + the client is aborted. However, if the --continue-on-error option is specified, "--continue-on-error" should be enclosed in <option> tags. + without completing the last transaction. By default, if execution of an SQL or meta command fails for reasons other than serialization or deadlock errors, <snip> + the client is aborted. However, if the --continue-on-error option is specified, + the client does not abort and proceeds to the next transaction regardless of + the error. These cases are reported as "other failures" in the output. This explanation can be read as if --continue-on-error allows the client to proceed to the next transaction even when mata command (not SQL) fails, but that is not correct, right? If so, the description should be updated to make it clear that only SQL errors are affected, while meta command failures are not. +$node->pgbench( + '-t 10 --continue-on-error --failures-detailed', Isn't it better to specify also -n option to skip unnecessary VACUUM and speed the test up? + 'test --continue-on-error', + { + '002_continue_on_error' => q{ Regarding the test file name, perhaps 001 would be a better prefix than 002, since other tests in 001_pgbench_with_server.pl use 001 as the prefix. + insert into unique_table values 0; This INSERT causes a syntax error. Was this intentional? If the intention was to test unique constraint violations, it should instead be INSERT INTO unique_table VALUES (0);. To further improve the test, it might also be useful to mix successful and failed transactions in the --continue-on-error case. For example, the following change would result in one successful transaction and nine failures: ----------------------------- $node->safe_psql('postgres', - 'CREATE TABLE unique_table(i int unique);' . 'INSERT INTO unique_table VALUES (0);'); + 'CREATE TABLE unique_table(i int unique);'); $node->pgbench( '-t 10 --continue-on-error --failures-detailed', 0, [ - qr{processed: 0/10\b}, - qr{other failures: 10\b} + qr{processed: 1/10\b}, + qr{other failures: 9\b} ----------------------------- Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-18T01:22:18Z
On Thu, 18 Sep 2025 01:52:46 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Tue, Sep 16, 2025 at 5:34 PM Jakub Wartak > <jakub.wartak@enterprisedb.com> wrote: > > > > On Thu, Jul 24, 2025 at 5:44 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > > > > > > > I believe the patches implement the expected behavior, include appropriste doc and test > > > > modification, are in good shape overall, so if there are no objections, > > > > I'll mark this as Read-for-Committer. > > > > > > I've updated the CF status to Ready for Committer. > > Since this patch is marked as ready for committer, I've started reviewing it. > The patch basically looks good to me. > > > + the client is aborted. However, if the --continue-on-error option > is specified, > > "--continue-on-error" should be enclosed in <option> tags. +1 > + without completing the last transaction. By default, if execution of an SQL > or meta command fails for reasons other than serialization or > deadlock errors, > <snip> > + the client is aborted. However, if the --continue-on-error option > is specified, > + the client does not abort and proceeds to the next transaction regardless of > + the error. These cases are reported as "other failures" in the output. > > This explanation can be read as if --continue-on-error allows the client to > proceed to the next transaction even when mata command (not SQL) fails, > but that is not correct, right? If so, the description should be updated to > make it clear that only SQL errors are affected, while meta command failures > are not. That makes sense. How about rewriting this like: However, if the --continue-on-error option is specified and the error occurs in an SQL command, the client does not abort and proceeds to the next transaction regardless of the error. These cases are reported as "other failures" in the output. Note that if the error occurs in a meta-command, the client will still abort even when this option is specified. > +$node->pgbench( > + '-t 10 --continue-on-error --failures-detailed', > > Isn't it better to specify also -n option to skip unnecessary VACUUM and > speed the test up? +1 > + 'test --continue-on-error', > + { > + '002_continue_on_error' => q{ > > Regarding the test file name, perhaps 001 would be a better prefix than 002, > since other tests in 001_pgbench_with_server.pl use 001 as the prefix. Right. This filename is shown in the “transaction type:” field of the results when the test fails, so it should be aligned with the test file name. > + insert into unique_table values 0; > > This INSERT causes a syntax error. Was this intentional? If the intention was > to test unique constraint violations, it should instead be > INSERT INTO unique_table VALUES (0);. This was clearly unintentional. I happened to overlook it during my review. > To further improve the test, it might also be useful to mix successful and > failed transactions in the --continue-on-error case. For example, > the following change would result in one successful transaction and > nine failures: > > ----------------------------- > $node->safe_psql('postgres', > - 'CREATE TABLE unique_table(i int unique);' . 'INSERT INTO > unique_table VALUES (0);'); > + 'CREATE TABLE unique_table(i int unique);'); > > $node->pgbench( > '-t 10 --continue-on-error --failures-detailed', > 0, > [ > - qr{processed: 0/10\b}, > - qr{other failures: 10\b} > + qr{processed: 1/10\b}, > + qr{other failures: 9\b} > ----------------------------- +1 This makes the purpose of the test clearer. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-09-18T05:37:29Z
On Thu, Sep 18, 2025 at 10:22 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > That makes sense. How about rewriting this like: > > However, if the --continue-on-error option is specified and the error occurs in > an SQL command, the client does not abort and proceeds to the next > transaction regardless of the error. These cases are reported as "other failures" > in the output. Note that if the error occurs in a meta-command, the client will > still abort even when this option is specified. How about phrasing it like this, based on your version? ---------------------------- A client's run is aborted in case of a serious error; for example, the connection with the database server was lost or the end of script was reached without completing the last transaction. The client also aborts if a meta-command fails, or if an SQL command fails for reasons other than serialization or deadlock errors when --continue-on-error is not specified. With --continue-on-error, the client does not abort on such SQL errors and instead proceeds to the next transaction. These cases are reported as "other failures" in the output. If the error occurs in a meta-command, however, the client still aborts even when this option is specified. ---------------------------- Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-18T07:20:17Z
On Thu, 18 Sep 2025 14:37:29 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Thu, Sep 18, 2025 at 10:22 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > That makes sense. How about rewriting this like: > > > > However, if the --continue-on-error option is specified and the error occurs in > > an SQL command, the client does not abort and proceeds to the next > > transaction regardless of the error. These cases are reported as "other failures" > > in the output. Note that if the error occurs in a meta-command, the client will > > still abort even when this option is specified. > > How about phrasing it like this, based on your version? > > ---------------------------- > A client's run is aborted in case of a serious error; for example, the > connection with the database server was lost or the end of script was reached > without completing the last transaction. The client also aborts > if a meta-command fails, or if an SQL command fails for reasons other than > serialization or deadlock errors when --continue-on-error is not specified. > With --continue-on-error, the client does not abort on such SQL errors > and instead proceeds to the next transaction. These cases are reported > as "other failures" in the output. If the error occurs in a meta-command, > however, the client still aborts even when this option is specified. > ---------------------------- I'm fine with that. This version is clearer. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-09-19T02:43:28Z
On Thu, Sep 18, 2025 at 4:20 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > On Thu, 18 Sep 2025 14:37:29 +0900 > Fujii Masao <masao.fujii@gmail.com> wrote: > > > On Thu, Sep 18, 2025 at 10:22 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > That makes sense. How about rewriting this like: > > > > > > However, if the --continue-on-error option is specified and the error occurs in > > > an SQL command, the client does not abort and proceeds to the next > > > transaction regardless of the error. These cases are reported as "other failures" > > > in the output. Note that if the error occurs in a meta-command, the client will > > > still abort even when this option is specified. > > > > How about phrasing it like this, based on your version? > > > > ---------------------------- > > A client's run is aborted in case of a serious error; for example, the > > connection with the database server was lost or the end of script was reached > > without completing the last transaction. The client also aborts > > if a meta-command fails, or if an SQL command fails for reasons other than > > serialization or deadlock errors when --continue-on-error is not specified. > > With --continue-on-error, the client does not abort on such SQL errors > > and instead proceeds to the next transaction. These cases are reported > > as "other failures" in the output. If the error occurs in a meta-command, > > however, the client still aborts even when this option is specified. > > ---------------------------- > > I'm fine with that. This version is clearer. Thanks for checking! Also I'd like to share the review comments for 0002 and 0003. Regarding 0002: - TSTATUS_OTHER_ERROR, + TSTATUS_UNKNOWN_ERROR, You did this rename to avoid confusion with other_sql_errors. I see the intention, but I'm not sure if this concern is really valid and if the rename adds much value. Also, TSTATUS_UNKNOWN_ERROR might be mistakenly assumed to be related to PQTRANS_UNKNOWN, even though they aren't related... But if we agree with this change, I think it should be folded into 0001, since there's no strong reason to keep it separate. Regarding 0003: - pg_log_error("client %d script %d command %d query %d: expected one row, got %d", - st->id, st->use_file, st->command, qrynum, 0); + commandFailed(st, "gset", psprintf("expected one row, got %d", 0)); The change to use commandFailed() seems to remove the "query %d" detail that the current pg_log_error() call reports. Is it OK to lose that information? Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-09-19T10:21:29Z
On Fri, Sep 19, 2025 at 11:43 AM Fujii Masao <masao.fujii@gmail.com> wrote: > > On Thu, Sep 18, 2025 at 4:20 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > On Thu, 18 Sep 2025 14:37:29 +0900 > > Fujii Masao <masao.fujii@gmail.com> wrote: > > > > > On Thu, Sep 18, 2025 at 10:22 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > That makes sense. How about rewriting this like: > > > > > > > > However, if the --continue-on-error option is specified and the error occurs in > > > > an SQL command, the client does not abort and proceeds to the next > > > > transaction regardless of the error. These cases are reported as "other failures" > > > > in the output. Note that if the error occurs in a meta-command, the client will > > > > still abort even when this option is specified. > > > > > > How about phrasing it like this, based on your version? > > > > > > ---------------------------- > > > A client's run is aborted in case of a serious error; for example, the > > > connection with the database server was lost or the end of script was reached > > > without completing the last transaction. The client also aborts > > > if a meta-command fails, or if an SQL command fails for reasons other than > > > serialization or deadlock errors when --continue-on-error is not specified. > > > With --continue-on-error, the client does not abort on such SQL errors > > > and instead proceeds to the next transaction. These cases are reported > > > as "other failures" in the output. If the error occurs in a meta-command, > > > however, the client still aborts even when this option is specified. > > > ---------------------------- > > > > I'm fine with that. This version is clearer. > > Thanks for checking! I've updated the 0001 patch based on the comments. The revised version is attached. While testing, I found that running pgbench with --continue-on-error and pipeline mode triggers the following assertion failure. Could this be a bug in the patch? --------------------------------------------------- $ cat pipeline.pgbench \startpipeline DO $$ BEGIN PERFORM pg_sleep(3); PERFORM pg_terminate_backend(pg_backend_pid()); END $$; \endpipeline $ pgbench -n --debug --verbose-errors -f pipeline.pgbench -c 2 -t 4 -M extended --continue-on-error ... Assertion failed: (sql_script[st->use_file].commands[st->command]->type == 1), function commandError, file pgbench.c, line 3081. Abort trap: 6 --------------------------------------------------- When I ran the same command without --continue-on-error, the assertion failure did not occur. Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-19T11:56:44Z
On Fri, 19 Sep 2025 11:43:28 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Thu, Sep 18, 2025 at 4:20 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > On Thu, 18 Sep 2025 14:37:29 +0900 > > Fujii Masao <masao.fujii@gmail.com> wrote: > > > > > On Thu, Sep 18, 2025 at 10:22 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > That makes sense. How about rewriting this like: > > > > > > > > However, if the --continue-on-error option is specified and the error occurs in > > > > an SQL command, the client does not abort and proceeds to the next > > > > transaction regardless of the error. These cases are reported as "other failures" > > > > in the output. Note that if the error occurs in a meta-command, the client will > > > > still abort even when this option is specified. > > > > > > How about phrasing it like this, based on your version? > > > > > > ---------------------------- > > > A client's run is aborted in case of a serious error; for example, the > > > connection with the database server was lost or the end of script was reached > > > without completing the last transaction. The client also aborts > > > if a meta-command fails, or if an SQL command fails for reasons other than > > > serialization or deadlock errors when --continue-on-error is not specified. > > > With --continue-on-error, the client does not abort on such SQL errors > > > and instead proceeds to the next transaction. These cases are reported > > > as "other failures" in the output. If the error occurs in a meta-command, > > > however, the client still aborts even when this option is specified. > > > ---------------------------- > > > > I'm fine with that. This version is clearer. > > Thanks for checking! > > > Also I'd like to share the review comments for 0002 and 0003. > > Regarding 0002: > > - TSTATUS_OTHER_ERROR, > + TSTATUS_UNKNOWN_ERROR, > > You did this rename to avoid confusion with other_sql_errors. > I see the intention, but I'm not sure if this concern is really valid > and if the rename adds much value. Also, TSTATUS_UNKNOWN_ERROR > might be mistakenly assumed to be related to PQTRANS_UNKNOWN, > even though they aren't related... I don’t have a strong opinion on this, but I think TSTATUS_* is slightly related to PQTRANS_*, since getTransactionStatus() determines the TSTATUS value based on PQTRANS. There is no one-to-one relationship, of course, but it is more related than ESTATUS_OTHER_SQL_ERROR, which is entirely separate. > But if we agree with this change, I think it should be folded into 0001, > since there's no strong reason to keep it separate. +1 I personally don't care if ommiting this change, but I would like to wait for Ikeda-san's response because he is the author of these two patches. > Regarding 0003: > > - pg_log_error("client %d script %d command %d query %d: expected one > row, got %d", > - st->id, st->use_file, st->command, qrynum, 0); > + commandFailed(st, "gset", psprintf("expected one row, got %d", 0)); > > The change to use commandFailed() seems to remove > the "query %d" detail that the current pg_log_error() call reports. > Is it OK to lose that information? "qrynum" is the index of SQL queries combined by "\;", but reporting it in \gset errors is almost useless, since \gset can only be applied to the last query of a compound query. So I think it’s fine to commit this. That said, it might still be useful for debugging when an internal error like the following occurs (mainly for developers rather than users): /* internal error */ commandFailed(st, cmd, psprintf("error storing into variable %s", varname)); For that case, I’d be fine with adding information like this: /* internal error */ commandFailed(st, cmd, psprintf("error storing into variable %s, at query %d", varname, qrynum)); Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-19T15:21:19Z
On Fri, 19 Sep 2025 19:21:29 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Fri, Sep 19, 2025 at 11:43 AM Fujii Masao <masao.fujii@gmail.com> wrote: > > > > On Thu, Sep 18, 2025 at 4:20 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > > > On Thu, 18 Sep 2025 14:37:29 +0900 > > > Fujii Masao <masao.fujii@gmail.com> wrote: > > > > > > > On Thu, Sep 18, 2025 at 10:22 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > > That makes sense. How about rewriting this like: > > > > > > > > > > However, if the --continue-on-error option is specified and the error occurs in > > > > > an SQL command, the client does not abort and proceeds to the next > > > > > transaction regardless of the error. These cases are reported as "other failures" > > > > > in the output. Note that if the error occurs in a meta-command, the client will > > > > > still abort even when this option is specified. > > > > > > > > How about phrasing it like this, based on your version? > > > > > > > > ---------------------------- > > > > A client's run is aborted in case of a serious error; for example, the > > > > connection with the database server was lost or the end of script was reached > > > > without completing the last transaction. The client also aborts > > > > if a meta-command fails, or if an SQL command fails for reasons other than > > > > serialization or deadlock errors when --continue-on-error is not specified. > > > > With --continue-on-error, the client does not abort on such SQL errors > > > > and instead proceeds to the next transaction. These cases are reported > > > > as "other failures" in the output. If the error occurs in a meta-command, > > > > however, the client still aborts even when this option is specified. > > > > ---------------------------- > > > > > > I'm fine with that. This version is clearer. > > > > Thanks for checking! > > I've updated the 0001 patch based on the comments. > The revised version is attached. Thank you for updating the patch. > > While testing, I found that running pgbench with --continue-on-error and > pipeline mode triggers the following assertion failure. Could this be > a bug in the patch? > > --------------------------------------------------- > $ cat pipeline.pgbench > \startpipeline > DO $$ > BEGIN > PERFORM pg_sleep(3); > PERFORM pg_terminate_backend(pg_backend_pid()); > END $$; > \endpipeline > > $ pgbench -n --debug --verbose-errors -f pipeline.pgbench -c 2 -t 4 -M > extended --continue-on-error > ... > Assertion failed: > (sql_script[st->use_file].commands[st->command]->type == 1), function > commandError, file pgbench.c, line 3081. > Abort trap: 6 > --------------------------------------------------- > > When I ran the same command without --continue-on-error, > the assertion failure did not occur. I think this bug was introduced by commit 4a39f87acd6e, which enabled pgbench to retry and added the --verbose-errors option, rather than by this patch itself. The assertion failure occurs in commandError(), which is called to report an error when it can be retried (i.e., serializable failure or deadlock), or when --continue-on-error is used after this patch. Assert(sql_script[st->use_file].commands[st->command]->type == SQL_COMMAND); This assumes the error is always detected during SQL command execution, but that’s not correct, since in pipeline mode, the error can be detected when a \endpipeline meta-command is executed. $ cat deadlock.sql \startpipeline begin; lock b; lock a; end; \endpipeline $ cat deadlock2.sql \startpipeline begin; lock a; lock b; end; \endpipeline $ pgbench --verbose-errors -f deadlock.sql -f deadlock2.sql -c 2 -T 3 -M extended pgbench (19devel) starting vacuum...end. pgbench: pgbench.c:3062: commandError: Assertion `sql_script[st->use_file].commands[st->command]->type == 1' failed. Although one option would be to remove this assertion, if we prefer to keep it, the attached patch fixes the issue. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-09-20T12:58:04Z
Thank you for reviewing the patches. On 2025/09/19 20:56, Yugo Nagata wrote: >>>> A client's run is aborted in case of a serious error; for example, the >>>> connection with the database server was lost or the end of script was reached >>>> without completing the last transaction. The client also aborts >>>> if a meta-command fails, or if an SQL command fails for reasons other than >>>> serialization or deadlock errors when --continue-on-error is not specified. >>>> With --continue-on-error, the client does not abort on such SQL errors >>>> and instead proceeds to the next transaction. These cases are reported >>>> as "other failures" in the output. If the error occurs in a meta-command, >>>> however, the client still aborts even when this option is specified. >>>> ---------------------------- >>> >>> I'm fine with that. This version is clearer. I also agree with this. >> >> Also I'd like to share the review comments for 0002 and 0003. >> >> Regarding 0002: >> >> - TSTATUS_OTHER_ERROR, >> + TSTATUS_UNKNOWN_ERROR, >> >> You did this rename to avoid confusion with other_sql_errors. >> I see the intention, but I'm not sure if this concern is really valid >> and if the rename adds much value. Also, TSTATUS_UNKNOWN_ERROR >> might be mistakenly assumed to be related to PQTRANS_UNKNOWN, >> even though they aren't related... > > I don’t have a strong opinion on this, but I think TSTATUS_* is slightly > related to PQTRANS_*, since getTransactionStatus() determines the TSTATUS > value based on PQTRANS. There is no one-to-one relationship, of course, > but it is more related than ESTATUS_OTHER_SQL_ERROR, which is entirely > separate. > >> But if we agree with this change, I think it should be folded into 0001, >> since there's no strong reason to keep it separate. > > +1 > > I personally don't care if ommiting this change, but I would like to wait > for Ikeda-san's response because he is the author of these two patches. > The points you both raise make sense to me. Changing the macro name is not important for the purpose of the patch, so I now feel it would be reasonable to drop patch 0002. Regards, Rintaro Ikeda
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-09-22T02:56:31Z
On Sat, Sep 20, 2025 at 12:21 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > While testing, I found that running pgbench with --continue-on-error and > > pipeline mode triggers the following assertion failure. Could this be > > a bug in the patch? > > > > --------------------------------------------------- > > $ cat pipeline.pgbench > > \startpipeline > > DO $$ > > BEGIN > > PERFORM pg_sleep(3); > > PERFORM pg_terminate_backend(pg_backend_pid()); > > END $$; > > \endpipeline > > > > $ pgbench -n --debug --verbose-errors -f pipeline.pgbench -c 2 -t 4 -M > > extended --continue-on-error > > ... > > Assertion failed: > > (sql_script[st->use_file].commands[st->command]->type == 1), function > > commandError, file pgbench.c, line 3081. > > Abort trap: 6 > > --------------------------------------------------- > > > > When I ran the same command without --continue-on-error, > > the assertion failure did not occur. > > I think this bug was introduced by commit 4a39f87acd6e, which enabled pgbench > to retry and added the --verbose-errors option, rather than by this patch itself. > > The assertion failure occurs in commandError(), which is called to report an error when > it can be retried (i.e., serializable failure or deadlock), or when --continue-on-error > is used after this patch. > > Assert(sql_script[st->use_file].commands[st->command]->type == SQL_COMMAND); > > This assumes the error is always detected during SQL command execution, but > that’s not correct, since in pipeline mode, the error can be detected when > a \endpipeline meta-command is executed. > > $ cat deadlock.sql > \startpipeline > begin; > lock b; > lock a; > end; > \endpipeline > > $ cat deadlock2.sql > \startpipeline > begin; > lock a; > lock b; > end; > \endpipeline > > $ pgbench --verbose-errors -f deadlock.sql -f deadlock2.sql -c 2 -T 3 -M extended > pgbench (19devel) > starting vacuum...end. > pgbench: pgbench.c:3062: commandError: Assertion `sql_script[st->use_file].commands[st->command]->type == 1' failed. > > Although one option would be to remove this assertion, if we prefer to keep it, > the attached patch fixes the issue. Thanks for the analysis and the patch! I think we should fix the issue rather than just removing the assertion. I'd like to apply your patch with the following source comment: --------------------------- Errors should only be detected during an SQL command or the \endpipeline meta command. Any other case triggers an assertion failure. -------------------------- With your patch and the continue-on-error patches, running the same pgbench command I used to reproduce the assertion failure upthread causes pgbench to hang. From my analysis, it enters an infinite loop in discardUntilSync(). That loop waits for PGRES_PIPELINE_SYNC, but since the connection has already been closed, it never arrives, leaving pgbench stuck. Could this also happen without the continue-on-error patch, or is it a new bug introduced by it? Either way, it seems pgbench needs to exit the loop when the result status is PGRES_FATAL_ERROR. Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-09-22T02:59:23Z
On Sat, Sep 20, 2025 at 9:58 PM Rintaro Ikeda <ikedarintarof@oss.nttdata.com> wrote: > The points you both raise make sense to me. > Changing the macro name is not important for the purpose of the patch, so I now > feel it would be reasonable to drop patch 0002. Thanks for your thoughts! So let's focus on the 0001 patch for now. Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-09-23T02:58:29Z
Hi, On 2025/09/22 11:56, Fujii Masao wrote: > On Sat, Sep 20, 2025 at 12:21 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: >>> While testing, I found that running pgbench with --continue-on-error and >>> pipeline mode triggers the following assertion failure. Could this be >>> a bug in the patch? >>> >>> --------------------------------------------------- >>> $ cat pipeline.pgbench >>> \startpipeline >>> DO $$ >>> BEGIN >>> PERFORM pg_sleep(3); >>> PERFORM pg_terminate_backend(pg_backend_pid()); >>> END $$; >>> \endpipeline >>> >>> $ pgbench -n --debug --verbose-errors -f pipeline.pgbench -c 2 -t 4 -M >>> extended --continue-on-error >>> ... >>> Assertion failed: >>> (sql_script[st->use_file].commands[st->command]->type == 1), function >>> commandError, file pgbench.c, line 3081. >>> Abort trap: 6 >>> --------------------------------------------------- >>> >>> When I ran the same command without --continue-on-error, >>> the assertion failure did not occur. >> >> I think this bug was introduced by commit 4a39f87acd6e, which enabled pgbench >> to retry and added the --verbose-errors option, rather than by this patch itself. >> >> The assertion failure occurs in commandError(), which is called to report an error when >> it can be retried (i.e., serializable failure or deadlock), or when --continue-on-error >> is used after this patch. >> >> Assert(sql_script[st->use_file].commands[st->command]->type == SQL_COMMAND); >> >> This assumes the error is always detected during SQL command execution, but >> that’s not correct, since in pipeline mode, the error can be detected when >> a \endpipeline meta-command is executed. >> >> $ cat deadlock.sql >> \startpipeline >> begin; >> lock b; >> lock a; >> end; >> \endpipeline >> >> $ cat deadlock2.sql >> \startpipeline >> begin; >> lock a; >> lock b; >> end; >> \endpipeline >> >> $ pgbench --verbose-errors -f deadlock.sql -f deadlock2.sql -c 2 -T 3 -M extended >> pgbench (19devel) >> starting vacuum...end. >> pgbench: pgbench.c:3062: commandError: Assertion `sql_script[st->use_file].commands[st->command]->type == 1' failed. >> >> Although one option would be to remove this assertion, if we prefer to keep it, >> the attached patch fixes the issue. > > Thanks for the analysis and the patch! > > I think we should fix the issue rather than just removing the assertion. > I'd like to apply your patch with the following source comment: > > --------------------------- > Errors should only be detected during an SQL command or the \endpipeline > meta command. Any other case triggers an assertion failure. > -------------------------- > > > With your patch and the continue-on-error patches, running the same pgbench > command I used to reproduce the assertion failure upthread causes pgbench > to hang. From my analysis, it enters an infinite loop in discardUntilSync(). > That loop waits for PGRES_PIPELINE_SYNC, but since the connection has already > been closed, it never arrives, leaving pgbench stuck. > > Could this also happen without the continue-on-error patch, or is it a new bug > introduced by it? Either way, it seems pgbench needs to exit the loop when > the result status is PGRES_FATAL_ERROR. > Thank you for the analysis and the patches. I think the issue is a new bug because we have transitioned to CSTATE_ABORT immediately after queries failed, without executing discardUntilSync(). I've attached a patch that fixes the assertion error. The content of v1 patch by Mr. Nagata is also included. I would appreciate it if you review my patch. Regards, Rintaro Ikeda
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-09-24T17:19:27Z
On Tue, Sep 23, 2025 at 11:58 AM Rintaro Ikeda <ikedarintarof@oss.nttdata.com> wrote: > I think the issue is a new bug because we have transitioned to CSTATE_ABORT > immediately after queries failed, without executing discardUntilSync(). If so, the fix in discardUntilSync() should be part of the continue-on-error patch. The assertion failure fix should be a separate patch, since only that needs to be backpatched (the failure can also occur in back branches). > I've attached a patch that fixes the assertion error. The content of v1 patch by > Mr. Nagata is also included. I would appreciate it if you review my patch. + if (received_sync == true) For boolean flags, we usually just use the variable itself instead of "== true/false". + switch (PQresultStatus(res)) + { + case PGRES_PIPELINE_SYNC: + received_sync = true; In the PGRES_PIPELINE_SYNC case, PQclear(res) isn't called but should be. + case PGRES_FATAL_ERROR: + PQclear(res); + goto done; I don't think we need goto here. How about this instead? ----------------------- @@ -3525,11 +3525,18 @@ discardUntilSync(CState *st) * results have been discarded. */ st->num_syncs = 0; - PQclear(res); break; } + /* + * Stop receiving further results if PGRES_FATAL_ERROR is returned + * (e.g., due to a connection failure) before PGRES_PIPELINE_SYNC, + * since PGRES_PIPELINE_SYNC will never arrive. + */ + else if (PQresultStatus(res) == PGRES_FATAL_ERROR) + break; PQclear(res); } + PQclear(res); /* exit pipeline */ if (PQexitPipelineMode(st->con) != 1) ----------------------- Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-25T02:09:40Z
On Thu, 25 Sep 2025 02:19:27 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Tue, Sep 23, 2025 at 11:58 AM Rintaro Ikeda > <ikedarintarof@oss.nttdata.com> wrote: > > I think the issue is a new bug because we have transitioned to CSTATE_ABORT > > immediately after queries failed, without executing discardUntilSync(). Agreed. > If so, the fix in discardUntilSync() should be part of the continue-on-error > patch. The assertion failure fix should be a separate patch, since only > that needs to be backpatched (the failure can also occur in back branches). +1 > > > I've attached a patch that fixes the assertion error. The content of v1 patch by > > Mr. Nagata is also included. I would appreciate it if you review my patch. > + switch (PQresultStatus(res)) > + { > + case PGRES_PIPELINE_SYNC: > + received_sync = true; > > In the PGRES_PIPELINE_SYNC case, PQclear(res) isn't called but should be. > > + case PGRES_FATAL_ERROR: > + PQclear(res); > + goto done; > > I don't think we need goto here. How about this instead? > > ----------------------- > @@ -3525,11 +3525,18 @@ discardUntilSync(CState *st) > * results have been discarded. > */ > st->num_syncs = 0; > - PQclear(res); > break; > } > + /* > + * Stop receiving further results if PGRES_FATAL_ERROR > is returned > + * (e.g., due to a connection failure) before > PGRES_PIPELINE_SYNC, > + * since PGRES_PIPELINE_SYNC will never arrive. > + */ > + else if (PQresultStatus(res) == PGRES_FATAL_ERROR) > + break; > PQclear(res); > } > + PQclear(res); > > /* exit pipeline */ > if (PQexitPipelineMode(st->con) != 1) > ----------------------- I think Fujii-san's version is better because Ikeda-san's version doesn't consider the case where PGRES_PIPELINE_SYNC is followed by another one. In that situation, the loop would terminate without getting NULL, which would causes an error in PQexitPipelineMode(). However, I would like to suggest an alternative solution: checking the connection status when readCommandResponse() returns false. This seems more straightforwad, since the cause of the error can be investigated immediately after it is detected. @@ -4024,7 +4043,10 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) if (PQpipelineStatus(st->con) != PQ_PIPELINE_ON) st->state = CSTATE_END_COMMAND; } - else if (canRetryError(st->estatus)) + else if (PQstatus(st->con) == CONNECTION_BAD) + st->state = CSTATE_ABORTED; + else if ((st->estatus == ESTATUS_OTHER_SQL_ERROR && continue_on_error) || + canRetryError(st->estatus)) st->state = CSTATE_ERROR; else st->state = CSTATE_ABORTED; What do you think? Additionally, I noticed that in pipeline mode, the error message reported in readCommandResponse() is lost, because it is reset when PQgetResult() returned NULL to indicate the end of query processing. For example: pgbench: client 0 got an error in command 3 (SQL) of script 0; pgbench: client 1 got an error in command 3 (SQL) of script 0; This can be fixed this by saving the previous error message and using it for the report. After the fix: pgbench: client 0 got an error in command 3 (SQL) of script 0; FATAL: terminating connection due to administrator command I've attached update patches. 0001 fixes the assersion failure in commandError() and error message lost in readCommandResponse(). 0002 was the previous 0001 that adds --continiue-on-error, including the fix to handle connection termination errors. 0003 is for improving error messages for errors that cause client abortion. Regareds, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-25T02:17:21Z
On Thu, 25 Sep 2025 11:09:40 +0900 Yugo Nagata <nagata@sraoss.co.jp> wrote: > On Thu, 25 Sep 2025 02:19:27 +0900 > Fujii Masao <masao.fujii@gmail.com> wrote: > > > On Tue, Sep 23, 2025 at 11:58 AM Rintaro Ikeda > > <ikedarintarof@oss.nttdata.com> wrote: > > > I think the issue is a new bug because we have transitioned to CSTATE_ABORT > > > immediately after queries failed, without executing discardUntilSync(). > > Agreed. > > > If so, the fix in discardUntilSync() should be part of the continue-on-error > > patch. The assertion failure fix should be a separate patch, since only > > that needs to be backpatched (the failure can also occur in back branches). > > +1 > > > > > > I've attached a patch that fixes the assertion error. The content of v1 patch by > > > Mr. Nagata is also included. I would appreciate it if you review my patch. > > > + switch (PQresultStatus(res)) > > + { > > + case PGRES_PIPELINE_SYNC: > > + received_sync = true; > > > > In the PGRES_PIPELINE_SYNC case, PQclear(res) isn't called but should be. > > > > + case PGRES_FATAL_ERROR: > > + PQclear(res); > > + goto done; > > > > I don't think we need goto here. How about this instead? > > > > ----------------------- > > @@ -3525,11 +3525,18 @@ discardUntilSync(CState *st) > > * results have been discarded. > > */ > > st->num_syncs = 0; > > - PQclear(res); > > break; > > } > > + /* > > + * Stop receiving further results if PGRES_FATAL_ERROR > > is returned > > + * (e.g., due to a connection failure) before > > PGRES_PIPELINE_SYNC, > > + * since PGRES_PIPELINE_SYNC will never arrive. > > + */ > > + else if (PQresultStatus(res) == PGRES_FATAL_ERROR) > > + break; > > PQclear(res); > > } > > + PQclear(res); > > > > /* exit pipeline */ > > if (PQexitPipelineMode(st->con) != 1) > > ----------------------- > > I think Fujii-san's version is better because Ikeda-san's version doesn't > consider the case where PGRES_PIPELINE_SYNC is followed by another one. > In that situation, the loop would terminate without getting NULL, which would > causes an error in PQexitPipelineMode(). > > However, I would like to suggest an alternative solution: checking the connection > status when readCommandResponse() returns false. This seems more straightforwad, > since the cause of the error can be investigated immediately after it is detected. > > @@ -4024,7 +4043,10 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) > if (PQpipelineStatus(st->con) != PQ_PIPELINE_ON) > st->state = CSTATE_END_COMMAND; > } > - else if (canRetryError(st->estatus)) > + else if (PQstatus(st->con) == CONNECTION_BAD) > + st->state = CSTATE_ABORTED; > + else if ((st->estatus == ESTATUS_OTHER_SQL_ERROR && continue_on_error) || > + canRetryError(st->estatus)) > st->state = CSTATE_ERROR; > else > st->state = CSTATE_ABORTED; > > What do you think? > > > Additionally, I noticed that in pipeline mode, the error message reported in > readCommandResponse() is lost, because it is reset when PQgetResult() returned > NULL to indicate the end of query processing. For example: > > pgbench: client 0 got an error in command 3 (SQL) of script 0; > pgbench: client 1 got an error in command 3 (SQL) of script 0; > > This can be fixed this by saving the previous error message and using it > for the report. After the fix: > > pgbench: client 0 got an error in command 3 (SQL) of script 0; FATAL: terminating connection due to administrator command > > I've attached update patches. > > 0001 fixes the assersion failure in commandError() and error message lost > in readCommandResponse(). > > 0002 was the previous 0001 that adds --continiue-on-error, including the > fix to handle connection termination errors. > > 0003 is for improving error messages for errors that cause client abortion. I think the patch 0001 should be back patched since the issues can occurs even for retries of serialization failure or deadlock detection in pipeline mode. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-09-25T04:49:05Z
On Thu, Sep 25, 2025 at 11:17 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > On Thu, 25 Sep 2025 11:09:40 +0900 > Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > On Thu, 25 Sep 2025 02:19:27 +0900 > > Fujii Masao <masao.fujii@gmail.com> wrote: > > > > > On Tue, Sep 23, 2025 at 11:58 AM Rintaro Ikeda > > > <ikedarintarof@oss.nttdata.com> wrote: > > > > I think the issue is a new bug because we have transitioned to CSTATE_ABORT > > > > immediately after queries failed, without executing discardUntilSync(). > > > > Agreed. > > > > > If so, the fix in discardUntilSync() should be part of the continue-on-error > > > patch. The assertion failure fix should be a separate patch, since only > > > that needs to be backpatched (the failure can also occur in back branches). > > > > +1 > > > > > > > > > I've attached a patch that fixes the assertion error. The content of v1 patch by > > > > Mr. Nagata is also included. I would appreciate it if you review my patch. > > > > > + switch (PQresultStatus(res)) > > > + { > > > + case PGRES_PIPELINE_SYNC: > > > + received_sync = true; > > > > > > In the PGRES_PIPELINE_SYNC case, PQclear(res) isn't called but should be. > > > > > > + case PGRES_FATAL_ERROR: > > > + PQclear(res); > > > + goto done; > > > > > > I don't think we need goto here. How about this instead? > > > > > > ----------------------- > > > @@ -3525,11 +3525,18 @@ discardUntilSync(CState *st) > > > * results have been discarded. > > > */ > > > st->num_syncs = 0; > > > - PQclear(res); > > > break; > > > } > > > + /* > > > + * Stop receiving further results if PGRES_FATAL_ERROR > > > is returned > > > + * (e.g., due to a connection failure) before > > > PGRES_PIPELINE_SYNC, > > > + * since PGRES_PIPELINE_SYNC will never arrive. > > > + */ > > > + else if (PQresultStatus(res) == PGRES_FATAL_ERROR) > > > + break; > > > PQclear(res); > > > } > > > + PQclear(res); > > > > > > /* exit pipeline */ > > > if (PQexitPipelineMode(st->con) != 1) > > > ----------------------- > > > > I think Fujii-san's version is better because Ikeda-san's version doesn't > > consider the case where PGRES_PIPELINE_SYNC is followed by another one. > > In that situation, the loop would terminate without getting NULL, which would > > causes an error in PQexitPipelineMode(). > > > > However, I would like to suggest an alternative solution: checking the connection > > status when readCommandResponse() returns false. This seems more straightforwad, > > since the cause of the error can be investigated immediately after it is detected. > > > > @@ -4024,7 +4043,10 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) > > if (PQpipelineStatus(st->con) != PQ_PIPELINE_ON) > > st->state = CSTATE_END_COMMAND; > > } > > - else if (canRetryError(st->estatus)) > > + else if (PQstatus(st->con) == CONNECTION_BAD) > > + st->state = CSTATE_ABORTED; > > + else if ((st->estatus == ESTATUS_OTHER_SQL_ERROR && continue_on_error) || > > + canRetryError(st->estatus)) > > st->state = CSTATE_ERROR; > > else > > st->state = CSTATE_ABORTED; > > > > What do you think? > > > > > > Additionally, I noticed that in pipeline mode, the error message reported in > > readCommandResponse() is lost, because it is reset when PQgetResult() returned > > NULL to indicate the end of query processing. For example: > > > > pgbench: client 0 got an error in command 3 (SQL) of script 0; > > pgbench: client 1 got an error in command 3 (SQL) of script 0; > > > > This can be fixed this by saving the previous error message and using it > > for the report. After the fix: > > > > pgbench: client 0 got an error in command 3 (SQL) of script 0; FATAL: terminating connection due to administrator command > > > > I've attached update patches. > > > > 0001 fixes the assersion failure in commandError() and error message lost > > in readCommandResponse(). > > > > 0002 was the previous 0001 that adds --continiue-on-error, including the > > fix to handle connection termination errors. > > > > 0003 is for improving error messages for errors that cause client abortion. > > I think the patch 0001 should be back patched since the issues can occurs > even for retries of serialization failure or deadlock detection in pipeline mode. Agreed. Regarding 0001: + /* + Errors should only be detected during an SQL command or the \endpipeline + meta command. Any other case triggers an assertion failure. + */ * should be added before "Errors" and "meta". + errmsg = pg_strdup(PQerrorMessage(st->con)); It would be good to add a comment explaining why we do this. + pg_free(errmsg); Shouldn't pg_free() be called also in the error case, i.e., after jumping to the error label? Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-25T07:22:16Z
On Thu, 25 Sep 2025 13:49:05 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Thu, Sep 25, 2025 at 11:17 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > On Thu, 25 Sep 2025 11:09:40 +0900 > > Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > > On Thu, 25 Sep 2025 02:19:27 +0900 > > > Fujii Masao <masao.fujii@gmail.com> wrote: > > > > > > > On Tue, Sep 23, 2025 at 11:58 AM Rintaro Ikeda > > > > <ikedarintarof@oss.nttdata.com> wrote: > > > > > I think the issue is a new bug because we have transitioned to CSTATE_ABORT > > > > > immediately after queries failed, without executing discardUntilSync(). > > > > > > Agreed. > > > > > > > If so, the fix in discardUntilSync() should be part of the continue-on-error > > > > patch. The assertion failure fix should be a separate patch, since only > > > > that needs to be backpatched (the failure can also occur in back branches). > > > > > > +1 > > > > > > > > > > > > I've attached a patch that fixes the assertion error. The content of v1 patch by > > > > > Mr. Nagata is also included. I would appreciate it if you review my patch. > > > > > > > + switch (PQresultStatus(res)) > > > > + { > > > > + case PGRES_PIPELINE_SYNC: > > > > + received_sync = true; > > > > > > > > In the PGRES_PIPELINE_SYNC case, PQclear(res) isn't called but should be. > > > > > > > > + case PGRES_FATAL_ERROR: > > > > + PQclear(res); > > > > + goto done; > > > > > > > > I don't think we need goto here. How about this instead? > > > > > > > > ----------------------- > > > > @@ -3525,11 +3525,18 @@ discardUntilSync(CState *st) > > > > * results have been discarded. > > > > */ > > > > st->num_syncs = 0; > > > > - PQclear(res); > > > > break; > > > > } > > > > + /* > > > > + * Stop receiving further results if PGRES_FATAL_ERROR > > > > is returned > > > > + * (e.g., due to a connection failure) before > > > > PGRES_PIPELINE_SYNC, > > > > + * since PGRES_PIPELINE_SYNC will never arrive. > > > > + */ > > > > + else if (PQresultStatus(res) == PGRES_FATAL_ERROR) > > > > + break; > > > > PQclear(res); > > > > } > > > > + PQclear(res); > > > > > > > > /* exit pipeline */ > > > > if (PQexitPipelineMode(st->con) != 1) > > > > ----------------------- > > > > > > I think Fujii-san's version is better because Ikeda-san's version doesn't > > > consider the case where PGRES_PIPELINE_SYNC is followed by another one. > > > In that situation, the loop would terminate without getting NULL, which would > > > causes an error in PQexitPipelineMode(). > > > > > > However, I would like to suggest an alternative solution: checking the connection > > > status when readCommandResponse() returns false. This seems more straightforwad, > > > since the cause of the error can be investigated immediately after it is detected. > > > > > > @@ -4024,7 +4043,10 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) > > > if (PQpipelineStatus(st->con) != PQ_PIPELINE_ON) > > > st->state = CSTATE_END_COMMAND; > > > } > > > - else if (canRetryError(st->estatus)) > > > + else if (PQstatus(st->con) == CONNECTION_BAD) > > > + st->state = CSTATE_ABORTED; > > > + else if ((st->estatus == ESTATUS_OTHER_SQL_ERROR && continue_on_error) || > > > + canRetryError(st->estatus)) > > > st->state = CSTATE_ERROR; > > > else > > > st->state = CSTATE_ABORTED; > > > > > > What do you think? > > > > > > > > > Additionally, I noticed that in pipeline mode, the error message reported in > > > readCommandResponse() is lost, because it is reset when PQgetResult() returned > > > NULL to indicate the end of query processing. For example: > > > > > > pgbench: client 0 got an error in command 3 (SQL) of script 0; > > > pgbench: client 1 got an error in command 3 (SQL) of script 0; > > > > > > This can be fixed this by saving the previous error message and using it > > > for the report. After the fix: > > > > > > pgbench: client 0 got an error in command 3 (SQL) of script 0; FATAL: terminating connection due to administrator command > > > > > > I've attached update patches. > > > > > > 0001 fixes the assersion failure in commandError() and error message lost > > > in readCommandResponse(). > > > > > > 0002 was the previous 0001 that adds --continiue-on-error, including the > > > fix to handle connection termination errors. > > > > > > 0003 is for improving error messages for errors that cause client abortion. > > > > I think the patch 0001 should be back patched since the issues can occurs > > even for retries of serialization failure or deadlock detection in pipeline mode. > > Agreed. > > Regarding 0001: > > + /* > + Errors should only be detected during an SQL command or the \endpipeline > + meta command. Any other case triggers an assertion failure. > + */ > > * should be added before "Errors" and "meta". Oops. Fixed. > + errmsg = pg_strdup(PQerrorMessage(st->con)); > > It would be good to add a comment explaining why we do this. > > + pg_free(errmsg); > > Shouldn't pg_free() be called also in the error case, i.e., after > jumping to the error label? Yes, it should be. Fixed. I've attached updated patches. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com> — 2025-09-25T08:27:44Z
Hi, The patch looks good, I've spotted some typos in the doc. + Allows clients to continue their run even if an SQL statement fails due to + errors other than serialization or deadlock. Unlike serialization and deadlock + failures, clients do not retry the same transactions but start new transaction. Should be "but start a new transaction.", although "proceed to the next transaction." may be clearer here that ? + number of transactions that got a SQL error + (zero unless <option>--failures-detailed</option> is specified) It seems like both "a SQL" and "an SQL" are used in the codebase and doc, but this page only uses "an SQL", so using "an SQL" may be better for consistency. + If an SQL command fails due to serialization or deadlock errors, the + client does not aborted, regardless of whether Should be "the client does not abort." Regards, Anthonin Bonnefoy
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-09-25T09:17:36Z
Hi Yugo, Thanks for the patch. After reviewing it, I got a few small comments: > On Sep 25, 2025, at 15:22, Yugo Nagata <nagata@sraoss.co.jp> wrote: > > -- > Yugo Nagata <nagata@sraoss.co.jp <mailto:nagata@sraoss.co.jp>> > <v13-0003-Improve-error-messages-for-errors-that-cause-cli.patch><v13-0002-Add-continue-on-error-option.patch><v13-0001-Fix-assertion-failure-and-verbose-messages-in-pi.patch> 1 - 0001 ``` @@ -3265,6 +3271,7 @@ readCommandResponse(CState *st, MetaCommand meta, char *varprefix) PGresult *res; PGresult *next_res; int qrynum = 0; + char *errmsg; ``` I think we should initialize errmsg to NULL. Compiler won’t auto initialize a local variable. If it happens to not enter the while loop, then errmsg will hold a random value, then pg_free(errmsg) will have trouble. 2 - 0002 ``` + <para> + Allows clients to continue their run even if an SQL statement fails due to + errors other than serialization or deadlock. Unlike serialization and deadlock + failures, clients do not retry the same transactions but start new transaction. + This option is useful when your custom script may raise errors due to some + reason like unique constraints violation. Without this option, the client is + aborted after such errors. + </para> ``` A few nit suggestions: * “continue their run” => “continue running” * “clients to not retry the same transactions but start new transaction” => “clients do not retry the same transaction but start a new transaction instead" * “due to some reason like” => “for reasons such as" 3 - 0002 ``` + * Without --continue-on-error: * failed (the number of failed transactions) = ``` Maybe add an empty line after “without” line. 4 - 0002 ``` + * When --continue-on-error is specified: + * + * failed (number of failed transactions) = ``` Maybe change to “With ---continue-on-error”, which sounds consistent with the previous “without”. 5 - 0002 ``` + int64 other_sql_failures; /* number of failed transactions for + * reasons other than + * serialization/deadlock failure, which + * is counted if --continue-on-error is + * specified */ ``` How about rename this variable to “sql_errors”, which reflects to the new option name. 6 - 0002 ``` @@ -4571,6 +4594,8 @@ getResultString(bool skipped, EStatus estatus) return "serialization"; case ESTATUS_DEADLOCK_ERROR: return "deadlock"; + case ESTATUS_OTHER_SQL_ERROR: + return "other”; ``` I think this can just return “error”. I checked where this function is called, there will not be other words such as “error” appended. 7 - 0002 ``` /* it can be non-zero only if max_tries is not equal to one */ @@ -6569,6 +6602,10 @@ printResults(StatsData *total, sstats->deadlock_failures, (100.0 * sstats->deadlock_failures / script_total_cnt)); + printf(" - number of other failures: " INT64_FORMAT " (%.3f%%)\n", + sstats->other_sql_failures, + (100.0 * sstats->other_sql_failures / + script_total_cnt)); ``` Do we only want to print this number when “—continue-on-error” is given? Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-09-25T15:03:06Z
On Thu, Sep 25, 2025 at 4:22 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > I've attached updated patches. Thanks for updating the patches! About 0001: you mentioned that the lost error message issue occurs in pipeline mode. Just to confirm, are you sure it never happens in non-pipeline mode? >From a quick look, readCommandResponse() seems to have this problem regardless of whether pipeline mode is used. If it can also happen outside pipeline mode, maybe we should split this from the assertion failure fix, since they'd need to be backpatched to different branches. What do you think? Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-26T01:29:32Z
On Fri, 26 Sep 2025 00:03:06 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Thu, Sep 25, 2025 at 4:22 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > I've attached updated patches. > > Thanks for updating the patches! > > About 0001: you mentioned that the lost error message issue occurs in > pipeline mode. > Just to confirm, are you sure it never happens in non-pipeline mode? > From a quick look, > readCommandResponse() seems to have this problem regardless of whether pipeline > mode is used. > > If it can also happen outside pipeline mode, maybe we should split this from > the assertion failure fix, since they'd need to be backpatched to > different branches. I could not find a code path that resets the error state before reporting in non-pipeline mode, since it is typically reset when starting to send a query. However, referencing an error message after another PQgetResult() does not seem like a good idea in general, so I agree with splitting the patch. I'll submit updated patches soon. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-26T02:44:42Z
On Thu, 25 Sep 2025 17:17:36 +0800 Chao Li <li.evan.chao@gmail.com> wrote: > Hi Yugo, > > Thanks for the patch. After reviewing it, I got a few small comments: Thank you for your reviewing and comments. > > On Sep 25, 2025, at 15:22, Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > -- > > Yugo Nagata <nagata@sraoss.co.jp <mailto:nagata@sraoss.co.jp>> > > <v13-0003-Improve-error-messages-for-errors-that-cause-cli.patch><v13-0002-Add-continue-on-error-option.patch><v13-0001-Fix-assertion-failure-and-verbose-messages-in-pi.patch> > > > 1 - 0001 > ``` > @@ -3265,6 +3271,7 @@ readCommandResponse(CState *st, MetaCommand meta, char *varprefix) > PGresult *res; > PGresult *next_res; > int qrynum = 0; > + char *errmsg; > ``` > > I think we should initialize errmsg to NULL. Compiler won’t auto initialize a local variable. If it happens to not enter the while loop, then errmsg will hold a random value, then pg_free(errmsg) will have trouble. I think this initialization is unnecessary, just like for res and next_res. If the code happens not to enter the while loop, pg_free(errmsg) will not be called anyway, since the error: label is only reachable from inside the loop. > 2 - 0002 > ``` > + <para> > + Allows clients to continue their run even if an SQL statement fails due to > + errors other than serialization or deadlock. Unlike serialization and deadlock > + failures, clients do not retry the same transactions but start new transaction. > + This option is useful when your custom script may raise errors due to some > + reason like unique constraints violation. Without this option, the client is > + aborted after such errors. > + </para> > ``` > > A few nit suggestions: > > * “continue their run” => “continue running” Fixed. > * “clients to not retry the same transactions but start new transaction” => “clients do not retry the same transaction but start a new transaction instead" I see your point. Maybe we could follow Anthonin Bonnefoy's suggestion to use "proceed to the next transaction", as it may sound a bit more natural. > * “due to some reason like” => “for reasons such as" Fixed. > 3 - 0002 > ``` > + * Without --continue-on-error: > * failed (the number of failed transactions) = > ``` > > Maybe add an empty line after “without” line. Makes sense. Fixed. > 4 - 0002 > ``` > + * When --continue-on-error is specified: > + * > + * failed (number of failed transactions) = > ``` > > Maybe change to “With ---continue-on-error”, which sounds consistent with the previous “without”. Fixed. > 5 - 0002 > ``` > + int64 other_sql_failures; /* number of failed transactions for > + * reasons other than > + * serialization/deadlock failure, which > + * is counted if --continue-on-error is > + * specified */ > ``` > > How about rename this variable to “sql_errors”, which reflects to the new option name. I think it’s better to keep the current name, since the variable counts failed transactions, even though that happens to be equivalent to the number of SQL errors. It’s also consistent with the other variables, serialization_failures and deadlock_failures. > 6 - 0002 > ``` > @@ -4571,6 +4594,8 @@ getResultString(bool skipped, EStatus estatus) > return "serialization"; > case ESTATUS_DEADLOCK_ERROR: > return "deadlock"; > + case ESTATUS_OTHER_SQL_ERROR: > + return "other”; > ``` > > I think this can just return “error”. I checked where this function is called, there will not be other words such as “error” appended. getResultString() is called to get a string that represents the type of error causing the transaction failure, so simply returning "error" doesn’t seem very useful. > 7 - 0002 > ``` > /* it can be non-zero only if max_tries is not equal to one */ > @@ -6569,6 +6602,10 @@ printResults(StatsData *total, > sstats->deadlock_failures, > (100.0 * sstats->deadlock_failures / > script_total_cnt)); > + printf(" - number of other failures: " INT64_FORMAT " (%.3f%%)\n", > + sstats->other_sql_failures, > + (100.0 * sstats->other_sql_failures / > + script_total_cnt)); > ``` > > Do we only want to print this number when “―continue-on-error” is given? We could do that, but this message is printed only when --failures-detailed is specified. So I think users would not mind if it shows that the number of other failures is zero, even when --continue-on-error is not specified. I would appreciate hearing other people's opinions on this. I've attached updated patches that include fixes for some of your suggestions and for Anthonin Bonnefoy's suggestion on the documentation. I also split the patch according to Fujii-san's suggestion. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-26T02:52:34Z
On Thu, 25 Sep 2025 10:27:44 +0200 Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com> wrote: > Hi, > > The patch looks good, I've spotted some typos in the doc. > > + Allows clients to continue their run even if an SQL statement > fails due to > + errors other than serialization or deadlock. Unlike > serialization and deadlock > + failures, clients do not retry the same transactions but > start new transaction. > > Should be "but start a new transaction.", although "proceed to the > next transaction." may be clearer here that ? > > + number of transactions that got a SQL error > + (zero unless <option>--failures-detailed</option> is specified) > > It seems like both "a SQL" and "an SQL" are used in the codebase and > doc, but this page only uses "an SQL", so using "an SQL" may be better > for consistency. > > + If an SQL command fails due to serialization or deadlock errors, the > + client does not aborted, regardless of whether > > Should be "the client does not abort." Thank you for your review. I've attached the updated patch in my previous post in this thread. By the way, on the pgsql-hackers list, top-posting is generally discouraged [1], so replying below the quoted messages is usually preferred. [1] https://wiki.postgresql.org/wiki/Mailing_Lists Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-30T01:23:53Z
On Fri, 26 Sep 2025 11:44:42 +0900 Yugo Nagata <nagata@sraoss.co.jp> wrote: > On Thu, 25 Sep 2025 17:17:36 +0800 > Chao Li <li.evan.chao@gmail.com> wrote: > > > Hi Yugo, > > > > Thanks for the patch. After reviewing it, I got a few small comments: > > Thank you for your reviewing and comments. > > > > On Sep 25, 2025, at 15:22, Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > > > -- > > > Yugo Nagata <nagata@sraoss.co.jp <mailto:nagata@sraoss.co.jp>> > > > <v13-0003-Improve-error-messages-for-errors-that-cause-cli.patch><v13-0002-Add-continue-on-error-option.patch><v13-0001-Fix-assertion-failure-and-verbose-messages-in-pi.patch> > > > > > > 1 - 0001 > > ``` > > @@ -3265,6 +3271,7 @@ readCommandResponse(CState *st, MetaCommand meta, char *varprefix) > > PGresult *res; > > PGresult *next_res; > > int qrynum = 0; > > + char *errmsg; > > ``` > > > > I think we should initialize errmsg to NULL. Compiler won’t auto initialize a local variable. If it happens to not enter the while loop, then errmsg will hold a random value, then pg_free(errmsg) will have trouble. > > I think this initialization is unnecessary, just like for res and next_res. > If the code happens not to enter the while loop, pg_free(errmsg) will not be > called anyway, since the error: label is only reachable from inside the loop. > > > 2 - 0002 > > ``` > > + <para> > > + Allows clients to continue their run even if an SQL statement fails due to > > + errors other than serialization or deadlock. Unlike serialization and deadlock > > + failures, clients do not retry the same transactions but start new transaction. > > + This option is useful when your custom script may raise errors due to some > > + reason like unique constraints violation. Without this option, the client is > > + aborted after such errors. > > + </para> > > ``` > > > > A few nit suggestions: > > > > * “continue their run” => “continue running” > > Fixed. > > > * “clients to not retry the same transactions but start new transaction” => “clients do not retry the same transaction but start a new transaction instead" > > I see your point. Maybe we could follow Anthonin Bonnefoy's suggestion > to use "proceed to the next transaction", as it may sound a bit more natural. > > > * “due to some reason like” => “for reasons such as" > > Fixed. > > > 3 - 0002 > > ``` > > + * Without --continue-on-error: > > * failed (the number of failed transactions) = > > ``` > > > > Maybe add an empty line after “without” line. > > Makes sense. Fixed. > > > 4 - 0002 > > ``` > > + * When --continue-on-error is specified: > > + * > > + * failed (number of failed transactions) = > > ``` > > > > Maybe change to “With ---continue-on-error”, which sounds consistent with the previous “without”. > > Fixed. > > > 5 - 0002 > > ``` > > + int64 other_sql_failures; /* number of failed transactions for > > + * reasons other than > > + * serialization/deadlock failure, which > > + * is counted if --continue-on-error is > > + * specified */ > > ``` > > > > How about rename this variable to “sql_errors”, which reflects to the new option name. > > I think it’s better to keep the current name, since the variable counts failed transactions, > even though that happens to be equivalent to the number of SQL errors. It’s also consistent > with the other variables, serialization_failures and deadlock_failures. > > > 6 - 0002 > > ``` > > @@ -4571,6 +4594,8 @@ getResultString(bool skipped, EStatus estatus) > > return "serialization"; > > case ESTATUS_DEADLOCK_ERROR: > > return "deadlock"; > > + case ESTATUS_OTHER_SQL_ERROR: > > + return "other”; > > ``` > > > > I think this can just return “error”. I checked where this function is called, there will not be other words such as “error” appended. > > getResultString() is called to get a string that represents the type of error > causing the transaction failure, so simply returning "error" doesn’t seem very > useful. > > > 7 - 0002 > > ``` > > /* it can be non-zero only if max_tries is not equal to one */ > > @@ -6569,6 +6602,10 @@ printResults(StatsData *total, > > sstats->deadlock_failures, > > (100.0 * sstats->deadlock_failures / > > script_total_cnt)); > > + printf(" - number of other failures: " INT64_FORMAT " (%.3f%%)\n", > > + sstats->other_sql_failures, > > + (100.0 * sstats->other_sql_failures / > > + script_total_cnt)); > > ``` > > > > Do we only want to print this number when “―continue-on-error” is given? > > We could do that, but this message is printed only when > --failures-detailed is specified. So I think users would not mind > if it shows that the number of other failures is zero, even when > --continue-on-error is not specified. > > I would appreciate hearing other people's opinions on this. > > > I've attached updated patches that include fixes for some of your > suggestions and for Anthonin Bonnefoy's suggestion on the documentation. > > I also split the patch according to Fujii-san's suggestion. Fujii-san, thank you for committing the patch that fixes the assertion failure. I've attached the remaining patches so that cfbot stays green. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-09-30T04:46:11Z
On Tue, Sep 30, 2025 at 10:24 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > Fujii-san, thank you for committing the patch that fixes the assertion failure. > I've attached the remaining patches so that cfbot stays green. Thanks for reattaching the patches! For 0001, after reading the docs on PQresultErrorMessage(), I wonder if it would be better to just use that to get the error message. Thought? Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-09-30T06:16:53Z
On Tue, 30 Sep 2025 13:46:11 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Tue, Sep 30, 2025 at 10:24 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > Fujii-san, thank you for committing the patch that fixes the assertion failure. > > I've attached the remaining patches so that cfbot stays green. > > Thanks for reattaching the patches! > > For 0001, after reading the docs on PQresultErrorMessage(), I wonder if it would > be better to just use that to get the error message. Thought? Thank you for your suggestion. I agree that it is better to use PQresultErrorMessage(). I had overlooked the existence of this interface. I've attached the updated patches. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-10-01T16:22:19Z
On Tue, Sep 30, 2025 at 3:17 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > On Tue, 30 Sep 2025 13:46:11 +0900 > Fujii Masao <masao.fujii@gmail.com> wrote: > > > On Tue, Sep 30, 2025 at 10:24 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > Fujii-san, thank you for committing the patch that fixes the assertion failure. > > > I've attached the remaining patches so that cfbot stays green. > > > > Thanks for reattaching the patches! > > > > For 0001, after reading the docs on PQresultErrorMessage(), I wonder if it would > > be better to just use that to get the error message. Thought? > > Thank you for your suggestion. > > I agree that it is better to use PQresultErrorMessage(). > I had overlooked the existence of this interface. > > I've attached the updated patches. Thanks for updating the patches! I've pushed 0001. Regarding 0002: - if (canRetryError(st->estatus)) + if (continue_on_error || canRetryError(st->estatus)) { if (verbose_errors) commandError(st, PQresultErrorMessage(res)); goto error; With this change, even non-SQL errors (e.g., connection failures) would satisfy the condition when --continue-on-error is set. Isn't that a problem? Shouldn't we also check that the error status is one that --continue-on-error is meant to handle? + * Without --continue-on-error: * * failed (the number of failed transactions) = * 'serialization_failures' (they got a serialization error and were not * successfully retried) + * 'deadlock_failures' (they got a deadlock error and were not * successfully retried). * + * With --continue-on-error: + * + * failed (number of failed transactions) = + * 'serialization_failures' + 'deadlock_failures' + + * 'other_sql_failures' (they got some other SQL error; the transaction was + * not retried and counted as failed due to --continue-on-error). About the comments on failed transactions: I don't think we need to split them into separate "with/without --continue-on-error" sections. How about simplifying them like this? ------------------------ * failed (the number of failed transactions) = * 'serialization_failures' (they got a serialization error and were not * successfully retried) + * 'deadlock_failures' (they got a deadlock error and were not * successfully retried) + * 'other_sql_failures' (they failed on the first try or after retries * due to a SQL error other than serialization or * deadlock; they are counted as a failed transaction * only when --continue-on-error is specified). ------------------------ * 'retried' (number of all retried transactions) = * successfully retried transactions + * failed transactions. Since transactions that failed on the first try (i.e., no retries) due to an SQL error are not counted as 'retried', shouldn't this source comment be updated? Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Rintaro Ikeda <ikedarintarof@oss.nttdata.com> — 2025-10-19T13:12:37Z
Hi, On 2025/10/02 1:22, Fujii Masao wrote: > Regarding 0002: > > - if (canRetryError(st->estatus)) > + if (continue_on_error || canRetryError(st->estatus)) > { > if (verbose_errors) > commandError(st, PQresultErrorMessage(res)); > goto error; > > With this change, even non-SQL errors (e.g., connection failures) would > satisfy the condition when --continue-on-error is set. Isn't that a problem? > Shouldn't we also check that the error status is one that > --continue-on-error is meant to handle? I agree that connection failures should not be ignored even when --continue-on-error is specified. For now, I’m not sure if other cases would cause issues, so the updated patch explicitly checks the connection status and emits an error message when the connection is lost. > > > + * Without --continue-on-error: > * > * failed (the number of failed transactions) = > * 'serialization_failures' (they got a serialization error and were not > * successfully retried) + > * 'deadlock_failures' (they got a deadlock error and were not > * successfully retried). > * > + * With --continue-on-error: > + * > + * failed (number of failed transactions) = > + * 'serialization_failures' + 'deadlock_failures' + > + * 'other_sql_failures' (they got some other SQL error; the transaction was > + * not retried and counted as failed due to --continue-on-error). > > About the comments on failed transactions: I don't think we need > to split them into separate "with/without --continue-on-error" sections. > How about simplifying them like this? > > > ------------------------ > * failed (the number of failed transactions) = > * 'serialization_failures' (they got a serialization error and were not > * successfully retried) + > * 'deadlock_failures' (they got a deadlock error and were not > * successfully retried) + > * 'other_sql_failures' (they failed on the first try or after retries > * due to a SQL error other than serialization or > * deadlock; they are counted as a failed transaction > * only when --continue-on-error is specified). > ------------------------ > Thank you for the suggestion. I’ve updated the comments as you proposed. > > * 'retried' (number of all retried transactions) = > * successfully retried transactions + > * failed transactions. > > Since transactions that failed on the first try (i.e., no retries) due to > an SQL error are not counted as 'retried', shouldn't this source comment > be updated? Agreed. I added "failed transactions" is actually counted when they are retied. I've attached the updated patch v17-0002. 0003 remains unchanged. Best regards, Rintaro Ikeda -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-10-21T00:58:12Z
On Sun, Oct 19, 2025 at 10:12 PM Rintaro Ikeda <ikedarintarof@oss.nttdata.com> wrote: > > Hi, > > On 2025/10/02 1:22, Fujii Masao wrote: > > Regarding 0002: > > > > - if (canRetryError(st->estatus)) > > + if (continue_on_error || canRetryError(st->estatus)) > > { > > if (verbose_errors) > > commandError(st, PQresultErrorMessage(res)); > > goto error; > > > > With this change, even non-SQL errors (e.g., connection failures) would > > satisfy the condition when --continue-on-error is set. Isn't that a problem? > > Shouldn't we also check that the error status is one that > > --continue-on-error is meant to handle? > > I agree that connection failures should not be ignored even when > --continue-on-error is specified. > For now, I’m not sure if other cases would cause issues, so the updated patch > explicitly checks the connection status and emits an error message when the > connection is lost. I agree that connection failures should prevent further processing even with --continue-on-error, and pgbench should focus on handling that first. However, the patch doesn't seem to handle cases where the connection is terminated by an admin (e.g., via pg_terminate_backend()) correctly. Please see the following test case, which is the same one I shared earlier: ----------------------------------------- $ cat pipeline.sql \startpipeline DO $$ BEGIN PERFORM pg_sleep(3); PERFORM pg_terminate_backend(pg_backend_pid()); END $$; \endpipeline $ pgbench -n -f pipeline.sql -c 2 -t 4 -M extended --continue-on-error ----------------------------------------- In this case, PQstatus() (added in readCommandResponse() by the patch) still returns CONNECTION_OK (BTW, the SQLSTATE is 57P01 in this case). As a result, the expected error message like “client ... script ... aborted in command ...” isn't reported. So the PQstatus() check alone that the patch added doesn't fully fix the issue. Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-10-27T09:13:53Z
On Tue, Oct 21, 2025 at 9:58 AM Fujii Masao <masao.fujii@gmail.com> wrote: > I agree that connection failures should prevent further processing even with > --continue-on-error, and pgbench should focus on handling that first. > However, the patch doesn't seem to handle cases where the connection is > terminated by an admin (e.g., via pg_terminate_backend()) correctly. > Please see the following test case, which is the same one I shared earlier: > > ----------------------------------------- > $ cat pipeline.sql > \startpipeline > DO $$ > BEGIN > PERFORM pg_sleep(3); > PERFORM pg_terminate_backend(pg_backend_pid()); > END $$; > \endpipeline > > $ pgbench -n -f pipeline.sql -c 2 -t 4 -M extended --continue-on-error > ----------------------------------------- > > In this case, PQstatus() (added in readCommandResponse() by the patch) > still returns CONNECTION_OK (BTW, the SQLSTATE is 57P01 in this case). > As a result, the expected error message like “client ... script ... aborted > in command ...” isn't reported. So the PQstatus() check alone that > the patch added doesn't fully fix the issue. One approach to address this issue is to keep calling PQgetResult() until it returns NULL, and then check the connection status when getSQLErrorStatus() determines the error state. If the connection status is CONNECTION_BAD at that point, we can treat it as a connection failure and stop processing even when --continue-on-error is specified. Attached is a WIP patch implementing this idea based on the v17 patch. It still needs more testing, review, and possibly documentation updates. Another option would be to explicitly list all SQLSTATE codes (e.g., 57P01) that should prevent continued processing, even with --continue-on-error, inside getSQLErrorStatus(). However, maintaining such a list would be cumbersome, so I believe the first approach is preferable. Thought? Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-10-28T16:00:25Z
On Mon, Oct 27, 2025 at 6:13 PM Fujii Masao <masao.fujii@gmail.com> wrote: > One approach to address this issue is to keep calling PQgetResult() until > it returns NULL, and then check the connection status when getSQLErrorStatus() > determines the error state. If the connection status is CONNECTION_BAD > at that point, we can treat it as a connection failure and stop processing > even when --continue-on-error is specified. Attached is a WIP patch > implementing this idea based on the v17 patch. It still needs more testing, > review, and possibly documentation updates. > > Another option would be to explicitly list all SQLSTATE codes (e.g., 57P01) > that should prevent continued processing, even with --continue-on-error, > inside getSQLErrorStatus(). However, maintaining such a list would be > cumbersome, so I believe the first approach is preferable. Thought? Nagata-san let me know off-list that there was the case where the previous patch didn't work correctly in pipeline mode. I've updated the patch so that --continue-on-error now works properly in that mode, and also revised the commit message. Updated patch attached. Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-05T15:12:11Z
On Wed, Oct 29, 2025 at 1:00 AM Fujii Masao <masao.fujii@gmail.com> wrote: > > On Mon, Oct 27, 2025 at 6:13 PM Fujii Masao <masao.fujii@gmail.com> wrote: > > One approach to address this issue is to keep calling PQgetResult() until > > it returns NULL, and then check the connection status when getSQLErrorStatus() > > determines the error state. If the connection status is CONNECTION_BAD > > at that point, we can treat it as a connection failure and stop processing > > even when --continue-on-error is specified. Attached is a WIP patch > > implementing this idea based on the v17 patch. It still needs more testing, > > review, and possibly documentation updates. > > > > Another option would be to explicitly list all SQLSTATE codes (e.g., 57P01) > > that should prevent continued processing, even with --continue-on-error, > > inside getSQLErrorStatus(). However, maintaining such a list would be > > cumbersome, so I believe the first approach is preferable. Thought? > > Nagata-san let me know off-list that there was the case where the previous > patch didn't work correctly in pipeline mode. I've updated the patch so that > --continue-on-error now works properly in that mode, and also revised > the commit message. Updated patch attached. In v19 patch, the description of --continue-on-error was placed right after --verbose-errors in the docs. Since pgbench long option descriptions are listed in alphabetical order, I've moved it to follow --aggregate-interval instead. I've also refined the wording of the --continue-on-error description. Attached is the updated patch. Unless there are any objections, I will commit it. Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-05T23:37:37Z
> On Nov 5, 2025, at 23:12, Fujii Masao <masao.fujii@gmail.com> wrote: > > On Wed, Oct 29, 2025 at 1:00 AM Fujii Masao <masao.fujii@gmail.com> wrote: >> >> On Mon, Oct 27, 2025 at 6:13 PM Fujii Masao <masao.fujii@gmail.com> wrote: >>> One approach to address this issue is to keep calling PQgetResult() until >>> it returns NULL, and then check the connection status when getSQLErrorStatus() >>> determines the error state. If the connection status is CONNECTION_BAD >>> at that point, we can treat it as a connection failure and stop processing >>> even when --continue-on-error is specified. Attached is a WIP patch >>> implementing this idea based on the v17 patch. It still needs more testing, >>> review, and possibly documentation updates. >>> >>> Another option would be to explicitly list all SQLSTATE codes (e.g., 57P01) >>> that should prevent continued processing, even with --continue-on-error, >>> inside getSQLErrorStatus(). However, maintaining such a list would be >>> cumbersome, so I believe the first approach is preferable. Thought? >> >> Nagata-san let me know off-list that there was the case where the previous >> patch didn't work correctly in pipeline mode. I've updated the patch so that >> --continue-on-error now works properly in that mode, and also revised >> the commit message. Updated patch attached. > > In v19 patch, the description of --continue-on-error was placed right after > --verbose-errors in the docs. Since pgbench long option descriptions are listed > in alphabetical order, I've moved it to follow --aggregate-interval instead. > I've also refined the wording of the --continue-on-error description. > > Attached is the updated patch. Unless there are any objections, I will > commit it. > > Regards, > > -- > Fujii Masao > <v20-0001-pgbench-Add-continue-on-error-option.patch> I just eyeball reviewed v20 and got a doubt: ``` +static void +discardAvailableResults(CState *st) +{ + PGresult *res = NULL; + + for (;;) + { + res = PQgetResult(st->con); + + /* + * Read and discard results until PQgetResult() returns NULL (no more + * results) or a connection failure is detected. If the pipeline + * status is PQ_PIPELINE_ABORTED, more results may still be available + * even after PQgetResult() returns NULL, so continue reading in that + * case. + */ + if ((res == NULL && PQpipelineStatus(st->con) != PQ_PIPELINE_ABORTED) || + PQstatus(st->con) == CONNECTION_BAD) + break; + + PQclear(res); + } + PQclear(res); +} ``` If pipeline is aborted and no more results, then the “if” will be "true && false”. And in this case, I guess PQstatus(st->con) != CONNECTION_BAD because it’s not a connection error, then overall, the “if” will be “false”, and it falls into an infinite loop. Expect that, everything else looks good to me. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-06T16:38:27Z
On Thu, Nov 6, 2025 at 8:38 AM Chao Li <li.evan.chao@gmail.com> wrote: > I just eyeball reviewed v20 and got a doubt: Thanks for the review! > +static void > +discardAvailableResults(CState *st) > +{ > + PGresult *res = NULL; > + > + for (;;) > + { > + res = PQgetResult(st->con); > + > + /* > + * Read and discard results until PQgetResult() returns NULL (no more > + * results) or a connection failure is detected. If the pipeline > + * status is PQ_PIPELINE_ABORTED, more results may still be available > + * even after PQgetResult() returns NULL, so continue reading in that > + * case. > + */ > + if ((res == NULL && PQpipelineStatus(st->con) != PQ_PIPELINE_ABORTED) || > + PQstatus(st->con) == CONNECTION_BAD) > + break; > + > + PQclear(res); > + } > + PQclear(res); > +} > ``` > > If pipeline is aborted and no more results, then the “if” will be "true && false”. And in this case, I guess PQstatus(st->con) != CONNECTION_BAD because it’s not a connection error, then overall, the “if” will be “false”, and it falls into an infinite loop. Can this situation actually happen? It would be helpful if you could share the custom script that triggers it. When the pipeline is aborted, PGRES_PIPELINE_SYNC should arrive afterward, changing the status from PQ_PIPELINE_ABORTED to PQ_PIPELINE_ON. That should make the condition true and prevent an infinite loop, right? Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-07T00:06:32Z
> On Nov 7, 2025, at 00:38, Fujii Masao <masao.fujii@gmail.com> wrote: > > On Thu, Nov 6, 2025 at 8:38 AM Chao Li <li.evan.chao@gmail.com> wrote: >> I just eyeball reviewed v20 and got a doubt: > > Thanks for the review! > > >> +static void >> +discardAvailableResults(CState *st) >> +{ >> + PGresult *res = NULL; >> + >> + for (;;) >> + { >> + res = PQgetResult(st->con); >> + >> + /* >> + * Read and discard results until PQgetResult() returns NULL (no more >> + * results) or a connection failure is detected. If the pipeline >> + * status is PQ_PIPELINE_ABORTED, more results may still be available >> + * even after PQgetResult() returns NULL, so continue reading in that >> + * case. >> + */ >> + if ((res == NULL && PQpipelineStatus(st->con) != PQ_PIPELINE_ABORTED) || >> + PQstatus(st->con) == CONNECTION_BAD) >> + break; >> + >> + PQclear(res); >> + } >> + PQclear(res); >> +} >> ``` >> >> If pipeline is aborted and no more results, then the “if” will be "true && false”. And in this case, I guess PQstatus(st->con) != CONNECTION_BAD because it’s not a connection error, then overall, the “if” will be “false”, and it falls into an infinite loop. > > Can this situation actually happen? It would be helpful if you could share > the custom script that triggers it. No, I don’t have such a script. I am on vacation and traveling with my family this week, I just found a little time to work on the day, that was why I only did an eyeball review. > > When the pipeline is aborted, PGRES_PIPELINE_SYNC should arrive afterward, > changing the status from PQ_PIPELINE_ABORTED to PQ_PIPELINE_ON. That should > make the condition true and prevent an infinite loop, right? > If you put this explanation to the inline comment, things would get clearer. But based on this explanation, I just got the other doubt. When a pipeline is aborted, res is NULL, but we still stay in the for loop, PQClear(res) will do nothing, then the “for” loop is similar to an empty loop, would that lead to a high CPU usage? From this perspective, when pipeline is aborted, while waiting for PIPELINE_SYNC, adding a tiny sleep might be better. I will back to work next Monday, then I will try to run a test and reproduce the scenario of pipeline abort. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-07T09:33:17Z
On Fri, Nov 7, 2025 at 9:07 AM Chao Li <li.evan.chao@gmail.com> wrote: > If you put this explanation to the inline comment, things would get clearer. But based on this explanation, I just got the other doubt. When a pipeline is aborted, res is NULL, but we still stay in the for loop, PQClear(res) will do nothing, then the “for” loop is similar to an empty loop, would that lead to a high CPU usage? From this perspective, when pipeline is aborted, while waiting for PIPELINE_SYNC, adding a tiny sleep might be better. You're concerned about cases where the server response is delayed, causing the pipeline status to take time to reach PIPELINE_SYNC, right? In that situation, since discardAvailableResults() waits on PQgetResult(), it shouldn't enter a busy loop, correct? > I will back to work next Monday, then I will try to run a test and reproduce the scenario of pipeline abort. I plan to commit the patch soon, but let's keep discussing and investigating the case you mentioned afterward! Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-10T02:06:35Z
> On Nov 7, 2025, at 17:33, Fujii Masao <masao.fujii@gmail.com> wrote: > > On Fri, Nov 7, 2025 at 9:07 AM Chao Li <li.evan.chao@gmail.com> wrote: >> If you put this explanation to the inline comment, things would get clearer. But based on this explanation, I just got the other doubt. When a pipeline is aborted, res is NULL, but we still stay in the for loop, PQClear(res) will do nothing, then the “for” loop is similar to an empty loop, would that lead to a high CPU usage? From this perspective, when pipeline is aborted, while waiting for PIPELINE_SYNC, adding a tiny sleep might be better. > > You're concerned about cases where the server response is delayed, > causing the pipeline status to take time to reach PIPELINE_SYNC, right? > In that situation, since discardAvailableResults() waits on PQgetResult(), > it shouldn't enter a busy loop, correct? > > >> I will back to work next Monday, then I will try to run a test and reproduce the scenario of pipeline abort. > > I plan to commit the patch soon, but let's keep discussing and > investigating the case you mentioned afterward! > I just did a test. In the test, I inserted a tuple with the same primary key so that the inserts fails by the unique key constraint which breaks the pipeline, and some random select statements followed. And I added some debug messages in discardAvailableResults(), which showed me that the function will discard rest of statements’ results until \endpipeline. As there are anyway limited number of statements before \endpipeline, my concern is actually not valid. So, now I am good with this patch. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-10T04:45:39Z
On Mon, Nov 10, 2025 at 11:07 AM Chao Li <li.evan.chao@gmail.com> wrote: > I just did a test. In the test, I inserted a tuple with the same primary key so that the inserts fails by the unique key constraint which breaks the pipeline, and some random select statements followed. And I added some debug messages in discardAvailableResults(), which showed me that the function will discard rest of statements’ results until \endpipeline. As there are anyway limited number of statements before \endpipeline, my concern is actually not valid. So, now I am good with this patch. Thanks a lot for testing! Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-11T01:50:37Z
On Fri, 7 Nov 2025 18:33:17 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > I plan to commit the patch soon, but let's keep discussing and > investigating the case you mentioned afterward! I'm sorry for the late reply and for not joining the discussion earlier. I've spent some time investigating the code in pgbench and libpq, and it seems to me that your commit looks fine. However, I found another issue related to the --continue-on-error option, where an assertion failure occurs in the following test case: $ cat pgbench_error.sql \startpipeline select 1/0; \syncpipeline select 1; \syncpipeline select 1; \syncpipeline select 1; \endpipeline $ pgbench -f pgbench_error.sql -M extended --continue-on-error -T 1 pgbench (19devel) starting vacuum...end. pgbench: pgbench.c:3594: discardUntilSync: Assertion `res == ((void *)0)' failed. Even after removing the Assert(), we get the following error: pgbench: error: client 0 aborted: failed to exit pipeline mode for rolling back the failed transaction This happens because discardUntilSync() does not expect that a PGRES_TUPLES_OK may be received after \syncpipeline, and also fails to discard all PGRES_PIPELINE_SYNC results when multiple \syncpipeline commands are used. I've attached a patch to fix this. If a PGRES_PIPELINE_SYNC is followed by something other than PGRES_PIPELINE_SYNC or NULL, it means that another PGRES_PIPELINE_SYNC will eventually follow after some other results. In this case, we should reset the receive_sync flag and continue discarding results. I think this fix should be back-patched, since this is not a bug introduced by --continue-on-error. The same assertion failure occurs in the following test case, where transactions are retried after a deadlock error: $ cat deadlock.sql \startpipeline select * from a order by i for update; select 1; \syncpipeline select 1; \syncpipeline select 1; \syncpipeline select 1; \endpipeline $ cat deadlock2.sql \startpipeline select * from a order by i desc for update; select 1; \syncpipeline select 1; \syncpipeline select 1; \syncpipeline select 1; \endpipeline $ pgbench -f deadlock.sql -f deadlock2.sql -j 2 -c 2 -M extended Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-11T02:40:38Z
> On Nov 11, 2025, at 09:50, Yugo Nagata <nagata@sraoss.co.jp> wrote: > > On Fri, 7 Nov 2025 18:33:17 +0900 > Fujii Masao <masao.fujii@gmail.com> wrote: > >> I plan to commit the patch soon, but let's keep discussing and >> investigating the case you mentioned afterward! > > I'm sorry for the late reply and for not joining the discussion earlier. > > I've spent some time investigating the code in pgbench and libpq, and > it seems to me that your commit looks fine. > > However, I found another issue related to the --continue-on-error option, > where an assertion failure occurs in the following test case: > > $ cat pgbench_error.sql > \startpipeline > select 1/0; > \syncpipeline > select 1; > \syncpipeline > select 1; > \syncpipeline > select 1; > \endpipeline > > $ pgbench -f pgbench_error.sql -M extended --continue-on-error -T 1 > pgbench (19devel) > starting vacuum...end. > pgbench: pgbench.c:3594: discardUntilSync: Assertion `res == ((void *)0)' failed. > > Even after removing the Assert(), we get the following error: > > pgbench: error: client 0 aborted: failed to exit pipeline mode for rolling back the failed transaction > > This happens because discardUntilSync() does not expect that a PGRES_TUPLES_OK may be > received after \syncpipeline, and also fails to discard all PGRES_PIPELINE_SYNC results > when multiple \syncpipeline commands are used. > > I've attached a patch to fix this. > If a PGRES_PIPELINE_SYNC is followed by something other than PGRES_PIPELINE_SYNC or NULL, > it means that another PGRES_PIPELINE_SYNC will eventually follow after some other results. > In this case, we should reset the receive_sync flag and continue discarding results. > > I think this fix should be back-patched, since this is not a bug introduced by > --continue-on-error. The same assertion failure occurs in the following test case, > where transactions are retried after a deadlock error: > > $ cat deadlock.sql > \startpipeline > select * from a order by i for update; > select 1; > \syncpipeline > select 1; > \syncpipeline > select 1; > \syncpipeline > select 1; > \endpipeline > > $ cat deadlock2.sql > \startpipeline > select * from a order by i desc for update; > select 1; > \syncpipeline > select 1; > \syncpipeline > select 1; > \syncpipeline > select 1; > \endpipeline > > $ pgbench -f deadlock.sql -f deadlock2.sql -j 2 -c 2 -M extended > > Regards, > Yugo Nagata > > -- > Yugo Nagata <nagata@sraoss.co.jp> > <0001-Make-sure-discardUntilSync-discards-until-the-last-s.patch> Hi Yugo-san, I am also debugging the patch for the other purpose when I saw your email, so I tried to reproduce the problem with your script. I think in master branch, we can simply fix the problem by calling discardAvailableResults(st) before discardUntilSync(st), like this: ``` /* Read and discard until a sync point in pipeline mode */ if (PQpipelineStatus(st->con) != PQ_PIPELINE_OFF) { discardAvailableResults(st); # <=== Add this line if (!discardUntilSync(st)) { st->state = CSTATE_ABORTED; break; } } ``` But this is not good for back-patch. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-11T02:49:16Z
> On Nov 10, 2025, at 12:45, Fujii Masao <masao.fujii@gmail.com> wrote: > > On Mon, Nov 10, 2025 at 11:07 AM Chao Li <li.evan.chao@gmail.com> wrote: >> I just did a test. In the test, I inserted a tuple with the same primary key so that the inserts fails by the unique key constraint which breaks the pipeline, and some random select statements followed. And I added some debug messages in discardAvailableResults(), which showed me that the function will discard rest of statements’ results until \endpipeline. As there are anyway limited number of statements before \endpipeline, my concern is actually not valid. So, now I am good with this patch. > > Thanks a lot for testing! > Hi Fujii-san, I just did more tests on both pipeline mode and non-pipeline mode, I think the main purpose of discardAvailableResults() is to drain results for pipeline mode. In non-pipeline mode, a NULL res indicates no more result to read; while in pipeline mode, when a pipeline is aborted, either a valid result or NULL could still be returned, thus we need to wait until pipeline state switch to PQ_PIPELINE_OK. From this perspective, the current inline comment is correct, but I feel it’s not clear enough. So I am proposing the function comment and inline comment like the following: ``` /* * Read and discard all available results from the connection. * * Non-pipeline mode: * ------------------ * PQgetResult() returns each PGresult in order for the last command sent. * When it returns NULL, that definitively means there are no more results * for that command. We stop on NULL (or on CONNECTION_BAD). * * Pipeline mode: * -------------- * If an earlier command in the pipeline errors, libpq enters the * PQ_PIPELINE_ABORTED state. In this state, PQgetResult() may return * either a valid PGresult or NULL, and a NULL return does NOT mean * that the connection is drained. More results for later commands (or * protocol housekeeping such as the pipeline sync result) can still * arrive afterward. Therefore we must continue calling PQgetResult() * while PQpipelineStatus(conn) == PQ_PIPELINE_ABORTED, even if we see * intermittent NULLs. */ static void discardAvailableResults(CState *st) { PGresult *res = NULL; for (;;) { res = PQgetResult(st->con); /* * Stop when there are no more results *and* the pipeline is not * in the aborted state, or if the connection has failed. */ if ((res == NULL && PQpipelineStatus(st->con) != PQ_PIPELINE_ABORTED) || PQstatus(st->con) == CONNECTION_BAD) break; PQclear(res); } PQclear(res); } ``` What do you think? Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-11T15:20:15Z
On Tue, Nov 11, 2025 at 10:50 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > I've attached a patch to fix this. Thanks for reporting the issue and providing the patch! > If a PGRES_PIPELINE_SYNC is followed by something other than PGRES_PIPELINE_SYNC or NULL, > it means that another PGRES_PIPELINE_SYNC will eventually follow after some other results. > In this case, we should reset the receive_sync flag and continue discarding results. Yes. + if (res) + { + received_sync = false; + continue; Shouldn't we also call PQclear(res) here? For example: --------------------------- if (PQresultStatus(res) == PGRES_PIPELINE_SYNC) received_sync = true; - else if (received_sync) + else if (received_sync && res == NULL) { - /* - * PGRES_PIPELINE_SYNC must be followed by another - * PGRES_PIPELINE_SYNC or NULL; otherwise, assert failure. - */ - Assert(res == NULL); - /* * Reset ongoing sync count to 0 since all PGRES_PIPELINE_SYNC * results have been discarded. @@ -3601,6 +3595,8 @@ discardUntilSync(CState *st) PQclear(res); break; } + else + received_sync = false; PQclear(res); --------------------------- Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-11T15:22:38Z
On Tue, Nov 11, 2025 at 11:41 AM Chao Li <li.evan.chao@gmail.com> wrote: > I am also debugging the patch for the other purpose when I saw your email, so I tried to reproduce the problem with your script. > > I think in master branch, we can simply fix the problem by calling discardAvailableResults(st) before discardUntilSync(st), like this: This change doesn't seem to fix the issue. If the custom script includes many \syncpipeline commands, the assertion failure can still occur. No? Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-11T16:47:37Z
On Tue, Nov 11, 2025 at 11:49 AM Chao Li <li.evan.chao@gmail.com> wrote: > I just did more tests on both pipeline mode and non-pipeline mode, I think the main purpose of discardAvailableResults() is to drain results for pipeline mode. In non-pipeline mode, a NULL res indicates no more result to read; while in pipeline mode, when a pipeline is aborted, either a valid result or NULL could still be returned, thus we need to wait until pipeline state switch to PQ_PIPELINE_OK. From this perspective, the current inline comment is correct, but I feel it’s not clear enough. Thanks for working on this! After reconsidering, I think the main goal here is to determine whether the error causes a connection failure after it occurs. If we can read and discard results without PQstatus() becoming CONNECTION_BAD either until the end (in non-pipeline mode) or until the first sync point after an error (in pipeline mode), that means the connection is still alive, and processing can continue when --continue-on-error is specified. The current function comments don’t mention this purpose enough, so seems they should be updated to clarify that. Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-12T07:47:03Z
On Wed, 12 Nov 2025 00:22:38 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Tue, Nov 11, 2025 at 11:41 AM Chao Li <li.evan.chao@gmail.com> wrote: > > I am also debugging the patch for the other purpose when I saw your email, so I tried to reproduce the problem with your script. > > > > I think in master branch, we can simply fix the problem by calling discardAvailableResults(st) before discardUntilSync(st), like this: > > This change doesn't seem to fix the issue. If the custom script includes > many \syncpipeline commands, the assertion failure can still occur. No? Yes. discardAvailableResults() does not discard all syncs, just until NULL following the first sync, in pipeline mode without a connection failure. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-12T09:33:46Z
On Wed, 12 Nov 2025 00:20:15 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Tue, Nov 11, 2025 at 10:50 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > I've attached a patch to fix this. > > Thanks for reporting the issue and providing the patch! > > > If a PGRES_PIPELINE_SYNC is followed by something other than PGRES_PIPELINE_SYNC or NULL, > > it means that another PGRES_PIPELINE_SYNC will eventually follow after some other results. > > In this case, we should reset the receive_sync flag and continue discarding results. > > Yes. > > + if (res) > + { > + received_sync = false; > + continue; > > Shouldn't we also call PQclear(res) here? For example: Thank you for your review! Yes, we need PQclear() here. I've attached an updated patch. The comment for the PQpipelineSync() call has been also updated to clarify why it is necessary. In addition, I added a connection status check in the loop to avoid an infinte loop that waiting for PQpipelineSync after a connection failure. I packed these changes in the same patch, but they can be split into separate patches. What do you think? Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-12T09:34:17Z
On Wed, 12 Nov 2025 00:20:15 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Tue, Nov 11, 2025 at 10:50 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > I've attached a patch to fix this. > > Thanks for reporting the issue and providing the patch! > > > If a PGRES_PIPELINE_SYNC is followed by something other than PGRES_PIPELINE_SYNC or NULL, > > it means that another PGRES_PIPELINE_SYNC will eventually follow after some other results. > > In this case, we should reset the receive_sync flag and continue discarding results. > > Yes. > > + if (res) > + { > + received_sync = false; > + continue; > > Shouldn't we also call PQclear(res) here? For example: Thank you for your review! Yes, we need PQclear() here. I've attached an updated patch. The comment for the PQpipelineSync() call has been also updated to clarify why it is necessary. In addition, I added a connection status check in the loop to avoid an infinte loop that waiting for PQpipelineSync after a connection failure. I packed these changes in the same patch, but they can be split into separate patches. What do you think? Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-13T02:20:30Z
> On Nov 12, 2025, at 17:34, Yugo Nagata <nagata@sraoss.co.jp> wrote: > > On Wed, 12 Nov 2025 00:20:15 +0900 > Fujii Masao <masao.fujii@gmail.com> wrote: > >> On Tue, Nov 11, 2025 at 10:50 AM Yugo Nagata <nagata@sraoss.co.jp> wrote: >>> I've attached a patch to fix this. >> >> Thanks for reporting the issue and providing the patch! >> >>> If a PGRES_PIPELINE_SYNC is followed by something other than PGRES_PIPELINE_SYNC or NULL, >>> it means that another PGRES_PIPELINE_SYNC will eventually follow after some other results. >>> In this case, we should reset the receive_sync flag and continue discarding results. >> >> Yes. >> >> + if (res) >> + { >> + received_sync = false; >> + continue; >> >> Shouldn't we also call PQclear(res) here? For example: > > Thank you for your review! > Yes, we need PQclear() here. > > I've attached an updated patch. > > The comment for the PQpipelineSync() call has been also updated to clarify > why it is necessary. > > In addition, I added a connection status check in the loop to avoid an > infinte loop that waiting for PQpipelineSync after a connection failure. > > I packed these changes in the same patch, but they can be split into separate > patches. > > What do you think? > > Regards, > Yugo Nagata > > -- > Yugo Nagata <nagata@sraoss.co.jp> > <v2-0001-pgbench-Fix-assertion-failure-with-multiple-syncp.patch> I debugged further this morning, and I think I have found the root cause. Ultimately, the problem is not with discardUntilSync(), instead, discardAvailableResults() mistakenly eats PGRES_PIPELINE_SYNC. In my debug, I slightly updated Yugo’s script as: (every select returns a different value) ``` % cat pgbench_error.sql \startpipeline select 1/0; \syncpipeline select 2; \syncpipeline select 3; \syncpipeline select 4; \endpipeline ``` Please see my dirty fix in the attachment. The diff is based master + Yugo’s v2 patch. In my fix, I make discardAvailableResults() to return the PGRES_PIPELINE_SYNC it reads, and moved discardAvailableResults() out of getSQLErrorStatus(), so that if discardAvailableResults() returns a result, then use the result as next_res to continue the reading loop. Here is my execution output: ``` % pgbench -n --failures-detailed --continue-on-error -M extended -t 5 -f pgbench_error.sql evantest pgbench (19devel) EVAN: readCommandResponse: Got result: res=7, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: discardAvailableResults: Got result: res=10, conn=0 EVAN: discardAvailableResults: Got sync, returning, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 2, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 3, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 4, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=7, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: discardAvailableResults: Got result: res=10, conn=0 EVAN: discardAvailableResults: Got sync, returning, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 2, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 3, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 4, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=7, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: discardAvailableResults: Got result: res=10, conn=0 EVAN: discardAvailableResults: Got sync, returning, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 2, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 3, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 4, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=7, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: discardAvailableResults: Got result: res=10, conn=0 EVAN: discardAvailableResults: Got sync, returning, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 2, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 3, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 4, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=7, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: discardAvailableResults: Got result: res=10, conn=0 EVAN: discardAvailableResults: Got sync, returning, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 2, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 3, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=2, conn=0 EVAN: readCommandResponse2: Got next-result value: 4, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 EVAN: readCommandResponse: Got result: res=10, conn=0 EVAN: readCommandResponse2: Got result: next_res=7, conn=0 EVAN: readCommandResponse: completed, conn=0 transaction type: pgbench_error.sql scaling factor: 1 query mode: extended number of clients: 1 number of threads: 1 maximum number of tries: 1 number of transactions per client: 5 number of transactions actually processed: 5/5 number of failed transactions: 0 (0.000%) number of serialization failures: 0 (0.000%) number of deadlock failures: 0 (0.000%) number of other failures: 0 (0.000%) latency average = 0.265 ms initial connection time = 2.092 ms tps = 3773.584906 (without initial connection time) ``` You can see that, select 2/3/4 are properly handled. Yugo-san, if you add some debug log, you will see that with your patch, 2 and 3 will be discarded by discardUntilSync(), so I don’t think your patch works. To apply my dirty diff: * git checkout master * git am Yugo’s v2 patch * git apply dirty-fix.diff Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-13T02:53:52Z
On Wed, 12 Nov 2025 01:47:37 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Tue, Nov 11, 2025 at 11:49 AM Chao Li <li.evan.chao@gmail.com> wrote: > > I just did more tests on both pipeline mode and non-pipeline mode, I think the main purpose of discardAvailableResults() is to drain results for pipeline mode. In non-pipeline mode, a NULL res indicates no more result to read; while in pipeline mode, when a pipeline is aborted, either a valid result or NULL could still be returned, thus we need to wait until pipeline state switch to PQ_PIPELINE_OK. From this perspective, the current inline comment is correct, but I feel it’s not clear enough. > > Thanks for working on this! > > After reconsidering, I think the main goal here is to determine whether > the error causes a connection failure after it occurs. > > If we can read and discard results without PQstatus() becoming CONNECTION_BAD > either until the end (in non-pipeline mode) or until the first sync point > after an error (in pipeline mode), that means the connection is still alive, > and processing can continue when --continue-on-error is specified. > > The current function comments don’t mention this purpose enough, > so seems they should be updated to clarify that. I agree that the goal of this function is to discard results until the point where a connection failure can be detected. When the socket reaches EOF, PQgetResult() returns PGRES_FATAL_ERROR to report it, followed by NULL. However, in an aborted pipeline, several NULLs following each PGRES_PIPELINE_ABORTED may be returned before that, so we need to discard those NULLs beforehand. Considering this, the function name "discardAvailableResults" might be a bit misleading, since it doesn’t actually discard all available results. How about renaming it to something like "discardForErrorStatusCheck" (a bit long, though)? Related to this, I doubt the necessity of calling this function after the error: label in readCommandResponse(). If the error is retriable, all results will be discarded later by discardUntilSync(). If it’s not retriable, the thread will immediately exit and the connection will be abandoned, so discarding results here seems unnecessary. If discardAvailableResults() is unnecessary here, we could embed its logic into getSQLErrorStatus() instead of leaving it as a separate function. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-13T02:55:25Z
On Wed, Nov 12, 2025 at 6:34 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > I've attached an updated patch. Thanks for updating the patch! > The comment for the PQpipelineSync() call has been also updated to clarify > why it is necessary. + /* + * If a PGRES_PIPELINE_SYNC is followed by something other than + * PGRES_PIPELINE_SYNC or NULL, another PGRES_PIPELINE_SYNC will + * eventually follow. + */ LGTM. I'd like to append "Reset received_sync to false to wait for it." into this comment. > In addition, I added a connection status check in the loop to avoid an > infinte loop that waiting for PQpipelineSync after a connection failure. Would it be better to move this status check right after PQgetResult() so that connection failures can be detected regardless of what result it returns? + pg_log_error("client %d aborted: the backend died while rolling back the failed transaction after", The trailing “after” seems unnecessary. Since there's no guarantee the backend actually died in this case, it might be better to use something like "client %d aborted while rolling back the transaction after an error; perhaps the backend died while processing" which matches the wording used under CSTATE_WAIT_ROLLBACK_RESULT in advanceConnectionState(). Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-13T03:47:11Z
On Thu, Nov 13, 2025 at 11:21 AM Chao Li <li.evan.chao@gmail.com> wrote: > I debugged further this morning, and I think I have found the root cause. Ultimately, the problem is not with discardUntilSync(), instead, discardAvailableResults() mistakenly eats PGRES_PIPELINE_SYNC. Thanks for debugging! Yes, discardAvailableResults() can discard PGRES_PIPELINE_SYNC, but do you mean that's the root cause of the assertion failure Nagata-san reported? Since that failure can occur even in older branches, I was thinking that newer code like discardAvailableResults() in master isn't the root cause... Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-13T04:02:42Z
> On Nov 13, 2025, at 11:47, Fujii Masao <masao.fujii@gmail.com> wrote: > > On Thu, Nov 13, 2025 at 11:21 AM Chao Li <li.evan.chao@gmail.com> wrote: >> I debugged further this morning, and I think I have found the root cause. Ultimately, the problem is not with discardUntilSync(), instead, discardAvailableResults() mistakenly eats PGRES_PIPELINE_SYNC. > > Thanks for debugging! > > Yes, discardAvailableResults() can discard PGRES_PIPELINE_SYNC, > but do you mean that's the root cause of the assertion failure > Nagata-san reported? > Since that failure can occur even in older branches, I was thinking > that newer code > like discardAvailableResults() in master isn't the root cause... > I haven’t debugged with old code, but the old code also discard non-NULL results: ``` - do - { - res = PQgetResult(st->con); - PQclear(res); - } while (res); + discardAvailableResults(st); ``` Which may also discard the sync message. That’s my guess. I can also debug the old code this afternoon. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-13T05:14:37Z
> On Nov 13, 2025, at 12:02, Chao Li <li.evan.chao@gmail.com> wrote: > > > >> On Nov 13, 2025, at 11:47, Fujii Masao <masao.fujii@gmail.com> wrote: >> >> On Thu, Nov 13, 2025 at 11:21 AM Chao Li <li.evan.chao@gmail.com> wrote: >>> I debugged further this morning, and I think I have found the root cause. Ultimately, the problem is not with discardUntilSync(), instead, discardAvailableResults() mistakenly eats PGRES_PIPELINE_SYNC. >> >> Thanks for debugging! >> >> Yes, discardAvailableResults() can discard PGRES_PIPELINE_SYNC, >> but do you mean that's the root cause of the assertion failure >> Nagata-san reported? >> Since that failure can occur even in older branches, I was thinking >> that newer code >> like discardAvailableResults() in master isn't the root cause... >> > > I haven’t debugged with old code, but the old code also discard non-NULL results: > > ``` > - do > - { > - res = PQgetResult(st->con); > - PQclear(res); > - } while (res); > + discardAvailableResults(st); > ``` > > Which may also discard the sync message. That’s my guess. I can also debug the old code this afternoon. > I just tried the old code but it didn’t trigger the assert with Yugo’s deadlock scripts. I did "git reset --hard a3ea5330fcf47390c8ab420bbf433a97a54505d6”, that is the previous commit of “—continue-on-error”. And I ran Yugo’s deadlock scripts, but I didn’t get the assert: ``` % pgbench -n --failures-detailed -M extended -j 2 -c 2 -f deadlock.sql -f deadlock2.sql evantest pgbench (19devel) transaction type: multiple scripts scaling factor: 1 query mode: extended number of clients: 2 number of threads: 2 maximum number of tries: 1 number of transactions per client: 10 number of transactions actually processed: 20/20 number of failed transactions: 0 (0.000%) number of serialization failures: 0 (0.000%) number of deadlock failures: 0 (0.000%) latency average = 0.341 ms initial connection time = 2.637 ms tps = 5865.102639 (without initial connection time) SQL script 1: deadlock.sql - weight: 1 (targets 50.0% of total) - 12 transactions (60.0% of total) - number of transactions actually processed: 12 (tps = 3519.061584) - number of failed transactions: 0 (0.000%) - number of serialization failures: 0 (0.000%) - number of deadlock failures: 0 (0.000%) - latency average = 0.311 ms - latency stddev = 0.304 ms SQL script 2: deadlock2.sql - weight: 1 (targets 50.0% of total) - 8 transactions (40.0% of total) - number of transactions actually processed: 8 (tps = 2346.041056) - number of failed transactions: 0 (0.000%) - number of serialization failures: 0 (0.000%) - number of deadlock failures: 0 (0.000%) - latency average = 0.366 ms - latency stddev = 0.364 ms ``` Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-13T05:50:33Z
On Thu, 13 Nov 2025 13:14:37 +0800 Chao Li <li.evan.chao@gmail.com> wrote: > > > > On Nov 13, 2025, at 12:02, Chao Li <li.evan.chao@gmail.com> wrote: > > > > > > > >> On Nov 13, 2025, at 11:47, Fujii Masao <masao.fujii@gmail.com> wrote: > >> > >> On Thu, Nov 13, 2025 at 11:21 AM Chao Li <li.evan.chao@gmail.com> wrote: > >>> I debugged further this morning, and I think I have found the root cause. Ultimately, the problem is not with discardUntilSync(), instead, discardAvailableResults() mistakenly eats PGRES_PIPELINE_SYNC. > >> > >> Thanks for debugging! > >> > >> Yes, discardAvailableResults() can discard PGRES_PIPELINE_SYNC, > >> but do you mean that's the root cause of the assertion failure > >> Nagata-san reported? > >> Since that failure can occur even in older branches, I was thinking > >> that newer code > >> like discardAvailableResults() in master isn't the root cause... > >> > > > > I haven’t debugged with old code, but the old code also discard non-NULL results: > > > > ``` > > - do > > - { > > - res = PQgetResult(st->con); > > - PQclear(res); > > - } while (res); > > + discardAvailableResults(st); > > ``` > > > > Which may also discard the sync message. That’s my guess. I can also debug the old code this afternoon. > > > > I just tried the old code but it didn’t trigger the assert with Yugo’s deadlock scripts. To trigger a deadlock error, the tables need to have enough rows so that the scan takes some time. In my environment, about 1,000 rows were enough to cause a deadlock. Regards, Yugo Nagata > > I did "git reset --hard a3ea5330fcf47390c8ab420bbf433a97a54505d6”, that is the previous commit of “—continue-on-error”. And I ran Yugo’s deadlock scripts, but I didn’t get the assert: > > ``` > % pgbench -n --failures-detailed -M extended -j 2 -c 2 -f deadlock.sql -f deadlock2.sql evantest > pgbench (19devel) > transaction type: multiple scripts > scaling factor: 1 > query mode: extended > number of clients: 2 > number of threads: 2 > maximum number of tries: 1 > number of transactions per client: 10 > number of transactions actually processed: 20/20 > number of failed transactions: 0 (0.000%) > number of serialization failures: 0 (0.000%) > number of deadlock failures: 0 (0.000%) > latency average = 0.341 ms > initial connection time = 2.637 ms > tps = 5865.102639 (without initial connection time) > SQL script 1: deadlock.sql > - weight: 1 (targets 50.0% of total) > - 12 transactions (60.0% of total) > - number of transactions actually processed: 12 (tps = 3519.061584) > - number of failed transactions: 0 (0.000%) > - number of serialization failures: 0 (0.000%) > - number of deadlock failures: 0 (0.000%) > - latency average = 0.311 ms > - latency stddev = 0.304 ms > SQL script 2: deadlock2.sql > - weight: 1 (targets 50.0% of total) > - 8 transactions (40.0% of total) > - number of transactions actually processed: 8 (tps = 2346.041056) > - number of failed transactions: 0 (0.000%) > - number of serialization failures: 0 (0.000%) > - number of deadlock failures: 0 (0.000%) > - latency average = 0.366 ms > - latency stddev = 0.364 ms > ``` > > Best regards, > -- > Chao Li (Evan) > HighGo Software Co., Ltd. > https://www.highgo.com/ > > > > -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-13T06:54:28Z
> On Nov 13, 2025, at 13:50, Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > To trigger a deadlock error, the tables need to have enough rows so that the scan takes some > time. In my environment, about 1,000 rows were enough to cause a deadlock. > Yes, after inserting 1000 rows, I got the assert triggered. I added some logs to track what had been read: ``` % pgbench -n --failures-detailed -M extended -j 2 -c 2 -f deadlock.sql -f deadlock2.sql evantest pgbench (19devel) EVAN: on error discard: Got result: res=11, conn=0 EVAN: on error discard: Got result: res=7, conn=0 EVAN: discardUntilSync: Got result: res=10, conn=0 <== received sync EVAN: discardUntilSync: Got sync, conn=0 EVAN: discardUntilSync: Got result: res=2, conn=0 <== then immediately received result of next select, without a null res in between EVAN: discardUntilSync: Got result value: 2, conn=0 Assertion failed: (res == ((void*)0)), function discardUntilSync, file pgbench.c, line 3579. zsh: abort pgbench -n --failures-detailed -M extended -j 2 -c 2 -f deadlock.sql -f ``` Looks like there is not a null result following the PIPELINE_SYNC message. So the code comment seems to not accurate: ``` /* * PGRES_PIPELINE_SYNC must be followed by another * PGRES_PIPELINE_SYNC or NULL; otherwise, assert failure. */ Assert(res == NULL); ``` Then I made a dirty change that return from discardUntilSync() once receives SYNC: ``` if (PQresultStatus(res) == PGRES_PIPELINE_SYNC) { printf("EVAN: discardUntilSync: Got sync, conn=%d\n", PQstatus(st->con)); received_sync = true; st->num_syncs = 0; PQclear(res); break; } ``` that eliminates the assert: ``` % pgbench -n --failures-detailed -M extended -j 2 -c 2 -f deadlock.sql -f deadlock2.sql evantest pgbench (19devel) EVAN: on error discard: Got result: res=11, conn=0 EVAN: on error discard: Got result: res=7, conn=0 EVAN: discardUntilSync: Got result: res=10, conn=0 EVAN: discardUntilSync: Got sync, conn=0 pgbench: error: client 0 aborted: failed to exit pipeline mode for rolling back the failed transaction transaction type: multiple scripts scaling factor: 1 query mode: extended number of clients: 2 number of threads: 2 maximum number of tries: 1 number of transactions per client: 10 number of transactions actually processed: 10/20 number of failed transactions: 0 (0.000%) number of serialization failures: 0 (0.000%) number of deadlock failures: 0 (0.000%) latency average = 203.933 ms initial connection time = 3.006 ms tps = 9.807152 (without initial connection time) SQL script 1: deadlock.sql - weight: 1 (targets 50.0% of total) - 8 transactions (80.0% of total) - number of transactions actually processed: 8 (tps = 7.845722) - number of failed transactions: 0 (0.000%) - number of serialization failures: 0 (0.000%) - number of deadlock failures: 0 (0.000%) - latency average = 127.115 ms - latency stddev = 332.002 ms SQL script 2: deadlock2.sql - weight: 1 (targets 50.0% of total) - 2 transactions (20.0% of total) - number of transactions actually processed: 2 (tps = 1.961430) - number of failed transactions: 0 (0.000%) - number of serialization failures: 0 (0.000%) - number of deadlock failures: 0 (0.000%) - latency average = 1.347 ms - latency stddev = 0.207 ms pgbench: error: Run was aborted; the above results are incomplete. ``` So, I think now the key problem is to confirm if there must be a NULL following PGRES_PIPELINE_SYNC. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-13T07:09:29Z
On Thu, 13 Nov 2025 11:55:25 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Wed, Nov 12, 2025 at 6:34 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > I've attached an updated patch. > > Thanks for updating the patch! > > > The comment for the PQpipelineSync() call has been also updated to clarify > > why it is necessary. > > + /* > + * If a PGRES_PIPELINE_SYNC is followed by something other than > + * PGRES_PIPELINE_SYNC or NULL, another PGRES_PIPELINE_SYNC will > + * eventually follow. > + */ > > LGTM. I'd like to append "Reset received_sync to false to wait for > it." into this comment. > > > > In addition, I added a connection status check in the loop to avoid an > > infinte loop that waiting for PQpipelineSync after a connection failure. > > Would it be better to move this status check right after PQgetResult() > so that connection failures can be detected regardless of what result > it returns? > > + pg_log_error("client %d aborted: the backend died while rolling back > the failed transaction after", > > The trailing “after” seems unnecessary. > > Since there's no guarantee the backend actually died in this case, > it might be better to use something like "client %d aborted while rolling back > the transaction after an error; perhaps the backend died while processing" > which matches the wording used under CSTATE_WAIT_ROLLBACK_RESULT > in advanceConnectionState(). Thank you for your review! I've attached an updated patch reflecting your suggestion. Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp> -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-13T08:13:30Z
> On Nov 13, 2025, at 15:09, Yugo Nagata <nagata@sraoss.co.jp> wrote: > > On Thu, 13 Nov 2025 11:55:25 +0900 > Fujii Masao <masao.fujii@gmail.com> wrote: > >> On Wed, Nov 12, 2025 at 6:34 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: >>> I've attached an updated patch. >> >> Thanks for updating the patch! >> >>> The comment for the PQpipelineSync() call has been also updated to clarify >>> why it is necessary. >> >> + /* >> + * If a PGRES_PIPELINE_SYNC is followed by something other than >> + * PGRES_PIPELINE_SYNC or NULL, another PGRES_PIPELINE_SYNC will >> + * eventually follow. >> + */ >> >> LGTM. I'd like to append "Reset received_sync to false to wait for >> it." into this comment. >> >> >>> In addition, I added a connection status check in the loop to avoid an >>> infinte loop that waiting for PQpipelineSync after a connection failure. >> >> Would it be better to move this status check right after PQgetResult() >> so that connection failures can be detected regardless of what result >> it returns? >> >> + pg_log_error("client %d aborted: the backend died while rolling back >> the failed transaction after", >> >> The trailing “after” seems unnecessary. >> >> Since there's no guarantee the backend actually died in this case, >> it might be better to use something like "client %d aborted while rolling back >> the transaction after an error; perhaps the backend died while processing" >> which matches the wording used under CSTATE_WAIT_ROLLBACK_RESULT >> in advanceConnectionState(). > > Thank you for your review! > I've attached an updated patch reflecting your suggestion. > > Regards, > Yugo Nagata > > -- > Yugo Nagata <nagata@sraoss.co.jp> > <v3-0001-pgbench-Fix-assertion-failure-with-multiple-syncp.patch> With v3 patch, the assert is gone, but test result is no longer accurate, because discardAvailableResults() discarded PIPELINE_SYNC messages. This is my test result with v3: ``` % pgbench -n --failures-detailed -M extended -j 2 -c 2 -f deadlock.sql -f deadlock2.sql evantest pgbench (19devel) EVAN: discardAvailableResults: discarding result: res=11, conn=0 EVAN: discardAvailableResults: discarding result: res=7, conn=0 EVAN: discardAvailableResults: discarding result: res=10, conn=0 EVAN: discardAvailableResults: discarding result: res=2, conn=0 EVAN: discardAvailableResults: discarding result value: 6, conn=0 EVAN: discardAvailableResults: discarding result: res=10, conn=0 EVAN: discardAvailableResults: discarding result: res=2, conn=0 EVAN: discardAvailableResults: discarding result value: 7, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got result: res=2, conn=0 EVAN: discardUntilSync: discarding result value=8, conn=0 EVAN: discardUntilSync: Got result: res=7, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got NULL, conn=0 EVAN: discardAvailableResults: discarding result: res=11, conn=0 EVAN: discardAvailableResults: discarding result: res=7, conn=0 EVAN: discardAvailableResults: discarding result: res=10, conn=0 EVAN: discardAvailableResults: discarding result: res=2, conn=0 EVAN: discardAvailableResults: discarding result value: 6, conn=0 EVAN: discardAvailableResults: discarding result: res=10, conn=0 EVAN: discardAvailableResults: discarding result: res=2, conn=0 EVAN: discardAvailableResults: discarding result value: 7, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got result: res=2, conn=0 EVAN: discardUntilSync: discarding result value=8, conn=0 EVAN: discardUntilSync: Got result: res=7, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got NULL, conn=0 EVAN: discardAvailableResults: discarding result: res=11, conn=0 EVAN: discardAvailableResults: discarding result: res=7, conn=0 EVAN: discardAvailableResults: discarding result: res=10, conn=0 EVAN: discardAvailableResults: discarding result: res=2, conn=0 EVAN: discardAvailableResults: discarding result value: 2, conn=0 EVAN: discardAvailableResults: discarding result: res=10, conn=0 EVAN: discardAvailableResults: discarding result: res=2, conn=0 EVAN: discardAvailableResults: discarding result value: 3, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got result: res=2, conn=0 EVAN: discardUntilSync: discarding result value=4, conn=0 EVAN: discardUntilSync: Got result: res=7, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got NULL, conn=0 EVAN: discardAvailableResults: discarding result: res=11, conn=0 EVAN: discardAvailableResults: discarding result: res=7, conn=0 EVAN: discardAvailableResults: discarding result: res=10, conn=0 EVAN: discardAvailableResults: discarding result: res=2, conn=0 EVAN: discardAvailableResults: discarding result value: 6, conn=0 EVAN: discardAvailableResults: discarding result: res=10, conn=0 EVAN: discardAvailableResults: discarding result: res=2, conn=0 EVAN: discardAvailableResults: discarding result value: 7, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got result: res=2, conn=0 EVAN: discardUntilSync: discarding result value=8, conn=0 EVAN: discardUntilSync: Got result: res=7, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got NULL, conn=0 EVAN: discardAvailableResults: discarding result: res=11, conn=0 EVAN: discardAvailableResults: discarding result: res=7, conn=0 EVAN: discardAvailableResults: discarding result: res=10, conn=0 EVAN: discardAvailableResults: discarding result: res=2, conn=0 EVAN: discardAvailableResults: discarding result value: 2, conn=0 EVAN: discardAvailableResults: discarding result: res=10, conn=0 EVAN: discardAvailableResults: discarding result: res=2, conn=0 EVAN: discardAvailableResults: discarding result value: 3, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got result: res=2, conn=0 EVAN: discardUntilSync: discarding result value=4, conn=0 EVAN: discardUntilSync: Got result: res=7, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got SYNC, conn=0 EVAN: discardUntilSync: Got NULL, conn=0 transaction type: multiple scripts scaling factor: 1 query mode: extended number of clients: 2 number of threads: 2 maximum number of tries: 1 number of transactions per client: 10 number of transactions actually processed: 15/20 number of failed transactions: 5 (25.000%) number of serialization failures: 0 (0.000%) number of deadlock failures: 5 (25.000%) number of other failures: 0 (0.000%) latency average = 502.741 ms (including failures) initial connection time = 2.882 ms tps = 2.983644 (without initial connection time) SQL script 1: deadlock.sql - weight: 1 (targets 50.0% of total) - 11 transactions (55.0% of total) - number of transactions actually processed: 9 (tps = 1.790186) - number of failed transactions: 2 (18.182%) - number of serialization failures: 0 (0.000%) - number of deadlock failures: 2 (18.182%) - number of other failures: 0 (0.000%) - latency average = 336.030 ms - latency stddev = 472.160 ms SQL script 2: deadlock2.sql - weight: 1 (targets 50.0% of total) - 9 transactions (45.0% of total) - number of transactions actually processed: 6 (tps = 1.193457) - number of failed transactions: 3 (33.333%) - number of serialization failures: 0 (0.000%) - number of deadlock failures: 3 (33.333%) - number of other failures: 0 (0.000%) - latency average = 335.757 ms - latency stddev = 472.107 ms ``` We can see: * number of transactions actually processed: 15/20 * number of failed transactions: 5 (25.000%) However, with the dirty diff I sent in the morning: ``` % pgbench -n --failures-detailed -M extended -j 2 -c 2 -f deadlock.sql -f deadlock2.sql evantest … omit debug logs … transaction type: multiple scripts scaling factor: 1 query mode: extended number of clients: 2 number of threads: 2 maximum number of tries: 1 number of transactions per client: 10 number of transactions actually processed: 20/20 number of failed transactions: 0 (0.000%) number of serialization failures: 0 (0.000%) number of deadlock failures: 0 (0.000%) number of other failures: 0 (0.000%) latency average = 302.863 ms initial connection time = 2.749 ms tps = 6.603655 (without initial connection time) SQL script 1: deadlock.sql - weight: 1 (targets 50.0% of total) - 11 transactions (55.0% of total) - number of transactions actually processed: 11 (tps = 3.632010) - number of failed transactions: 0 (0.000%) - number of serialization failures: 0 (0.000%) - number of deadlock failures: 0 (0.000%) - number of other failures: 0 (0.000%) - latency average = 275.532 ms - latency stddev = 445.629 ms SQL script 2: deadlock2.sql - weight: 1 (targets 50.0% of total) - 9 transactions (45.0% of total) - number of transactions actually processed: 9 (tps = 2.971645) - number of failed transactions: 0 (0.000%) - number of serialization failures: 0 (0.000%) - number of deadlock failures: 0 (0.000%) - number of other failures: 0 (0.000%) - latency average = 336.150 ms - latency stddev = 472.091 ms ``` Now, all transactions are processed, there is no failure, I think that is expected, because syncpipeline should rollback failures, so that all script should succeed. Feels to me like, because of introducing the new discardAvailableResults(), we need to make different fixes for master and old branches. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-13T09:16:04Z
On Thu, 13 Nov 2025 16:13:30 +0800 Chao Li <li.evan.chao@gmail.com> wrote: > Now, all transactions are processed, there is no failure, I think that is expected, because syncpipeline should rollback failures, so that all script should succeed. > > Feels to me like, because of introducing the new discardAvailableResults(), we need to make different fixes for master and old branches. I understand your claim that scripts rolled back by \syncpipeline should be considered successful. However, I believe treating them as failed transactions is the expected behavior in pgbench, since it assumes that a transaction script contains only one transaction, as described in the documentation [1]. The following script: \startpipeline <queries list 1> \syncpipeline <queries list 2> \endpipeline can be considered equivalent to: BEGIN; <queries list 1> END; BEGIN; <queries list 2> END; with respect to the scope of queries rolled back. In the latter script, an error (such as a deadlock or serialization failure) in any query is recorded as a failed transaction in the current pgbench, even if part of the script has already been committed. Therefore, the same behavior would be expected for the former script using a pipeline. [1] https://www.postgresql.org/docs/current/pgbench.html#FAILURES-AND-RETRIES Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-13T09:40:36Z
On Thu, 13 Nov 2025 16:13:30 +0800 Chao Li <li.evan.chao@gmail.com> wrote: > Now, all transactions are processed, there is no failure, I think that is expected, because syncpipeline should rollback failures, so that all script should succeed. > > Feels to me like, because of introducing the new discardAvailableResults(), we need to make different fixes for master and old branches. I understand your claim that scripts rolled back by \syncpipeline should be considered successful. However, I believe treating them as failed transactions is the expected behavior in pgbench, since it assumes that a transaction script contains only one transaction, as described in the documentation [1]. The following script: \startpipeline <queries list 1> \syncpipeline <queries list 2> \endpipeline can be considered equivalent to: BEGIN; <queries list 1> END; BEGIN; <queries list 2> END; with respect to the scope of queries rolled back. In the latter script, an error (such as a deadlock or serialization failure) in any query is recorded as a failed transaction in the current pgbench, even if part of the script has already been committed. Therefore, the same behavior would be expected for the former script using a pipeline. [1] https://www.postgresql.org/docs/current/pgbench.html#FAILURES-AND-RETRIES Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-13T10:17:37Z
> On Nov 13, 2025, at 17:40, Yugo Nagata <nagata@sraoss.co.jp> wrote: > > The following script: > > \startpipeline > <queries list 1> > \syncpipeline > <queries list 2> > \endpipeline > > can be considered equivalent to: > > BEGIN; > <queries list 1> > END; > BEGIN; > <queries list 2> > END; This looks like that every \sysnpipeline will start a new transaction, is that true? Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-13T12:00:33Z
On Thu, 13 Nov 2025 18:17:37 +0800 Chao Li <li.evan.chao@gmail.com> wrote: > > > > On Nov 13, 2025, at 17:40, Yugo Nagata <nagata@sraoss.co.jp> wrote: > > > > The following script: > > > > \startpipeline > > <queries list 1> > > \syncpipeline > > <queries list 2> > > \endpipeline > > > > can be considered equivalent to: > > > > BEGIN; > > <queries list 1> > > END; > > BEGIN; > > <queries list 2> > > END; > > This looks like that every \sysnpipeline will start a new transaction, is that true? Yes, it causes a new transaction to start. In a pipeline, an implicit transaction block is started, and \syncpipeline closes it. Then, a new implicit transaction begins. Here’s a simple example to illustrate this: $ cat pipeline_tx.sql drop table if exists tbl; create table tbl (i int); \startpipeline insert into tbl values(1); insert into tbl values(2); \syncpipeline insert into tbl values(3); insert into tbl values(4); \endpipeline $ pgbench -f pipeline_tx.sql -t 1 -M extended -n > /dev/null $ psql -c "select xmin, i from tbl" xmin | i ------+--- 1268 | 1 1268 | 2 1269 | 3 1269 | 4 (4 rows) Regards, Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Chao Li <li.evan.chao@gmail.com> — 2025-11-14T07:44:38Z
> On Nov 13, 2025, at 21:55, Fujii Masao <masao.fujii@gmail.com> wrote: > > On Thu, Nov 13, 2025 at 4:09 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: >> Thank you for your review! >> I've attached an updated patch reflecting your suggestion. > > Thanks for updating the patch! LGTM. > > You mentioned that the assertion failure could occur when using \syncpipeline, > but it seems that multiple PGRES_PIPELINE_SYNC results can also appear > even without it, which can still trigger the same issue. For example, > I was able to reproduce the assertion failure in v16 (which doesn't support > \syncpipeline) with the following setup: > > -------------------------------- > $ cat deadlock.sql > \startpipeline > select * from a order by i for update; > select 1; > \endpipeline > > $ cat deadlock2.sql > \startpipeline > select * from a order by i desc for update; > select 1; > \endpipeline > > $ psql -c "create table a (i int primary key); insert into a > values(generate_series(1,1000));" > > $ pgbench -n -j 4 -c 4 -T 5 -M extended -f deadlock.sql -f deadlock2.sql > ... > Assertion failed: (res == ((void *)0)), function discardUntilSync, > file pgbench.c, line 3479. > -------------------------------- > > So I've updated the commit message to clarify that while using \syncpipeline > makes the failure more likely, it can still occur without it. Since the issue > can also happen in v15 and v16 (which both lack \syncpipeline), I plan to > backpatch the fix to v15. The failure doesn't occur in v14 because it doesn't > support retriable error retries. > > I've also made a few cosmetic tweaks to the patch. Attached is the updated > version, which I plan to push. > > Regards, > > -- > Fujii Masao > <v4-0001-pgbench-PG15-PG16-Fix-assertion-failure-when-discarding-res.txt><v4-0001-pgbench-Fix-assertion-failure-when-discarding-res.patch> I think I was misunderstanding that “\syncpipeline” would recover the transaction. Once the confusion is resolved, I think v4 patch is overall good. Only one small comment: ``` + else if (received_sync && res == NULL) { - /* - * PGRES_PIPELINE_SYNC must be followed by another - * PGRES_PIPELINE_SYNC or NULL; otherwise, assert failure. - */ - Assert(res == NULL); - /* * Reset ongoing sync count to 0 since all PGRES_PIPELINE_SYNC * results have been discarded. @@ -3601,6 +3610,15 @@ discardUntilSync(CState *st) PQclear(res); break; } ``` As we now add “res==NULL” to the “else if”, once entering "else if (received_sync && res == NULL)”, res must be NULL, so "PQclear(res);” should be deleted. Leaving it there doesn’t harm today, but is error-prone, because if in future someone removes “res==NULL” from the “else if”, it will lead to double memory free, because after “break”, PQclear(res) will be called again. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/ -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-14T07:50:40Z
On Thu, 13 Nov 2025 22:55:53 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Thu, Nov 13, 2025 at 4:09 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > Thank you for your review! > > I've attached an updated patch reflecting your suggestion. > > Thanks for updating the patch! LGTM. > > You mentioned that the assertion failure could occur when using \syncpipeline, > but it seems that multiple PGRES_PIPELINE_SYNC results can also appear > even without it, which can still trigger the same issue. For example, > I was able to reproduce the assertion failure in v16 (which doesn't support > \syncpipeline) with the following setup: > > -------------------------------- > $ cat deadlock.sql > \startpipeline > select * from a order by i for update; > select 1; > \endpipeline > > $ cat deadlock2.sql > \startpipeline > select * from a order by i desc for update; > select 1; > \endpipeline > > $ psql -c "create table a (i int primary key); insert into a > values(generate_series(1,1000));" > > $ pgbench -n -j 4 -c 4 -T 5 -M extended -f deadlock.sql -f deadlock2.sql > ... > Assertion failed: (res == ((void *)0)), function discardUntilSync, > file pgbench.c, line 3479. > -------------------------------- > > So I've updated the commit message to clarify that while using \syncpipeline > makes the failure more likely, it can still occur without it. Since the issue > can also happen in v15 and v16 (which both lack \syncpipeline), I plan to > backpatch the fix to v15. The failure doesn't occur in v14 because it doesn't > support retriable error retries. I could not reproduce it with the latest REL_16_STABLE branch. Perhaps, the assertion failure you mentioned above was the one fixed by 1d3ded521? Or, I am missing something... > I've also made a few cosmetic tweaks to the patch. Attached is the updated > version, which I plan to push. Thank you for updating the patch. By the way, your prevous email has not been archived [1]. I guess it was not received by the server due to some issue. Therefore, I've attached patches you've sent. [1] https://www.postgresql.org/list/pgsql-hackers/since/202511130000/ -- Yugo Nagata <nagata@sraoss.co.jp>
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-14T09:08:24Z
On Fri, Nov 14, 2025 at 4:50 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > I could not reproduce it with the latest REL_16_STABLE branch. > Perhaps, the assertion failure you mentioned above was the one > fixed by 1d3ded521? Yeah, you're right! Thanks for catching that. I've updated the commit message to explicitly mention the \syncpipeline command. Patch attached. Since the assertion failure can occur in versions that support \syncpipeline, the fix doesn't need to be backpatched to v16 or older. Regards, -- Fujii Masao
-
Re: Suggestion to add --continue-client-on-abort option to pgbench
Fujii Masao <masao.fujii@gmail.com> — 2025-11-14T09:15:27Z
On Fri, Nov 14, 2025 at 4:45 PM Chao Li <li.evan.chao@gmail.com> wrote: > ``` > + else if (received_sync && res == NULL) > { > - /* > - * PGRES_PIPELINE_SYNC must be followed by another > - * PGRES_PIPELINE_SYNC or NULL; otherwise, assert failure. > - */ > - Assert(res == NULL); > - > /* > * Reset ongoing sync count to 0 since all PGRES_PIPELINE_SYNC > * results have been discarded. > @@ -3601,6 +3610,15 @@ discardUntilSync(CState *st) > PQclear(res); > break; > } > ``` > > As we now add “res==NULL” to the “else if”, once entering "else if (received_sync && res == NULL)”, res must be NULL, so "PQclear(res);” should be deleted. OK, the PQclear() there is unnecessary, so I removed it in the patch I posted earlier. Regards, -- Fujii Masao -
Re: Suggestion to add --continue-client-on-abort option to pgbench
Yugo Nagata <nagata@sraoss.co.jp> — 2025-11-17T13:52:07Z
On Fri, 14 Nov 2025 18:08:24 +0900 Fujii Masao <masao.fujii@gmail.com> wrote: > On Fri, Nov 14, 2025 at 4:50 PM Yugo Nagata <nagata@sraoss.co.jp> wrote: > > I could not reproduce it with the latest REL_16_STABLE branch. > > Perhaps, the assertion failure you mentioned above was the one > > fixed by 1d3ded521? > > Yeah, you're right! Thanks for catching that. > > I've updated the commit message to explicitly mention the \syncpipeline command. > Patch attached. > > Since the assertion failure can occur in versions that support \syncpipeline, > the fix doesn't need to be backpatched to v16 or older. Thank you for updating and pushing the patch! Yugo Nagata -- Yugo Nagata <nagata@sraoss.co.jp>