事务隔离级别—— SERIALIZABLE(序列化)

首先,我们先设置MySQL事务隔离级别为SERIALIZABLE

  1. 在my.ini配置文件最后加上如下配置
#可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE.
[mysqld]
transaction-isolation = SERIALIZABLE
  1. 重启MySQL服务

1、脏读

提出问题
例如: 已知有两个事务A和B, B读取了已经被A更新但还没有被提交的数据,之后,A回滚事务,B读取的数据就是脏数据。
场景:
Tom的账户money=0,公司发工资把5000元打到Tom的账户上,Tom的money=money+5000元,但是该事务并未提交,而Tom正好去查看账户,发现工资已经到账,账户money=5000元,非常高兴,可是不幸的是,公司发现发给Tom的工资金额不对,应该是2000元,于是迅速回滚了事务,修改金额后,将事务提交,Tom再次查看账户时发现账户money=2000元,Tom空欢喜一场,从此郁郁寡欢,走上了不归路……
当我们设置事务隔离级别为SERIALIZABLE(序列化)时事务流程如下:

事务A(代表公司) 事务B(代表Tom)
read(money);
money=money+5000;
write(money)
read(money);(操作未成功!)
rollback;(money=0)
money=money+2000
submit ;
read(money);(操作成功)

分析:上述情况即为脏读,两个并发的事务:“事务A:公司给Tom发工资”、“事务B:Tom查询工资账户”,事务隔离级别为SERIALIZABLE(序列化)时事务B只能在事务A提交后执行。
实验
我们在java代码中观察这种情况:

public class Boss {
   //公司给Tom发工资

	public static void main(String[] args) {
   
		Connection connection = null;
		Statement statement = null;
		try {
   
			Class.forName("com.mysql.jdbc.Driver");
			String url = "jdbc:mysql://127.0.0.1:3306/test";
			connection = DriverManager.getConnection(url, "root", "root");
			connection.setAutoCommit(false);
			statement = connection.createStatement();
			String sql = "update account set money=money+5000 where card_id='6226090219290000'";
			statement.executeUpdate(sql);
			Thread.sleep(10000);//10秒后发现工资发错了
			connection.rollback();
			sql = "update account set money=money+2000 where card_id='6226090219290000'";
			statement.executeUpdate(sql);
			connection.commit();
		} catch (Exception e) {
   
			e.printStackTrace();
		} finally {
   
			//释放资源
		}
	}
}
public class Employee {
   //Tom查询余额

	public static void main(String[] args) {
   
		Connection connection = null;
		Statement statement = null;
		ResultSet resultSet = null;
		try {
   
			Class.forName("com.mysql.jdbc.Driver");
			String url = "jdbc:mysql://127.0.0.1:3306/test";
			connection = DriverManager.getConnection(url, "root", "root");
			statement = connection.createStatement();
			String sql = "select balance from account where card_id='6226090219290000'";
			resultSet = statement.executeQuery(sql);
			if(resultSet.next()) {
   
				System.out.
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值