一.事务
1.事务定义
逻辑上多个DML操作形成的一个整体,多个DML操作要么全都执行成功,要么全都执行失败,如果是DDL的操作会自动提交事务.
2.事务的控制
命令
- start transaction开启事务
- rollback 回滚
- commit提交事务
mysql默认自动提交事务,每个DML执行完毕后,直接提交事务
以下是一个使用例子:
1.首先打开mysql登录,创建一个user表,我事先在表里插入了数据,然后执行start transaction命令,并查询表中数据,如下图所示.
2.执行一条sql语句,删除username为张三的所有数据,然后查询表中剩余数据.
3.如果此时执行rollback命令,会回到在开启事务时还未执行任何命令的时候,如下图表中数据和图1一致
4.再执行delete语句删除,执行commit之后,再查询表中数据是无法回滚到之前未删除时的数据
三.事务的特性ACID
-
原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
-
一致性(Consistency)事务前后数据的完整性必须保持一致。
-
隔离性(Isolation)事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用 户的事务所干扰,多个并发事务之间数据要相互隔离,正常情况下数据库是做不到这一点的,可以设 置隔离级别,但是效率会非常低。
-
持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的, 接下来即使数据库发生故障也不应该对其有任何影响。
四.事务的并发
多个事务同时操作相同的数据
多个事务之间要有一定的隔离策略 我们称之为隔离级别,不同的隔离级别所出现的数据的问题也不同
隔离级别
-
read-uncommitted 一个事务可以读取到另一个事务未提交的数据
-
read-committed 一个事务只能读取到另一个事务提交的数据
-
repeatable-read 可重复读
-
serializable 串行化 所有的事务不以并发形式运行
隔离级别越高,数据的问题就越少,效率就越低,隔离级别的设置看业务对数据的容忍度,选择最低的
事务并发的数据的问题
1 脏读 一个事务读取到了另一个事务未提交的数据
2 不可重复读 在一个事务之内,反复读取数据发现数据不一致(数据记录数不变,数据某一条发生改变)
3 幻读 在一个事务之内反复读取表格,发现表格的记录数变化
4种隔离级别分别出现的问题
read-uncommitted 脏读 不可重复读 幻读
read-committed 不可重复读 幻读
repeatable-read 幻读 (mvcc的加入,理论上的幻读也不存在了)
4.JDBC控制事务
Connection对象可以控制事务是否 自动提交,回滚,提交
public class TestTransaction {
@Test
public void testJDBCTransaction() throws Exception{
/*connection 默认自动提交事务*/
Connection connection = JDBCUtils.getConnection();
// 设置connection不要自动提交事务
connection.setAutoCommit(false);
PreparedStatement pst = connection.prepareStatement("update `user` set username = ? where uid = ?");
try {
pst.setObject(1,"李四");
pst.setObject(2,3);
pst.executeUpdate();
//System.out.println(1/0);
pst.setObject(1,"赵六");
pst.setObject(2,5);
pst.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
connection.rollback();
} finally {
connection.commit();
}
JDBCUtils.release(null,pst,connection);
}
}