事务:
一组sql语句(insert、update、delete),全部成功整体才算成功,一个失败整体也算失败。
mysql 的事务默认自动打开,自动提交。 一条sql就是一个事务,所以不需要 事务开启、事务回滚、事务提交。
开启事务: start transaction;
执行sql语句群
出现异常 事务回滚(撤销)事务结束 rollback;
无异常 事务提交(生效) 事务结束commit;
start transaction; — 开启事务。以后的sql都在一个事务中。更改的内容不会自动提交。rollback; — 回滚事务,都失败的情况。事务结束,全部失败,数据恢复到事务未开启之前的状态。
commit; — 提交事务,都成功的情况。事务结束,全部成功。
无论是提交还是回滚,都意味着当前事务的结束。
JDBC的事务管理
JDBC的事务管理,是通过Connection对象来完成的。
当JDBC程序向数据库获得一个Connection对象时,默认情况下这个Connection对象会 自动向数据库提交 在它上面的发送的sql语句。
开启事务
setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态。
参数为false,表示禁用自动提交模式,相当于 strart transaction – 开启事务。
参数为true,表示自动提交。默认就是true。 一条sql语句就是一个事务。
开启事务:conn.setAutoCommit(false);
事务回滚
rollback()
取消在当前事务中进行的所有更改,并释放此 Connection 对象当前持有的所有数据库锁。
事务提交
commit()
使所有上一次提交/回滚后进行的更改成为持久更改,并释放此 Connection 对象当前持有的所有数据库锁。
事务的回滚点
类似于游戏的存档功能
Savepoint
设置事务的回滚点:conn.setSavePoint();
撤销保存点以后得操作:conn.rollback(savepoint);
使回滚点以前的操作生效:conn.commit
作用:JDBC使用接口Savapoint表示事务回滚点,当出现异常事务回滚时,使用savapoint 更新回滚点之前的数据。rollback(Savepoint savepoint) 取消所有设置给定 Savepoint 对象之后进行的更改。
事务的特性
事务是并发控制的基本单元。所谓事务一个sql语句操作序列,这些操作要么都执行,要么都不执行,他是一个不可分割的工作单元。例如:银行转账工作,从一个帐号扣款并使另一个帐号增款,这个两个操作,要么都执行,要么都不执行。
数据库的事务必须具备ACID特性,ACID是指 Atomic(原子性)、Consistensy(一致性)、Isolation(隔离型)和Durability(持久性)的英文缩写。
1、原子性(Atomicity)
一个事务中所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中如果发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行一样。
2、一致性(Consistency)
一个事务在执行之前和执行之后 数据库都必须处于一致性状态。如果事务成功的完成,那么数据库的所有变化将生效。如果事务执行出现错误,那么数据库的所有变化将会被回滚(撤销),返回到原始状态。
举例1: a、b 转账 100 a - 100 b + 100
结果: a + b = 2000
举例2:公司部门 和 员工信息,前提是每个员工都有部门
需求:解散一个部门,
分析:删除一个部门 --》 导致员工找不到对应的部门 --》 造成员工的部门信息不一致
解决:应该先删除部门的员工,再删除部门, 保证数据的一致性
3、隔离性(Isolation)
多个用户并发的访问数据库时,一个用户的事务不能被其他用户的事务干扰,多个并发的事务之间要相互隔离。多个事务事件是相互独立的,多个事务事件不能相互干扰。
a -b ----- 事务A
c -d ----- 事务B
如果A失败了,不能影响B。
4、持久性:
指一个事务一旦被提交,它对数据库的改变将是永久性的,接下来即使数据库发生故障也不会对数据产生影响。
举例:a、b转账
a-100
b+100
提交
结果: a 900 b 1100
开启事务 a - 100 出现错误 结果还是不变的。
事务的隔离级别
如果不考虑事务的隔离型,由于事务的并发,将会出现以下问题:
1、脏读 -- 最严重,杜绝发生
2、不可重复读
3、幻读(虚读)
脏读:指一个事务读取了另外一个事务 未提交的数据
不可重复读:在一个事务内多次读取表中的数据,多次读取的结果不同
幻读:指在一个事务中 读取 另一个事务 插入或删除 数据记录,导致当前事务 读取数据前后不一致。
虚读和不可重复读的区别:
虚读 强调的是数据表 记录数 的变化,主要是 insert 和 delete 语句。
不可重复读 强调的是数据表 内容 的变化,主要是 update 语句。
隔离级别
数据库共定义了4种隔离级别(限制由高到低, 性能从低到高):
serializable(串行化):可避免 脏读、不可重复读、虚读情况的发生。
repeatable read(可重复读):可避免 脏读、不可重复读, 不可避免 虚读。mysql采用可重复读。
read committed(读已提交):可避免 脏读,不可避免 不可重复读、虚读。oracle采用读已提交。
read uncommitted(读未提交):不可避免 脏读、不可重复读、虚读。
查询当前数据库的隔离级别:
select @@tx_isolation;
设置事务的隔离级别:
set session transaction isolation level 事务隔离级别;
1、read uncommitted 读未提交
2 read committed 读已提交
可以避免脏读,但读已提交,没有解决 不可重复读
3、repeatable read 可重复读
可重复读的隔离级别可以解决 不可重复读的问题。
4、serializable 串行化
可以避免所有的问题。数据库执行这个事务,其他事务必须等待当前事务执行完毕,才会执行。
mysql的默认隔离级别是 repeatable read;
oracle的默认隔离级别是 read committed;
性能比较:
serializable 性能最差,多个事务排队执行。
serializable < repeatable read < read committed < read uncommitted
安全性比较:
serializable 安全性能最好,所有问题都可以避免
serializable > repeatable read > read committed > read uncommitted
分析:
serializable 性能太差
read uncommitted 无法避免脏读,问题严重