When everyone tries to modify the same row (a guild vault, a popular auction house item, a server-wide counter), only one request at a time gets the lock.
Why An event or a popular item concentrates updates on the same row → Effect Requests wait until they get the lock → On screen Failed trades, “Please try again later” messages, timeouts
Primary owner Game team (Server development) · Also Infra team (DB infrastructure)
Game team action items
Split the row (sharded counters), keep transactions short, aggregate in memory and apply in one write.
Infra team action items
Monitor row lock wait time and count, find the rows where contention concentrates, and share them.
Ballpark numbers
If one request holds the lock for 10 ms, that row can be modified at most 100 times a second. A round trip to another server inside the transaction cuts that number further.
On the graph
Rises with load · Row lock wait count and time
Where to look
MySQL: growth of Innodb_row_lock_waits and Innodb_row_lock_time plus Innodb_row_lock_current_waits, and sys.innodb_lock_waits to find who is waiting on whom. PostgreSQL: sessions whose wait_event_type is Lock in pg_stat_activity and requests whose granted is false in pg_locks; turning on log_lock_waits (off by default) logs long lock waits
Confirmed if
Lock waits climb steeply with events and player count, and most waiting requests point to the same row (same key) in the same table
Ruled out if
Waits spread evenly across many tables and rows: points to disk or CPU saturation. One session holds a lock for a long time without releasing it: a long-open transaction (db-long-tx)
Check with
Infra tools (no game code needed)
Sources
InnoDB LockingMySQL When one transaction locks a row (index record), other transactions can’t modify that row and wait
How to Minimize and Handle DeadlocksMySQL Recommends keeping transactions small and short and committing right after related changes to reduce conflicts
Server Status VariablesMySQL Innodb_row_lock_waits and Innodb_row_lock_time give the count and total time of row lock waits; Innodb_row_lock_current_waits gives how many are waiting right now