关于mysql事务提交

package com.itheima.trans;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.itheima.util.DBUtil;

public class TransDemo {

	/*
	 	创建mysql数据库相关sql语句:
	 	create database day11;
	 	use day11;
	 	create table account(
	 		id int primary key auto_increment,
	 		name varchar(20),
	 		salary double
	 	);
	 	insert into account values(null, 'a', 1000);
	 	insert into account values(null, 'b', 1000);
	 */
	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = DBUtil.getConn();
			conn.setAutoCommit(false);//设置自动事务提交为false
			//a给b转账-----a账户减去100块钱;b账户增加100块钱
			ps = conn.prepareStatement("update account set salary=salary-100 where name=?");
			ps.setString(1, "a");
			ps.executeUpdate();

			int i = 1 / 0;	//设置异常

			ps = conn.prepareStatement("update account set salary=salary+100 where name=?");
			ps.setString(1, "b");
			ps.executeUpdate();

			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			DBUtil.close(conn, ps, rs);
		}
	}
}

代码解析:

默认情况下每执行一条sql语句,就是执行一次事务,也就是每一条sql语句的执行都会是一次事务的提交。

在这个例子中如果a给b转账,a账户减去100的sql语句执行成功,这时伴随着一次的事务提交,数据库中的a账户金额减去100;而再执行b的账务增加100sql语句之前,出现了异常,这里我设了一个除以零异常,此时程序终止,bsql语句不再执行。a账户扣了100,而b账户则金额不变。这时数据出错。

解决方法是:通过conn.setAutoCommit(false);方法设置事务自动提交为false。这时每一次的sql语句执行完成后就不会提交事务,数据库中的数据并不会发生改变,当俩个sql都执行完成,然后调用coon.commit();方法提交事务,此时数据库中的数据才会真正的改变。如果中途发生异常,通过conn.rollback();方法回滚,此时之前执行的sql语句的结果并不会提交。这样数据就不会出错了。

设置Savepoint:

package com.itheima.trans;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;

import com.itheima.util.DBUtil;

public class TransDemo {

	/*
	 	创建mysql数据库相关sql语句:
	 	create database day11;
	 	use day11;
	 	create table account(
	 		id int primary key auto_increment,
	 		name varchar(20),
	 		salary double
	 	);
	 	insert into account values(null, 'a', 1000);
	 	insert into account values(null, 'b', 1000);
	 */
	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		Savepoint point = null;
		try {
			conn = DBUtil.getConn();
			conn.setAutoCommit(false);//设置自动事务提交为false

			//a给b转账-----a账户减去100块钱;b账户增加100块钱
			ps = conn.prepareStatement("update account set salary=salary-100 where name=?");
			ps.setString(1, "a");
			ps.executeUpdate();

			ps = conn.prepareStatement("update account set salary=salary+100 where name=?");
			ps.setString(1, "b");
			ps.executeUpdate();

			point = conn.setSavepoint();
			int i = 1 / 0;

			//a给b转账-----a账户减去100块钱;b账户增加100块钱
			ps = conn.prepareStatement("update account set salary=salary-100 where name=?");
			ps.setString(1, "a");
			ps.executeUpdate();

			ps = conn.prepareStatement("update account set salary=salary+100 where name=?");
			ps.setString(1, "b");
			ps.executeUpdate();

			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
			try {
				if(point == null) {
					conn.rollback();
				} else {
					conn.rollback(point);
					conn.commit();
				}
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			DBUtil.close(conn, ps, rs);
		}
	}
}
时间: 2024-08-07 16:44:05

关于mysql事务提交的相关文章

MySQL事务提交过程(二)

