it rewrites the same data across all rows
So does campaign_id and variation_id combination exist across multiple rows? What do you mean all rows?
If you source-dive updateOrCreate you should see that it uses firstOrNew to find the first instance matching the attributes given in the first array (or create a new instance with those same attributes); then fills that instance with the values in the second array ($data) and persists this. There is no reason for more than one row to be updated...