MySql事务

Posted 晓锋残月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySql事务相关的知识,希望对你有一定的参考价值。

一、为什么会引入事务概念

在银行转账系统中进场会遇见一个现象,那便是如果A给B转账,但是转账的中间过程出了问题,导致A转账失败,但是B却得到了钱,因而出现了错误。下面使用简单的例子证明。

假设某数据库有数据如下:


新建一个Java项目,在里面写入下面代码:



得到的结果为:



上面的问题是:张三给李四转账了,但是由于中间过程出错,导致转账失败,导致李四没收到钱。


二、事务的应用

1、事务的概念

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。

2、mysql事务

a、mysql引擎是支持事务的
b、mysql默认自动提交事务。每条语句都处在单独的事务中。
c、手动控制事务
开启事务:start transaction | begin
提交事务:commit
回滚事务:rollback

下面以简单的例子来手动控制事务

(1)begin--commit,事务开启提交


查看数据库得到结果为:



(2)begin--rollback 进行事务回滚


得到的结果为:



3.JDBC中应用事务

在上面是在客户端进行事务处理,下面介绍的将是事务在jdbc中的应用

将上面的第一个代码修改为如下所示

package com.xfcy.test;

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

import org.junit.Test;

import com.xfcy.utils.DBUtils;

public class TestDemo01 

	@Test
	public void test1()
		Connection conn=null;
		PreparedStatement ps=null;
		
		
			try 
				conn=DBUtils.getConnection();
				conn.setAutoCommit(false);//其作用相当于begin
				ps=conn.prepareStatement("update testone set money=money-100 where name='张三'");
				ps.executeUpdate();
				ps=conn.prepareStatement("update testone set money=money+100 where name='李四'");
				ps.executeUpdate();
				
				conn.commit();//提交事务commit
			 catch (Exception e) 
				if(conn!=null)
					try 
						conn.rollback();//进行事务回滚
					 catch (SQLException e1) 
						e1.printStackTrace();
					
				
				e.printStackTrace();
			finally
				DBUtils.closeAll(null, ps, conn);
			
			
		
	


查看数据库结果为:



三、事务的基本性质

原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 

一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。转账前和转账后的总金额不变。

隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

持久性:指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

四、事务的隔离级别

如果多个进程并发,则会导致下面的问题。
1、赃读:指一个事务读取了另一个事务未提交的数据




2、不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同。一个事务读取到了另一个事务提交后的数据。

3、 虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。            (insert)


为了解决上面的问题发生,可以通过设置事务隔离级别完成。 * 1、READ UNCOMMITTED: 赃读、不可重复读、虚读都有可能发生。
* 2、READ COMMITTED: 避免赃读。不可重复读、虚读都有可能发生。(oracle默认的)
* 4、REPEATABLE READ:避免赃读、不可重复读。虚读有可能发生。(mysql默认)
* 8、SERIALIZABLE: 避免赃读、不可重复读、虚读。
级别越高,性能越低,数据越安全



查看当前事务隔离级别: SELECT @@TX_ISOLATION;
查看当前数据库隔离级别

通过查询可以知道当前MySQL级别为:REPEATABLE READ

更改当前事务隔离界别: SET TRANSACTION ISOLATION LEVEL+(read uncommitted等),注意;设置隔离级别必须在事务前。





在jdbc中设置隔离级别
设置隔离级别必须在开启事务之前进行。
Connection.setTransactionIsolation(int level);
 而leve的值为:

①TRANSACTION_READ_COMMITTED:指示不可以发生脏读的常量;不可重复读和虚读可以发生。

②TRANSACTION_READ_UNCOMMITTED:指示可以发生脏读 (dirty read)、不可重复读和虚读 (phantom read) 的常量

③TRANSACTION_REPEATABLE_READ:指示不可以发生脏读和不可重复读的常量;虚读可以发生。

④TRANSACTION_SERIALIZABLE:指示不可以发生脏读、不可重复读和虚读的常量。



总结

通常情况下,对于数据库的隔离级别不需要更改,对于这些知识更更多的是需要理解。上面便是个人对数据库事务的学习,如果有任何错误,希望提出,谢谢!






以上是关于MySql事务的主要内容,如果未能解决你的问题,请参考以下文章

MySQL事务

在 haproxy 中的写入故障转移期间,正在进行的 mysql 事务会发生啥?

减少InnoDB死锁发生的方法有什么?MySQL学习

MySQL之事务

MySQL事务处理实现方法步骤

MySQL事务处理实现方法步骤