一.什么是事务
在计算机科学中,事务(transaction)是指访问并可能更新数据库中各种数据项的一个程序执行单元。事务由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如Begin Transaction和End Transaction语句(或函数调用)来界定。事务由事务开始和事务结束之间执行的全体操作组成。
例如,在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。
事务应该具有4个属性:原子性,一致性,隔离性,持续性。(ACID特性)
1.原子性:指整个数据库事务是不可分割的工作单位。只有使据库中所有的操作执行成功,才算整个事务成功;事务中任何一个SQL语句执行失败,那么已经执行成功的SQL语句也必须撤销,数据库状态应该退回到执行事务前的状态。
2.一致性:指数据库事务不能破坏关系数据的完成性以及业务逻辑上的一致性。例如对银行转帐事务,不管事务成功还是失败,应该保证事务结束后ACCOUNTS表中Tom和Jack的存款总额为2000元。
3.隔离性:指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。
4.持久性:指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
锁就是防止其他事务访问指定资源的手段。锁是实现并发空值的主要方法,是多个用户能够同时操纵同一个数据库中的数据而不发生数据不一致现象的保障。
二.事务的语法
MySQL通过SET AUTOCOMMIT,START TRANSACTION,COMMIT和ROLLBACK等语句支持本地事务。
当一个成功的事务完成后,发出COMMIT命令应使所有参与表的更改才会生效。
如果发生故障时,应发出一个ROLLBACK命令返回的事务中引用的每一个表到以前的状态。
可以控制的事务行为称为AUTOCOMMIT设置会话变量。如果AUTOCOMMIT设置为1(默认值),然后每一个SQL语句(在事务与否)被认为是一个完整的事务,并承诺在默认情况下,当它完成。 AUTOCOMMIT设置为0时,发出SET AUTOCOMMIT =0命令,在随后的一系列语句的作用就像一个事务,直到一个明确的COMMIT语句时,没有活动的提交。
可以通过使用mysql_query()函数在PHP中执行这些SQL命令。
BEGIN WORK开始事务发出SQL命令发出一个或多个SQL命令,如SELECT,INSERT,UPDATE或DELETE
检查是否有任何错误,一切都依据的需要。
如果有任何错误,那么问题ROLLBACK命令,否则发出COMMIT命令。
MySQL支持事务的相关语法如下:
START TRANSACTION | BEGIN [WORK]
COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
SET AUTOCOMMIT = {0 | 1}
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
START TRANSACTION 或BEGIN 语句可以开始一项新的任务。COMMIT可以提交当前事务,时变得更成为永久变更。ROLLBACK可以回滚当前事务,取消其变更。
SET AUTOCOMMIT 语句可以禁用或启用默认的AUTOCOMMIT模式,用于当前连接。
CHAIN 和RELEASE可以被用于对事务完成进行附加的控制。AND CHAIN字句会在当前事务结束时,立刻启动一个新事务,并且与刚结束的事务有相同的隔离等级。
RELEASE子句在终止了当前事务后,会让服务器断开与当前客户端的链接。包含NO关键词可以抑制CHAIN或RELEASE完成。
默认情况下,MySQL采用AUTOCOMMIT模式运行。也就是说,当执行一个用于更新表的语句之后,MySQL立刻把更新存储到磁盘中。可以用下面语句禁用:
SET AUTOCOMMIT=0;
禁用后,必须用COMMIT把变更存储到磁盘中;或者如果突然想要忽略从事务开始进行以来做出的变更,使用ROLLBACK。
START TRANSACTION是标准的SQL语法,BEGIN 和BEGIN WORK可以看作是START TRANSACTION的别名,用于对事务的初始化。
默认情况下,SET TRANSACTION用于为紧邻的下一个事务(还未开始)设置隔离等级。
1、脏读(dirty read):一个事务可以读取另一个尚未提交事务的修改数据。
2、非重复读(nonrepeatable read):在同一个事务中,同一个查询在T1时间读取某一行,在T2时间重新读取这一行时候,这一行的数据已经发生修改,可能被更新了(update),也可能被删除了(delete)。
3、幻像读(phantom read):在同一事务中,同一查询多次进行时候,由于其他插入操作(insert)的事务提交,导致每次返回不同的结果集。
不同的隔离级别有不同的现象,并有不同的锁定/并发机制,隔离级别越高,数据库的并发性就越差,4种事务隔离级别分别表现的现象如下表:
隔离级别 | 脏读 | 非重复读 | 幻像读 |
read uncommitted | 允许 | 允许 | 允许 |
read committed | 允许 | 允许 | |
repeatable read | 允许 | ||
serializable |
保存点:通过保存点机制:用户可以在事物里用savepoint name命令设置一些保存点,以后用户在使用rollback to savepoint name结束事物时,name之前的数据保存,之后的数据不保存。
mysql使用事务的关键字
begin //打开一个事务
commit //提交到数据库
rollback //取消操作
savepoint //保存,部分取消,部分提交
alter table person type=INNODB //修改数据引擎
示例如下:
begin
update person set name='efgh' where id =10
select * from person
rollback
select * from person
示例如下:
alter table person type=INNODB
begin
update person set name='efgh' where id =10
select * from person
commit
select * from person
begin
delete from person where id=21
update person set name='efgh' where id =10
commit/rollback
1.只能取消到某个保存点 rollback to savepoint p1
2.不能提交某个保存 commit to savepoint p2//错误写法
3.最后commit 把未取消的保存点去不提交到数据
事务保存点使用例子:
begin;
update score set score=40 where scoreid=1;
savepoint s1;
update score set score=50 where scoreid=2;
select * from score;
rollback to savepoint s1;
select * from score;
commit;
三.事务的使用
在MySQL数据库中已经存在下面的SQL语句创建一张表dbtest:
CREATE TABLE dbtest(id int(4)) TYPE=INNODB;
我们创建一个简单的事务处理,用于插入记录:
BEGIN
INSERT INTO dbtest value(1);
INSERT INTO dbtest value(2);
COMMIT;
要更新锁操作,使用LOCK TABLES,首先必须拥有相关表的LOCK TABLES权限和SELECT权限。
我们下面定义一个锁:
LOCK TABLES trans READ,customer WRITE;
SELECT SUM(value) FROM trans WHERE customer_id=some_id;
UPDATE customer
SET total_value=sum_from_previous_statement WHERE customer_id=some_id
UNLOCK TABLES;