While working on #7165 it became apparent that the way we've written the table_update_tracker trigger means we hold long-lived row-level locks. Not sure how big a deal this is at the moment but worth bearing in mind. The trigger does cause issues as #7165 shows.
Claude:
The first tracker write in a transaction takes an exclusive lock on that row and holds it until commit. Any other transaction whose first tracker write hits the same row waits for the whole thing — it stalls on its first insert, because the wait happens inside the trigger that fires straight after it.
For the big submission path that is UploadDatabaseService.mapAndCopy, which is one transaction over an entire upload. A 100,000-sequence submission therefore holds the (sequence_entries, <organism>) tracker row for minutes, and a second submission of the same organism is serialised behind it rather than running alongside.
One sharp edge worth recording: the rows written for metadata_upload_aux_table, sequence_upload_aux_table, groups_table and user_groups_table carry no organism, so there is exactly one row per table shared by everything. Nothing holds those rows for long today: SubmitModel has no transaction of its own, so each UploadDatabaseService call runs in its own, and the long one (mapAndCopy) only reads the aux tables — the writes and the cleanup delete are separate short transactions. But any future change that pulls an aux-table write into a long transaction would serialise submissions across all organisms, and the failure would look like unrelated submissions mysteriously blocking each other.
While working on #7165 it became apparent that the way we've written the
table_update_trackertrigger means we hold long-lived row-level locks. Not sure how big a deal this is at the moment but worth bearing in mind. The trigger does cause issues as #7165 shows.Claude: