The AdWords API uses an optimistic concurrency control mechanism. When the server begins to process a request, it checkpoints the current state of the relevant account, then executes the business logic and validation rules in the request. Before committing the requested change, the server again checkpoints the account. If the “before and after” checks don’t match, the server returns a concurrency error to ensure that the request doesn’t introduce data inconsistency.
A concurrency issue occurs when two different applications or two different instances or threads of the same application attempt to change a single piece of data at the same time. Let’s say that request1 and request2 both want to operate on the same original version of some data. If request1 changes the data first and is committed, request2 becomes invalid, because it’s trying to operate on data that is now out-of-date.
A concurrency issue doesn’t occur only when your application tries to modify an entity that’s changed during processing. A problem can also occur if the entity that your request modifies has a dependency on another entity that’s been changed. For example, an ad group entity references a campaign. If your request modifies an ad group and the referenced campaign is modified while your request is executing, you’ll get an error.
In an exception to this general rule, we’ve recently introduced the ability to make concurrent changes to some services, such as AdGroupCriterionService and AdGroupAdService. However, the principle still applies at the field level: field-level changes are exclusive to one request at a time.
In the past, you might have gotten a CONCURRENT_MODIFICATION error even when using a single-threaded application to modify one account at a time. The problem was likely due to background processing, such as approvals, which also modified the account’s entities. We’ve made some changes that should reduce the likelihood of these errors occurring
To summarize, when you get a concurrency error, consider whether the application has done one of the following:
- Run multiple threads that attempted to modify the same entity
- Modified an entity on which another entity is dependent