最近在研究mysql的事务,参考了网上的一些例子写了一些,但是感觉有一点疑问,google后发现还是没找到答案,翻了下源码,还没找到核心关键点,想请大神们,帮忙指个路
1.如果在commit之前发生异常,进入catch里显式rollback,会造成什么隐形后果,如果在catch里去掉rollback,因为也没有commit所以数据还是不会提交,什么情况下会rollback才会真正发挥作用,并且这个作用如何和innodb挂钩的,看了下ConnectionImpl里的rollback源码,还没找到核心重点部分。
2.我写的这段简单的jdbc事务,有没有问题,我也是按照网上的模仿了下,如果有问题,一般的写法是怎么样的
3.commit和rollback实际的作用,原理是什么让事务提交和回滚,我所知道的spring-mybatis是用的aop,但是jdbc都是依赖的数据库的手动提交方式,那回滚呢?
4.Spring里所谓的小事务控制是什么样的,Manager层
5.insertTest1方法是自己try catch 还是抛出去 让外层得到异常 然后rollback
6.感觉insertTest1(con);insertTest2(con);这里有问题,如果insertTest1有异常 直接insertTest2不会执行,也就相当于事务的感觉(要么同时执行,要么都不执行)但是这里是通过异常造成的流程控制,不是真正的事务控制。
7.执行下面代码 insertTest1(),insertTest2()都正常执行(插入符合规范的值,不抛异常),finally里的rollback不起作用,test1,test2里还是有数据,怎么样去最终为什么没起作用,查看了数据库是innodb的
public static void main(String[] args) {
Connection con = null;
try {
con = getConnection();
con.setAutoCommit(false);
insertTest1(con);
insertTest2(con);
con.commit();
System.out.println("=======JDBC Transaction commit===========");
} catch (SQLException e) {
try {
con.rollback();
System.out.println("=======JDBC Transaction rolled back successfully=======");
} catch (SQLException e1) {
System.out.println("=======SQL Exception in rollback" + e1.getMessage()); //回滚必要条件:1.同一个transaction 2.connection未关,所以这里要加异常处理
}
e.printStackTrace();
}finally{
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Sql:
javaCode:
public class JdbcTransaction {
public final static String DB_DRIVER_CLASS = "com.mysql.jdbc.Driver";
public final static String DB_URL = "jdbc:mysql://xxx.mysql.rds.aliyuncs.com/weitoo";
public final static String DB_USERNAME = "xxx";
public final static String DB_PASSWORD = "xxx";
public static final String INSERT_TEST1 = "INSERT INTO test1(id,name) VALUES(?,?)";
public static final String INSERT_TEST2 = "INSERT INTO test2(id,name) VALUES(?,?)";
public static void main(String[] args) {
Connection con = null;
try {
con = getConnection();
con.setAutoCommit(false);
insertTest1(con);
insertTest2(con);
con.commit();
System.out.println("=======JDBC Transaction commit===========");
} catch (SQLException e) {
try {
con.rollback();
System.out.println("=======JDBC Transaction rolled back successfully=======");
} catch (SQLException e1) {
System.out.println("=======SQL Exception in rollback" + e1.getMessage()); //回滚必要条件:1.同一个transaction 2.connection未关,所以这里要加异常处理
}
e.printStackTrace();
}finally{
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName(DB_DRIVER_CLASS);
conn = DriverManager.getConnection(
DB_URL,
DB_USERNAME, DB_PASSWORD);
System.out.println("======DB connection successfully========");
} catch (ClassNotFoundException | SQLException e) {
System.out.println("======DB connection failed=========");
e.printStackTrace();
}
return conn;
}
public static void insertTest1(Connection conn) throws SQLException {
PreparedStatement stmt;
stmt = conn.prepareStatement("INSERT INTO test1(id,name) VALUES(?,?)");
stmt.setInt(1, 1);
stmt.setString(2, "1");
stmt.executeUpdate();
System.out.println("======insert into test1 successfully======");
stmt.close();
}
public static void insertTest2(Connection conn) throws SQLException {
PreparedStatement stmt;
stmt = conn.prepareStatement("INSERT INTO test2(id,name) VALUES(?,?)");
stmt.setInt(1, 1);
stmt.setString(2, "11"); //故意长度超出
stmt.executeUpdate();
System.out.println("======insert into test2 successfully========");
stmt.close();
}
}
没get到问题点, 你问的是客户端如何发起回滚么 ??
进行事务处理的时候,MySQL 在开始事务时会切换到一个延缓操作的状态,这个状态下操作并不都是立即执行的(通常情况下语句是立即执行的)。而在 commit 时,会将延缓执行的操作都执行进去,并将状态回归到及时写入状态。同样的, rollback 时会把延缓写入的操作抛弃掉,此间申请的锁释放掉,并将状态回归到及时写入状态。
执行 rollback 的关键在于释放 申请的锁 和 回归及时写入状态,而并不是放弃未写入的操作(你关心的点在未写入的操作,然而执行与不执行 rollback 都没有操作写进去,所有你感觉执行或不执行都没什么区别)。
有时候你不执行 rollback ,影响并不会马上提现,毕竟你下一次调用 startTransaction 的时候还是会重置一下状态。但是如果你在事务之中申请了锁,或者是其他一些关联操作,那就会响应你其他与之关联操作的执行。这就好比是关闭程序,rollback 是正常的关闭流程,你不执行 rollback 就好像是强行关闭程序,难免发生奇怪的问题。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。