I assume that you wish to ignore the second update. There are other scenarios (e.g. instead of inserting a new row, updating certain fields of the existing row), but I infer that you're looking for something called
AddOrIgnore rather than
There are some possible avenues here, some better than others.
Blocking at the application level.
This seems the easiest to implement, but it's not the best solution. There will be a minimal amount of time between checking for existence and saving the object. In that inbetween time, a row could be inserted and you would still end up with duplicate data.
Race conditions are notoriously hard to debug, so I suggest avoiding them at all costs.
Blocking at the database level.
Database locking gives you the ability to prevent the race condition.
However, if you're expecting a lot of concurrent access to that table (for different objects, whose statuses would never collide), then this may become a bottleneck for performance.
I'm not sure if the locking can be guaranteed to apply to every update to the table. Because if it cannot, then you run the risk of other parties forgetting to implement blocking behavior.
Cleaning up after the fact.
This is easier to implement but may end up causing a bit more work. This only applies in cases where your status update does not return a value, and you're not interested in alerting the user/application that a duplicate was found (but instead continue working as normal).
The benefit is that you don't need to block the behavior, and you can simply clean the data afterwards (removing any duplicates). Depending on avoiding duplicates being business critical; you could schedule this as a job. Or you could create a task to check this (preferably in a fire-and-forget separate thread).
The drawback is that you may end up having to undo the work you just did, which is extra work. If your server will be pressed for performance, then more work will always be a bad thing. The question here is how often you expect to run into collisions, and how much you'll be pressed for performance on the server.
A second benefit is that the original request is not slowed down by doing an additional check, and you instead delegate the checking behavior to a secondary thread/task/scheduled job.
This highly depends on your environment.
If you're creating a highly used service where duplicate entries are rare and nothing more than an aesthetic flaw, then blocking would create a bottleneck for everyone. Adding and cleaning, however, will only block those requests which happen to run into a rare collision.
If you're creating a service where duplicate entries can cause major issues, then you should focus on blocking instead of cleaning after the fact.
If you're creating a service where duplicate entries are a common occurrence, then cleaning behavior cause extra work too often. If duplicates are not causing issues, you could clean it up in a scheduled job. If duplicates are causing issues, you should focus on blocking behavior.