上一篇文章我们介绍了在关闭binlog的情况下,事务提交的大概流程.之所以关闭binlog,是因为开启binlog后事务提交流程会变成两阶段提交,这里的两阶段提交并不涉及分布式事务,当然mysql把它称之为内部xa事务(Distributed Transactions),与之对应的还有一个外部xa事务. 这里所谓的两阶段提交分别是prepare阶段和commit阶段. 内部xa事务主要是mysql内部为了保证binlog与redo log之间数据的一致性而存在的,这也是由其架构决定的(binlo

mysql 事务提交过程

打开binlog选项后,执行事务提交命令时,就会进入两阶段提交模式.两阶段提交分为prepare阶段和commit两个阶段.流程如下 :这里面涉及到两个重要的参数:innodb_flush_log_at_trx_commit和sync_binlog,参数可以设置不同的值,具体可以查看mysql的帮助手册.我这里设置的是双一模式(innodb_flush_log_at_trx_commit=1,sync_binlog=1),不同的模式区别在于,写文件调用write和落盘fsync调用的频率不同,所

MySQL事务提交过程(一)

MySQL作为一种关系型数据库,已被广泛应用到互联网中的诸多项目中.今天我们来讨论下事务的提交过程. MySQL体系结构 由于mysql插件式存储架构,导致开启binlog后,事务提交实质是二阶段提交,通过两阶段提交,来保证存储引擎和二进制日志的一致. 本文仅讨论binlog未打卡状态下的提交流程,后续会讨论打开binlog选项后的提交逻辑. 测试环境 OS:WIN7 ENGINE: bin-log:off DB: 测试条件 set autocommit=0; -- --------------

对mysql事务提交、回滚的错误理解

一.起因 begin或者START TRANSACTION开始一个事务 rollback事务回滚 commit 事务确认 人们对事务的解释如下:事务由作为一个单独单元的一个或多个SQL语句组成,如果其中一个语句不能完成,整个单元就会回滚(撤销),所有影响到的数据将返回到事务开始以前的状态.因而,只有事务中的所有语句都成功地执行才能说这个事务被成功地执行.  这句话本身没有什么问题,问题是我给理解错了,我测试中问题描述为如下: mysql事务中有两条insert语句,其中第二条语句是错误的,在运行

c++ mysql事务提交及回滚

之前在做有关数据库的操作时发现,有些内容应该作为一个事务一起提交,而不是每个都单独提交,这就需要把这些操作当做一个事务来处理.而我之前写过简单的数据库的操作,因为mysql默认的是自动提交,我们就需要用到api--mysql_commit(). mysql_commit(MYSQL* mysql, my_bool mode); mode为1时表示ON,mode为0时表示OFF. 在关掉自动提交后,以后我们的操作就需要自己手动提交了,而这就是我们所需要的了,对于一系列的操作,如果都成功了,那我们就

mysql自动提交

MySQL的autocommit(自动提交)默认是开启,其对mysql的性能有一定影响,举个例子来说,如果你插入了1000条数据,mysql会commit1000次的,如果我们把autocommit关闭掉,通过程序来控制,只要一次commit就可以了. 1,我们可以通过set来设置autocommit 2,我们可以修改mysql的配置文件my.cnf来关闭autocommit init_connect='SET autocommit=0'  #在mysqld里面加上这些内容 其他关于mysql事

nodejs mysql 事务封装

mysql.js const mysql = require("mysql2"); class MysqlModel { constructor() { this.mysqlConfig = config.mysql; } /** * 实例化mysql */ mysqlInstance() { const poolCluster = mysql.createPoolCluster({ removeNodeErrorCount: 1, // Remove the node immedia

mysql -- 事务隔离级别以及java中事务提交的步骤

SQL标准定义了四种隔离级别,不同隔离的级别使用不当会出现脏读.不可重复读和幻读的问题,隔离级别的出现是事务处理效率与安全的一种平衡. 隔离级别不同会出现的问题 脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的. 不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据. 幻读(Phant

PHP 中mysql如何实现事务提交?

事务就是指对数据库的多次修改,要么全部成功,要么全部失败,不能出现部分修改成功,部分修改失败的情况. PHP下操作mysql数据库要实现事务提交,需注意以下方面: 1, 数据库表存储引擎类型设置为innoDB.默认的mysql表采用MYISAM引擎,是不支持事务的,因此要采用以下语句变更: mysql> alter table ‘table_name’ engine=innodb; 2,PDO对象设置要设置errmode为Exception,否则第16行SQL执行出错,语句也不会跳到catch段