事务就是一组DML(数据操纵语言)语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。事务还规定不同的客户端看到的数据是不相同的。
事务的一些基本操作
- 开始一个事务
start transaction;
- 创建一个保存点
savepoint 保存点名;
- 回到保存点
rollback to 保存点名;
例:
我们先创建一个测试表:
create table account(
-> id int primary key,
-> name varchar(50) not null default ' ',
-> balance decimal(10,2) not null default 0.0
-> );
mysql> start transaction; ----开启一个事务
Query OK, 0 rows affected (0.00 sec)
mysql> savepoint aa;-----设置保存点aa
Query OK, 0 rows affected (0.00 sec)
mysql> insert into account values(1,'张三',10);----添加一条记录
Query OK, 1 row affected (0.01 sec)
mysql> savepoint bb;----设置保存点bb
Query OK, 0 rows affected (0.00 sec)
mysql> insert into account values(2,'王五',500);----再添加一条记录
Query OK, 1 row affected (0.00 sec)
mysql> select * from account;----插入的两条记录都在
+----+------+---------+
| id | name | balance |
+----+------+---------+
| 1 | 张三 | 10.00 |
| 2 | 王五 | 500.00 |
+----+------+---------+
2 rows in set (0.00 sec)
mysql> rollback to bb;----发现bb之后添加的记录是错的,所以回滚到bb状态
Query OK, 0 rows affected (0.00 sec)
mysql> select * from account;----bb之后添加的记录没了
+----+------+---------+
| id | name | balance |
+----+------+---------+
| 1 | 张三 | 10.00 |
+----+------+---------+
1 row in set (0.00 sec)
事务操作要注意的事项
- 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用rollback(前提是事务还没有提交)
- 如果一个事务被提交了(commit),则不可以回退(rollback)
- 可以选择回退到哪个保存点
- InnoDB支持事务,MyISAM不支持事务
- 开始事务可以使用
start transaction
如果事务没有隔离性会带来哪些问题?
- 脏读
是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库,这时,另一个事务也访问这个数据,然后使用了这个数据。
例:
- 李磊考试实际只考了59分,但老师登成绩的时候,看错了,登成了80
- 李磊看到自己的成绩很开心
- 可是老师在打算提交的时候,又核对了一遍,发现成绩登录有误,回滚了事务,李磊的成绩又变为了59
像这样,李磊读取的成绩80是一个脏数据
- 不可重读(update 读出的结果不同 重点在于修改)
是指一个事务内,多次读同一数据。在这个事务还没结束时,另一个事务也访问该同一数据并修改了它,由于第二个事务修改了数据,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读(也就是不能读到相同的数据内容)。
例:
- 在事务1中,李磊读到自己的成绩是80,操作没有完成
- 在事务2中,这时老师修改了李磊的成绩为59,并提交了事务
- 在事务1中,李磊再次读自己的成绩,成绩变为了59
如何解决?
如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。
- 幻读(insert 读出数据量不一 例如:第一次读了10条数据,第二次读了11条数据)
是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这个修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。之后操作第一个事务的用户就会发现虽然自己把全部的数据行都修改了,但是还是有没有修改的数据行,就好像发生幻觉一样。
例:
现在成绩为80的有3个人
- 事务1,读取所有成绩为80的学生
- 这时事务2向成绩表中插入了一条学生记录,成绩也是80
- 事务1再次读取所有成绩为80的员工,一共读取到了4条记录
如何解决?
如果在操作事务完成数据处理之前,任何其他事务都不可以添加新数据,则可以避免这个问题的发生。
innoDB增加了版本号,可解决幻读问题。
事务的隔离级别
设置事务的隔离级别
set session transaction isolation level read uncommitted;
查看当前的隔离级别
mySql> select @@tx_isolation;
事务的ACID特性
- 原子性(Atomicity):
事务是应用中最小的执行单位,就如原子是自然界的最小颗粒,具有不可再分的特征一样,事务是应用中不可再分的最小逻辑执行体。 - 一致性(Consistency):
事务执行的结果,必须使数据库从一个一致性状态变到另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而改未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不确定(不一致)的状态。因此一致性是通过原子性来保证的。 - 隔离性(Isolation):
各个事务的执行互不干扰,任意一个事务的内部操作对其他并发事务都是隔离的。也就是说,并发执行的事务之间不能看到对方的中间状态,并发执行的事务之间不能相互影响。 - 持久性(Durability):
持久性是指一个事务一旦被提交,它对数据库所做的改变都要记录到永久存储器中(磁盘…)