views:

890

answers:

4

Hello, I'm building an iPhone app / web application, and I'm trying to think through the best way to have two-way sync of the databases. I'll probably go with sqlite on the iPhone and mysql on the web (as that's what I know) but am unsure of how to handle keeping them in sync.

Here's a sample schema:

index_id(autoincrement) | title | amount | user_id | created(datetime)

Similar thread

+1  A: 

This is an issue because you have to deal with certain situations like. A = Server, B = iPhone

A - Adds new entry
B - Adss new entry
A - Get B's entry
B - Get A's entry
A - Update entry
B - Delete A's entry

(Which one do you use, do you sync over the change to B that A made or do you delete the item on B that A made?)

The syncing part can be a simple push/pull style http request, it's the logistics of how to properly keep them in sync that raises concerns.

For the How to: Simply have the iPhone check a server page(update.php) for any changes along with it's changes. Update the server with the changes the iPhone sent and update the iPhone with any changes that request sends back(using JSON or XML).

Ryan Detzel
I agree with your approach - how do you monitor those changes? If both databases have autoincrementing ID's, how do you compare the two? Theoretically, the only unique part of a row is the index_id (created is probably unique to in practice), but you could have two entries, one on the phone and one on the server, with identical title/amount/user_id. How would you know what to sync and what to leave alone?
thekevinscott
A: 

Why don't you have your web application provide a secure/authenticated web service for your iPhone clients?

For example, iPhones would communicate with this service (using JSON,XML,SOAP,whatever) and you only have to maintain ONE database.

David Christiansen
That's definitely a possibility, but I'd like to provide offline access (underground) for the iPhone app, thus the syncing.
thekevinscott
+3  A: 

Okay, I've had two subsequent ideas for how to approach this, thought it'd be better as an answer than an edit:

1) You have two databases, one for the phone and one for the web app. The schema would look like this:

index_id | title | amount | user_id | created | environment | foreign_id

So let's say I have an entry on my mobile device: 1,'Title',2.00,1,NOW() and an entry on my web app, 1,'Something',5.00,1,NOW() . To avoid these two things conflicting, the web app will add a row saying 2,'Title',2.00,1,NOW(),'mobile',1.

In this way I can maintain all index_id's correctly. This seems like an absolute nightmare to maintain and get right.

2) What if one were to designate a DB (say the web app) as the master and the device as a slave, so that you had one table on the web app and two tables on the device. For the device, you'd have one table 'queues' which, upon network connectivity, would update the live web app database (at the same time clearing itself out), and then the WEB APP database would sync, one way, back to the device's second main table.

Prior to syncronization, the business logic on the device would have to treat the two local tables as one. This seems like an easier beast to tackle than the above.

thekevinscott
This seems like one of the (very rare) instances where GUIDs for PKs are helpful.
jcollum
I think 2) is really the only way to go. You need one of your databases to be "always right" and the other to be "probably right". The phone is "probably right" and talks to the master db to see if it is right. If it's unconnected then it saves its changes locally and marks them as NeedsUpload. SQLite on both is an option. SQLite is appropriate for any site that's getting less than 100k hits/day. I'd start there, migrate to mysql later.
jcollum
@jcollum, your abbreviations fly over my head. Can you elaborate / provide some links?Is there a more elegant way to implement solution 2, besides having two separate tables? Or is that the cleanest solution?
thekevinscott
+2  A: 

Just replicate the schema in both places and toss a timestamp in each row on every table. Then have the client send up its newest timestamp and have the server return rows newer than it.

Easiest way...

Lounges