说明:在转账业务中,具体到数据库中,操作有两步:
1)把转账人的账户金额 - 转账金额;
2)被转账人的账户金额 + 转账金额;
这两步操作共同执行,才算完成了转账业务,但如果在执行第一步后,发生断电、报错等原因,导致第二步未能执行。对数据的部分操作,导致数据库中的数据失去一致性,而事务就是为了解决这类情况的。
一、事务(Transaction)的特点
事务具有以下四个特点,称为ACID:
原子性(Atomicity):事务包括的代码是最小的执行单元,要么都执行,要么都不执行;
一致性(Consistency):事务执行前后的数据,是一致的。即,要么事务执行失败,数据不发生变化;要么执行成功,数据发生变化;
隔离性(Isolation):事务之间是并行执行,互不影响。如,A事务处于开启事务,未提交状态,此时开启另一个事务,不会产生影响;
持久性(Durability):事务对数据的改变是永久性的;
二、数据库事务操作
教师表(tb_teacher)
部门表(tb_department)
如有以上两张表,教师表d_id字段关联(逻辑外键)部门表中的id;
需求:现在需要删除教研部;
分析:为了保证数据的一致性,教师表中的隶属教研的教师记录也应该删除。所以这是一个需要执行两条SQL语句的操作(删除教研部记录,删除教师表中关联教研部的记录),为了保证这两条SQL语句,任何时候都能同时执行,需要使用事务。
使用事务执行
# 1. 开启事务
start transaction;
# 2. 执行语句
delete from tb_department where id=1;
delete from tb_teacher where d_id=1;
# 3.1 以上执行成功,提交事务
commit;
# 3.2 以上执行失败,回滚事务
rollback;
开启事务,执行语句后,对数据的操作并未开始,只有提交事务时,才会真正修改数据
提交事务
当语句中发生执行报错时,就不能使用commit,需要用rollback。因为如果SQL语句中报错之前的SQL语句可以正常执行的话,此时提交事务,数据库会对数据执行前面未报错的语句,即部分执行。这就不对了,此时就需要执行rollback,结束事务。
如文章开头说的转账业务,事务可以通过try…catch…实现:
……
try{
// 开启事务
// 转账人的账户金额-转账金额
// 被转账人的账户金额+转账金额
// 提交事务(commit)
}catch (Exception e){
// 回滚事务(rollback)
}
总结
值得一提的是,开启事务也可用直接使用MySQL的关键字:begin
# 1. 开启事务
begin;
# 2. 执行语句
delete from tb_department where id=1;
# 语句错误
delete from tb_teacher where d_id=1;
# 3.1 以上执行成功,提交事务
commit;
# 3.2 以上执行失败,回滚事务
rollback;