When I noticed the duplicate rows in the table, I reduced the performance test to make one GET request to get a unique key (itself based on a unique value from a .csv row), and then make a POST request that creates a single row containing said key in a database table. The GET requests calls pm.variables.set to set a variable with this unique key, and the POST request has a field in its request body set to its value. Running this serially for each .csv row in a functional works precisely as expected, there’s exactly one database row for each request, all of them distinct and containing this key.
When I run this as a performance test, with a delay introduced in the post-request script so I can end it after the first round of requests, I get the same number of rows, but I get duplicates among them. The only way this makes sense, when it does not happen in one-at-a-time functional testing, is if the variable the POST request is using is somehow being set by a GET request from another virtual user, i.e. one user’s GET sets the variable to 123456, and another user’s POST sends that value even though its GET fetches/sets the value as 456789.
There is the (very stupid) possibility that the vendor-supplied server software we’re testing is somehow squashing the values received by simultaneous requests, but performance testing gives very limited ability to see the requests that it sent so I can’t really check this directly. I tried making the POST request to a deliberately invalid server so I could see the errors/the bodies of the requests that caused them, but that seems to arbitrarily pick one .csv row to use in its example error even know I know for a fact the same error happened with all of them.
EDIT: I went testing some more, to catch patterns of repeated rows, and found that I was actually getting very consistent repeats for given numbers of virtual users. When I have 15, for instance, I get this set of order no each time for the same .csv file
Similarly for 20 VU’s
I also found that if I use pm.iterationData instead of pm.variables, I consistently get all the same shop order (sometimes the last in the .csv, sometimes another; this also appears to be consistent across multiple runs with the same number of VU’s), instead of multiple-with-duplicates; this also does not happen with one-by-one functional testing, where it is in order from top to bottom. These together suggest a bug, albeit not a concurrency one, in mapping virtual users to the .csv file (yes I am using ordered VU data mapping), which I’ll include for reference/to indicate that it does not include duplicates.
ShopOrder,Machine
240721,SB101
240722,SB102
240723,SB103
240724,SB104
240725,SB105
240726,SB106
240727,SB107
240728,SB109
240729,SB113
240730,SB201
240731,SB202
240732,SB203
240733,SB204
240734,SB205
240735,SB206
240736,SB207
240737,SB208
240738,SB209
240739,SB211
240740,SB212
240741,SB301
240742,SB303
240743,SB304
240744,SB306
240745,SB307
240746,SB308
240747,SB314
240748,SB401
240749,SB403
240750,SB404
240751,SB405
240752,SB406
240753,SB407
240754,SB408
240755,SB409
240756,SB410
240757,SB411
240758,SB412
EDIT 2: While the initial GET request to get the key for each .csv row is necessary in the general case, to narrow this down further I made a .csv containing the fetched keys for all of the above to take the pm.variable.set completely out of the equation, and got the exact same results. This doesn’t totally rule out variable scope leaking across virtual users like I initially suspected (the JSON body still references them with the double-curly brackets), but this further reinforces something being wrong with the VU-.csv mapping.