I would implement it as follows:
Have a collection of data that is waiting to be saved protected by a lock.
When a thread has new data to be saved, acquire the lock on the collection, add the data to the collection, and release the lock.
Have a "save thread" (or save job, or whatever is appropriate for your language or threading library) that periodically acquires the lock on the collection, swaps the collection for an empty collection, releases the lock, and then saves all the data in the collection in a single SQL transaction.