57
57
58
58
#define ERRCODE_IN_FAILED_SQL_TRANSACTION "25P02"
59
59
#define ERRCODE_T_R_SERIALIZATION_FAILURE "40001"
60
+ #define ERRCODE_T_R_DEADLOCK_DETECTED "40P01"
60
61
#define ERRCODE_UNDEFINED_TABLE "42P01"
61
62
62
63
/*
@@ -236,6 +237,8 @@ typedef struct StatsData
236
237
* and --latency-limit */
237
238
int64 serialization_failures ;/* number of transactions with
238
239
* serialization failures */
240
+ int64 deadlock_failures ;/* number of transactions with deadlock
241
+ * failures */
239
242
SimpleStats latency ;
240
243
SimpleStats lag ;
241
244
}StatsData ;
@@ -266,6 +269,8 @@ typedef struct
266
269
int64 cnt ;/* transaction count */
267
270
bool serialization_failure ;/* if there was serialization failure
268
271
* during script execution */
272
+ bool deadlock_failure ;/* if there was deadlock failure during
273
+ * script execution */
269
274
int ecnt ;/* error count */
270
275
}CState ;
271
276
@@ -744,6 +749,7 @@ initStats(StatsData *sd, double start_time)
744
749
sd -> cnt = 0 ;
745
750
sd -> skipped = 0 ;
746
751
sd -> serialization_failures = 0 ;
752
+ sd -> deadlock_failures = 0 ;
747
753
initSimpleStats (& sd -> latency );
748
754
initSimpleStats (& sd -> lag );
749
755
}
@@ -753,19 +759,19 @@ initStats(StatsData *sd, double start_time)
753
759
*/
754
760
static void
755
761
accumStats (StatsData * stats ,bool skipped ,bool serialization_failure ,
756
- double lat ,double lag )
762
+ bool deadlock_failure , double lat ,double lag )
757
763
{
758
764
stats -> cnt ++ ;
759
765
760
- if (skipped )
766
+ if (skipped || serialization_failure || deadlock_failure )
761
767
{
762
- /* no latency to record onskipped transactions */
763
- stats -> skipped ++ ;
764
- }
765
- else if (serialization_failure )
766
- {
767
- /* no latency to record on transactions with serialization failures */
768
- stats -> serialization_failures ++ ;
768
+ /* no latency to record onsuch transactions */
769
+ if ( skipped )
770
+ stats -> skipped ++ ;
771
+ if (serialization_failure )
772
+ stats -> serialization_failures ++ ;
773
+ if ( deadlock_failure )
774
+ stats -> deadlock_failures ++ ;
769
775
}
770
776
else
771
777
{
@@ -1908,6 +1914,8 @@ doCustom(TState *thread, CState *st, StatsData *agg)
1908
1914
{
1909
1915
ExecStatusType result_status ;
1910
1916
bool serialization_failure = false;
1917
+ bool deadlock_failure = false;
1918
+ bool in_failed_transaction = false;
1911
1919
1912
1920
/* are we receiver? */
1913
1921
if (commands [st -> state ]-> type == SQL_COMMAND )
@@ -1932,18 +1940,26 @@ doCustom(TState *thread, CState *st, StatsData *agg)
1932
1940
res = PQgetResult (st -> con );
1933
1941
result_status = PQresultStatus (res );
1934
1942
sqlState = PQresultErrorField (res ,PG_DIAG_SQLSTATE );
1935
- serialization_failure = sqlState &&
1936
- (strcmp (sqlState ,ERRCODE_T_R_SERIALIZATION_FAILURE )== 0 ||
1937
- strcmp (sqlState ,ERRCODE_IN_FAILED_SQL_TRANSACTION )== 0 );
1938
- if (serialization_failure )
1939
- st -> serialization_failure = true;
1943
+ if (sqlState ) {
1944
+ serialization_failure =
1945
+ strcmp (sqlState ,ERRCODE_T_R_SERIALIZATION_FAILURE )== 0 ;
1946
+ deadlock_failure =
1947
+ strcmp (sqlState ,ERRCODE_T_R_DEADLOCK_DETECTED )== 0 ;
1948
+ in_failed_transaction =
1949
+ strcmp (sqlState ,ERRCODE_IN_FAILED_SQL_TRANSACTION )== 0 ;
1950
+
1951
+ if (serialization_failure )
1952
+ st -> serialization_failure = true;
1953
+ else if (deadlock_failure )
1954
+ st -> deadlock_failure = true;
1955
+ }
1940
1956
}
1941
1957
1942
1958
/*
1943
1959
* accumulate per-command execution times in thread-local data
1944
1960
* structure, if per-command latencies are requested
1945
1961
*/
1946
- if (is_latencies && !serialization_failure )
1962
+ if (is_latencies && !serialization_failure && ! deadlock_failure )
1947
1963
{
1948
1964
if (INSTR_TIME_IS_ZERO (now ))
1949
1965
INSTR_TIME_SET_CURRENT (now );
@@ -1967,6 +1983,8 @@ doCustom(TState *thread, CState *st, StatsData *agg)
1967
1983
thread -> stats .cnt ++ ;
1968
1984
if (st -> serialization_failure )
1969
1985
thread -> stats .serialization_failures ++ ;
1986
+ if (st -> deadlock_failure )
1987
+ thread -> stats .deadlock_failures ++ ;
1970
1988
}
1971
1989
}
1972
1990
@@ -1978,7 +1996,9 @@ doCustom(TState *thread, CState *st, StatsData *agg)
1978
1996
*/
1979
1997
if (!(result_status == PGRES_COMMAND_OK ||
1980
1998
result_status == PGRES_TUPLES_OK ||
1981
- serialization_failure ))
1999
+ serialization_failure ||
2000
+ deadlock_failure ||
2001
+ in_failed_transaction ))
1982
2002
{
1983
2003
fprintf (stderr ,"client %d aborted in state %d: %s" ,
1984
2004
st -> id ,st -> state ,PQerrorMessage (st -> con ));
@@ -2014,6 +2034,7 @@ doCustom(TState *thread, CState *st, StatsData *agg)
2014
2034
sql_script [st -> use_file ].desc );
2015
2035
st -> is_throttled = false;
2016
2036
st -> serialization_failure = false;
2037
+ st -> deadlock_failure = false;
2017
2038
2018
2039
/*
2019
2040
* No transaction is underway anymore, which means there is
@@ -2048,6 +2069,7 @@ doCustom(TState *thread, CState *st, StatsData *agg)
2048
2069
st -> sleeping = false;
2049
2070
st -> throttling = false;
2050
2071
st -> serialization_failure = false;
2072
+ st -> deadlock_failure = false;
2051
2073
memset (st -> prepared ,0 ,sizeof (st -> prepared ));
2052
2074
2053
2075
/* set default isolation level */
@@ -2316,29 +2338,38 @@ doLog(TState *thread, CState *st, instr_time *now,
2316
2338
if (latency_limit )
2317
2339
fprintf (logfile ," " INT64_FORMAT ,agg -> skipped );
2318
2340
}
2319
- fprintf (logfile ," " INT64_FORMAT ,agg -> serialization_failures );
2341
+ fprintf (logfile ," " INT64_FORMAT " " INT64_FORMAT ,
2342
+ agg -> serialization_failures ,agg -> deadlock_failures );
2320
2343
fputc ('\n' ,logfile );
2321
2344
2322
2345
/* reset data and move to next interval */
2323
2346
initStats (agg ,agg -> start_time + agg_interval );
2324
2347
}
2325
2348
2326
2349
/* accumulate the current transaction */
2327
- accumStats (agg ,skipped ,st -> serialization_failure ,latency ,lag );
2350
+ accumStats (agg ,skipped ,st -> serialization_failure ,
2351
+ st -> deadlock_failure ,latency ,lag );
2328
2352
}
2329
2353
else
2330
2354
{
2331
2355
/* no, print raw transactions */
2356
+ char transaction_label [256 ];
2357
+
2358
+ if (skipped )
2359
+ snprintf (transaction_label ,sizeof (transaction_label ),"skipped" );
2360
+ else if (st -> serialization_failure && st -> deadlock_failure )
2361
+ snprintf (transaction_label ,sizeof (transaction_label ),
2362
+ "serialization and deadlock failures" );
2363
+ else if (st -> serialization_failure || st -> deadlock_failure )
2364
+ snprintf (transaction_label ,sizeof (transaction_label ),"%s failure" ,
2365
+ st -> serialization_failure ?"serialization" :"deadlock" );
2366
+
2332
2367
#ifndef WIN32
2333
2368
2334
2369
/* This is more than we really ought to know about instr_time */
2335
- if (skipped )
2336
- fprintf (logfile ,"%d " INT64_FORMAT " skipped %d %ld %ld" ,
2337
- st -> id ,st -> cnt ,st -> use_file ,
2338
- (long )now -> tv_sec , (long )now -> tv_usec );
2339
- else if (st -> serialization_failure )
2340
- fprintf (logfile ,"%d " INT64_FORMAT " serialization failure %d %ld %ld" ,
2341
- st -> id ,st -> cnt ,st -> use_file ,
2370
+ if (skipped || st -> serialization_failure || st -> deadlock_failure )
2371
+ fprintf (logfile ,"%d " INT64_FORMAT " %s %d %ld %ld" ,
2372
+ st -> id ,st -> cnt ,transaction_label ,st -> use_file ,
2342
2373
(long )now -> tv_sec , (long )now -> tv_usec );
2343
2374
else
2344
2375
fprintf (logfile ,"%d " INT64_FORMAT " %.0f %d %ld %ld" ,
@@ -2347,12 +2378,9 @@ doLog(TState *thread, CState *st, instr_time *now,
2347
2378
#else
2348
2379
2349
2380
/* On Windows, instr_time doesn't provide a timestamp anyway */
2350
- if (skipped )
2351
- fprintf (logfile ,"%d " INT64_FORMAT " skipped %d 0 0" ,
2352
- st -> id ,st -> cnt ,st -> use_file );
2353
- else if (st -> serialization_failure )
2354
- fprintf (logfile ,"%d " INT64_FORMAT " serialization failure %d 0 0" ,
2355
- st -> id ,st -> cnt ,st -> use_file );
2381
+ if (skipped || st -> serialization_failure || st -> deadlock_failure )
2382
+ fprintf (logfile ,"%d " INT64_FORMAT " %s %d 0 0" ,
2383
+ st -> id ,st -> cnt ,transaction_label ,st -> use_file );
2356
2384
else
2357
2385
fprintf (logfile ,"%d " INT64_FORMAT " %.0f %d 0 0" ,
2358
2386
st -> id ,st -> cnt ,latency ,st -> use_file );
@@ -2378,7 +2406,7 @@ processXactStats(TState *thread, CState *st, instr_time *now,
2378
2406
if ((!skipped || agg_interval )&& INSTR_TIME_IS_ZERO (* now ))
2379
2407
INSTR_TIME_SET_CURRENT (* now );
2380
2408
2381
- if (!skipped && !st -> serialization_failure )
2409
+ if (!skipped && !st -> serialization_failure && ! st -> deadlock_failure )
2382
2410
{
2383
2411
/* compute latency & lag */
2384
2412
latency = INSTR_TIME_GET_MICROSEC (* now )- st -> txn_scheduled ;
@@ -2387,8 +2415,8 @@ processXactStats(TState *thread, CState *st, instr_time *now,
2387
2415
2388
2416
if (progress || throttle_delay || latency_limit )
2389
2417
{
2390
- accumStats (& thread -> stats ,skipped ,st -> serialization_failure ,latency ,
2391
- lag );
2418
+ accumStats (& thread -> stats ,skipped ,st -> serialization_failure ,
2419
+ st -> deadlock_failure , latency , lag );
2392
2420
2393
2421
/* count transactions over the latency limit, if needed */
2394
2422
if (latency_limit && latency > latency_limit )
@@ -2399,6 +2427,8 @@ processXactStats(TState *thread, CState *st, instr_time *now,
2399
2427
thread -> stats .cnt ++ ;
2400
2428
if (st -> serialization_failure )
2401
2429
thread -> stats .serialization_failures ++ ;
2430
+ if (st -> deadlock_failure )
2431
+ thread -> stats .deadlock_failures ++ ;
2402
2432
}
2403
2433
2404
2434
if (use_log )
@@ -2407,7 +2437,8 @@ processXactStats(TState *thread, CState *st, instr_time *now,
2407
2437
/* XXX could use a mutex here, but we choose not to */
2408
2438
if (per_script_stats )
2409
2439
accumStats (& sql_script [st -> use_file ].stats ,skipped ,
2410
- st -> serialization_failure ,latency ,lag );
2440
+ st -> serialization_failure ,st -> deadlock_failure ,latency ,
2441
+ lag );
2411
2442
}
2412
2443
2413
2444
@@ -3389,6 +3420,10 @@ printResults(TState *threads, StatsData *total, instr_time total_time,
3389
3420
total -> serialization_failures ,
3390
3421
(100.0 * total -> serialization_failures /total -> cnt ));
3391
3422
3423
+ printf ("number of transactions with deadlock failures: " INT64_FORMAT " (%.3f %%)\n" ,
3424
+ total -> deadlock_failures ,
3425
+ (100.0 * total -> deadlock_failures /total -> cnt ));
3426
+
3392
3427
if (throttle_delay && latency_limit )
3393
3428
printf ("number of transactions skipped: " INT64_FORMAT " (%.3f %%)\n" ,
3394
3429
total -> skipped ,
@@ -3448,6 +3483,11 @@ printResults(TState *threads, StatsData *total, instr_time total_time,
3448
3483
(100.0 * sql_script [i ].stats .serialization_failures /
3449
3484
sql_script [i ].stats .cnt ));
3450
3485
3486
+ printf (" - number of transactions with deadlock failures: " INT64_FORMAT " (%.3f%%)\n" ,
3487
+ sql_script [i ].stats .deadlock_failures ,
3488
+ (100.0 * sql_script [i ].stats .deadlock_failures /
3489
+ sql_script [i ].stats .cnt ));
3490
+
3451
3491
if (latency_limit )
3452
3492
printf (" - number of transactions skipped: " INT64_FORMAT " (%.3f%%)\n" ,
3453
3493
sql_script [i ].stats .skipped ,
@@ -4235,6 +4275,7 @@ main(int argc, char **argv)
4235
4275
stats .cnt += thread -> stats .cnt ;
4236
4276
stats .skipped += thread -> stats .skipped ;
4237
4277
stats .serialization_failures += thread -> stats .serialization_failures ;
4278
+ stats .deadlock_failures += thread -> stats .deadlock_failures ;
4238
4279
latency_late += thread -> latency_late ;
4239
4280
INSTR_TIME_ADD (conn_total_time ,thread -> conn_time );
4240
4281
}
@@ -4391,6 +4432,7 @@ threadRun(void *arg)
4391
4432
st -> sleeping = false;
4392
4433
st -> throttling = false;
4393
4434
st -> serialization_failure = false;
4435
+ st -> deadlock_failure = false;
4394
4436
PQfinish (st -> con );
4395
4437
st -> con = NULL ;
4396
4438
continue ;
@@ -4574,6 +4616,7 @@ threadRun(void *arg)
4574
4616
cur .skipped += thread [i ].stats .skipped ;
4575
4617
cur .serialization_failures +=
4576
4618
thread [i ].stats .serialization_failures ;
4619
+ cur .deadlock_failures += thread [i ].stats .deadlock_failures ;
4577
4620
}
4578
4621
4579
4622
total_run = (now - thread_start ) /1000000.0 ;
@@ -4606,6 +4649,9 @@ threadRun(void *arg)
4606
4649
fprintf (stderr ,", " INT64_FORMAT " serialization failures" ,
4607
4650
(cur .serialization_failures -
4608
4651
last .serialization_failures ));
4652
+ fprintf (stderr ,", " INT64_FORMAT " deadlock failures" ,
4653
+ (cur .deadlock_failures - last .deadlock_failures ));
4654
+
4609
4655
fprintf (stderr ,"\n" );
4610
4656
4611
4657
last = cur ;