Question

I have 2 non-transactional tables. I want to perform an 'insert' on one and 'update' on another.

I want to do this atomically, both should go through or both should not.

How to achieve this for non-transactional tables? I'm using MySql

Was it helpful?

Solution

Use locking:

LOCK TABLES t1, t2 WRITE;
...
UNLOCK TABLES;

NOTE: if any of the queries fail, you'll have to roll them back manually! So make sure you collect INSERT_ID()s or some other ways to determine the rows you're inserting. (10x ring0)

If this happens too often in your application — you'll get awful performance.. In this case you'd better switch to InnoDB with its row-locking feature and transactions.

And make sure you ALWAYS either disconnect right after this operation or issue the UNLOCK TABLES query! Otherwise (like forgetting to unlock/dying with an exception while using persistent connection to DB — you'll end up with a deadlock on these tables!)

OTHER TIPS

Without the transactions mechanism, you need to protect the read and write code that will access the database.

Some pseudo-code to perform the write and read operations, in critical sections, protected via a semaphore:

Semaphore sem;

bool method write (data) {
  lock(sem);
  ok  = do (insert data into table);
  prevdata = do (select olddata from table2);
  ok2 = do (update data into table2);
  if (ok && !ok2) do (delete date from table);
  else if (!ok && ok2) do (update olddata into table2);
  unlock(sem);
  return (ok && ok2);
}

datacontainer method read () {
  lock (sem);
  data = do (select data from table);
  unlock(sem);
  return data;
}

datacontainer method read2 () {
  lock (sem);
  data = do (select data from table2);
  unlock(sem);
  return data;
}

The synchronization can be optimized depending on your needs.

If you could use InnoDB, it is much simpler: in MySQL code

START TRANSACTION;
INSERT INTO table (...) VALUES (...);
UPDATE table2 SET data=... WHERE ...;
COMMIT;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top