Database Tip: Use Transactions
Monday, 27 August 2007
Here's another Database Tip, to follow on from my previous one on creating appropriate indexes. This time the focus is transactions.
For any experienced database developer, using transactions might seem an obvious suggestion, but lightweight databases may
require configuration in order to use transactions. For example, MySql tables use the
MyISAM engine by default, which doesn't support transactions — in order to use transactions you need to set the
storage engine of your tables to InnoDB or BDB. Also, whereas in Oracle, every statement occurs within a transaction, and you need an explicit COMMIT
or ROLLBACK to end the transaction, in databases such as MySQL and SQLite every
statement is its own transaction (and thus committed to the database immediately) unless you explicitly begin a transaction with a
BEGIN statement, or other database configuration command.
Benefits of Transactions
The primary benefit of using transactions is data integrity. Many database uses require storing data to multiple tables, or multiple rows to the same table in order to maintain a consistent data set. Using transactions ensures that other connections to the same database see either all the updates or none of them. This also applies in the case of interrupted connections — if the power goes off in the middle of a transaction, the database engine will roll back the transaction so it is as-if it was never started. If each statement is committed independently, then other connections may see partial updates, and there is no opportunity for automatic rollback on error.
A secondary benefit of using transactions is speed. There is often an overhead associated with actually committing the data to the database. If you've got 1000 rows to insert, committing after every row can cause quite a performance hit compared to committing once after all the inserts. Of course, this can work the other way too — if you do too much work in a transaction then the database engine can consume lots of space storing the not-yet-committed data or caching data for use by other database connections in order to maintain consistency, which causes a performance hit. As with every optimisation, if you're changing the boundaries of your transactions to gain performance, then it is important to measure both before and after the change.
Using Transactions in Oracle
Oracle databases are always in transaction mode, so all that's needed is to decide where to put the COMMIT or
ROLLBACK. When one transaction is finished, another is automatically started. There are some additional options that
can be specified for advanced usage — see the Oracle documentation for these.
INSERT INTO foo (a,b) VALUES (1,'hello');
INSERT INTO foo (a,b) VALUES (2,'goodbye');
COMMIT;
INSERT INTO foo (a,b) VALUES (3,'banana');
COMMIT;
Using Transactions in SQLite
In SQLite, if you wish a transaction to cover more than one statement, then you must use a BEGIN or BEGIN
TRANSACTION statement. The transaction ends when you execute a COMMIT or ROLLBACK statement, and
the database reverts to auto-commit mode where each statement has its own transaction.
BEGIN;
INSERT INTO foo (a,b) VALUES (1,'hello');
INSERT INTO foo (a,b) VALUES (2,'goodbye');
COMMIT;
INSERT INTO foo (a,b) VALUES (3,'banana');
-- implicit COMMIT at end of statement
-- with no preceding BEGIN
Using Transactions in MySQL
As mentioned above, by default all tables use the MyISAM storage engine, so transaction support is disabled. By
changing a table to use the InnoDB or BDB storage engines, transaction support can be enabled. For new
tables, this is done using the ENGINE or TYPE parameters on the CREATE TABLE statement:
CREATE TABLE foo
(
bar INTEGER PRIMARY KEY,
baz VARCHAR(80) NOT NULL
)
ENGINE = InnoDB;
Existing tables can be changed to use the InnoDB storage engine using ALTER TABLE:
ALTER TABLE foo ENGINE = InnoDB;
You can also change the default storage engine using the default-storage-engine server option on the server command
line, or in the server configuration file.
Once all the tables you're using have storage engines that support transactions, you have two choices. For a given connection,
you can set the AUTOCOMMIT session variable to 0, in which case every statement within that connection is
part of a transaction, as for Oracle, or you can leave AUTOCOMMIT set to 1 and start transactions
explicitly as for SQLite. In auto-commit mode for MySQL, transactions are started with BEGIN, BEGIN WORK
or START TRANSACTION. To disable AUTOCOMMIT for the current transaction, use the SET statement:
SET AUTOCOMMIT=0;
You can configure the database to run this statement immediately upon opening a connection using the init_connect
server variable. This can be set in the configuration file, or using the following command:
SET GLOBAL init_connect='SET AUTOCOMMIT=0';
MySQL also supports additional transaction options — check the documentation for details.
Automatic ROLLBACK and COMMIT
One thing to watch out for is code that causes an automatic ROLLBACK or COMMIT. Most databases cause an
automatic ROLLBACK of any open transaction when a connection is closed, so it is important to make sure that all
changes are committed before closing the connection.
Also worth watching out for are commands that cause an automatic COMMIT. The list varies depending on the database,
but generally DDL statements such as CREATE TABLE will cause an automatic commit. It is probably best to avoid
interleaving DML statement with any other type of statement in order to avoid surprises. Check your database documentation for
details.
Posted by Anthony Williams
[/ database /] permanent link
Stumble It!
| Submit to Reddit
| Submit to DZone ![]()
If you liked this post, why not subscribe to the RSS feed
or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Design and Content Copyright © 2005-2025 Just Software Solutions Ltd. All rights reserved. | Privacy Policy
1 Comment
This is such a trick.