上一篇提到了数据库事务的ACID特性,那么谁来保证数据库事务具有ACID呢?其实,只要向数据库系统声明一个事务,数据库系统就会自动保证事务的ACID特性的。那么下面从抽象的概念上来看看怎么声明事务:
----- BEGIN 事务的开始边界
----- COMMIT 事务的正常结束边界,提交事务,永久保存被事务更新后的数据库状态。
----- ROLLBACK 事务的异常结束边界,撤销事务,使数据退回到执行事务前的初始状态。
数据库系统支持以下两种事务模式:
----- 自动提交模式:每个SQL语句都是一个独立的事务,当数据库系统执行完一个SQL语句后,会自动提交事务。
----- 手工提交事务:必须由数据库的客户端显式指定事务开始边界和结束边界。
以MySQL为例,如果我们启动一个MySQL客户端,就会得到一个独立的数据库连接。每个数据库连接都有一个全局变量@@autocommit,表示当前的事务模式,它有两个可选值:
----- 0:表示手工提交模式。
----- 1:默认值,表示自动提交模式。
可以通过SQL命令 SELECT @@autocommit 来查看当前的事务模式。如果想要把当前的事务模式改为手工提交模式,可以使用以下SQL命令 SET autocommit=0 来实现。
还要多说几句,在MySQL中,数据库表分为三种类型:INNODB、BDB、MyISAM。其中前两种类型的表支持数据库事务,而MyISAM类型的表不支持事务。在使用CREATE TABLE命令创建表时默认的类型为MyISAM,如果希望更改的话可以通过如下DLL来进行:
ALTER TABLE table_name TYPE=INNODB;
如果希望在创建时就指定表的类型,可以通过以下DLL来进行:
CREATE TABLE table_name(
.....
.....
) TYPE=INNODB;
好了,下面我们来看几个在实践应用程序中声明事务的模板。
1.在MySQL.exe客户端程序中声明事务
我们以一条插入语句为例,当然如果是自动提交模式的话,每一个SQL语句都是一个单独的事务,我们直接运行以下语句就可以了:
mysql>INSERT INTO qq_account VALUES('leon', 1000);
下面我们看看在手动模式下的命令:
mysql>SET autocommit=0;
mysql>BEGIN;
mysql>INSERT INTO qq_account VALUES('leon', 1000);
mysql>COMMIT;
这样一个事务就完成了,下面我们看一看如何撤销一个事务,很简单也许你已经猜到了吧
mysql>BEGIN;
mysql>INSERT INTO qq_account VALUES('leon', 1000);
mysql>ROLLBACK;
2.在JDBC API中声明事务
没有什么难度,我们直接来看看代码:
没有什么可再说的了,代码详细得已经像是一篇技术文章了,需要注意的是对于新建的Connection实例来说,在默认的情况下采用自动提交的事务模式,通过方法 con.setAutoCommit(false)来设置手动提交模式。
3.在Hibernate API中声明事务
Hibernate封装了JDBC API和JTA API,尽管应用程序可以绕过Hibernate API,直接通过JDBC API和JTA API来声明事务,但是这不利于跨平台的开发,下面我们只考虑Hibernate API的实现:
上面的代码和JDBC API很相像,值得注意的是,在任何时候,一个Session只允许有一个未提交的事务。以下代码对于一个Session同时声明了两个未提交的事务,这是不允许的:
tx1 = session.beginTransaction();
tx2 = session.beginTransaction();
......
tx1.commit();
tx2.commit();
好了,今天就写到这里吧,顺便唠叨一句,看到新的一期《程序员》里面的调查71%的程序员通过写技术BLOG提升自己的技术水平,坚定了自己作技术BLOG的信心,每天都记录下自己的学习轨迹,让自己更加的充实...