前言

一直在用spring的事务控制,但是始终都没有搞明白他是怎么实现事务控制的,现在还是不能彻底搞清楚,但是看了很多文档明白了一些东西,也不太确定对不对,权当一些个人理解和笔记记录一下,如有不对,还望各位指正。

怎么才算一个事务

首先要明白,jdbc怎么才算一个事务,看下面的代码(这里就不用银行转账的例子了,用一个插入,一个更新操作,但道理是一样的)

//基础代码省略
conn = DriverManager.getConnection(url, dbName, dbPass);
statement = conn.createStatement();
//要执行的sql语句
String sqlUpdate = "update account set money=0 where name='张三'";
String sqlInsert = "insert into account(name, money) values('赵六', 1000)";
statement.execute(sqlUpdate);
statement.execute(sqlInsert);

上面的代码执行了几个事务,两个。一个execute语句完成就执行了一个事务,你可以在两个execute之间手动添加int i=1/0;的异常,你会发现上面的语句完成了对数据库的操作。(PS:以前听过某马班老师的视频说过,完成了对数据库的操作一定是有事务产生的。)

事务控制的实现

通过上面的实验,说明了一个什么问题呢?
一个connection可以有多个事务,这点很重要。
但是上面也没有实现事务的控制啊,我们是想实现更新和插入同时发生(要么一起成功,要么一起失败)。
为什么会这样呢?那是因为jdbc默认是开启自动提交事务的,也就是说第一个execute执行完就提交了事务根本不管它底下兄弟的死活。所以我们要关闭自动提交事务,等最后他们都执行完了,在进行事务的提交。
改动代码如下:

try
//基础代码省略
conn = DriverManager.getConnection(url, dbName, dbPass);
statement = conn.createStatement();
conn.setAutoCommit(false);  //关闭自动提交事务
//要执行的sql语句
String sqlUpdate = "update account set money=0 where name='张三'";
String sqlInsert = "insert into account(name, money) values('赵六', 1000)";
statement.execute(sqlUpdate);
int i=1/0;
statement.execute(sqlInsert);
conn.commit();
//后面还有rollback(),就不写了
事务控制一定是在一个connection中完成的

通过上面的实验我们要明白一个道理,要想实现事务控制就必须在一个connection中进行增删改查(我就是一开始一直不明白这个道理),你想把,如果都不在一个connection中了,两个connection之间怎么协调完成事务控制呢。(当然,分布式事务控制除外

参考资料

https://docstore.mik.ua/orelly/weblinux2/mysql/ch08_02.htm

这个里边有一句话,对我影响特比大:

A database transaction is one or more database statements that must be executed together, or not at all.

你仔细看他的措辞,你发现了什么关键信息了吗?
他说的是一个或者多个statement必须一起执行,你是不是似乎明白了什么。


小结

上面的代码就完成了事务控制。很简单,但是有几个道理藏在里面,下面再重申一下:

  1. 一个execute就会执行一个事务
  2. 由1推导出一个connection可以执行多个事务
  3. 那么事务控制就是将多个execute放到一个connection中进行控制
  4. 控制的方式就是,关闭jdbc的自动提交(不在让他们各自自动进行提交),等所有事务全部执行成功再一起提交。