Java基础28--mysql-事物的概述与事务的开启、提交、回滚

Java基础28–mysql-事物的概述与事务的开启、提交、回滚

package com.atguigu.thread;

public class TestThread {
	public static void main(String[] args) {
		Ticket t1 = new Ticket("窗口一");
		Ticket t2 = new Ticket("窗口二");
		
		t1.start();
		t2.start();
	}
}
class Ticket extends Thread{
	private static int count = 10;//共享数据
	
	public Ticket() {
		super();
	}

	public Ticket(String name) {
		super(name);
	}

	public void run(){
		while(count>0){
			synchronized (Ticket.class) {
				if(count>0){
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					count--;
					System.out.println(getName() + "卖出一张票,剩余:" + count);
				}
			}
			
		}
	}
}

在这里插入图片描述
同步了代码块

数据库中的表格可能同时多个线程访问,就有线程安全问题,mysql还有一个需求,就是中间出现问题,能还原到原来的状态

1、事务:概念

事务是表示一组操作要么同时成功,要么同时失败,而且事务与事务之间是独立。
事务有ACID的特性。
(1)原子性(2)一致性(3)隔离性(4)持久性

事务处理**(事务操作):**保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态。**

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

一致性(Consistency)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。

隔离性(Isolation)
事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的, 并发执行的各个事务之间不能互相干扰。

持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响

银行转账

张三-》李四转账500元
张三原来的余额是1000元,
李四原来的余额是0元。

(1)张三账户-500
(2)李四账户+500

一致性:要么张三还是1000,李四是0
	    要么张三现在是500,李四是500
		
张三-500成功了,要给李四+500时,发现李四的账号异常,那么要回滚,还原刚刚张三-500的操作。
如果都成功了,就提交。

事务:
网购,下订单

(1)创建订单--》订单表中要添加记录
(2)记录订单明细--》订单明细表中要添加订单都买了什么
(3)商品表修改-->库存量修改,销量增量	

2、
mysql默认是自动提交事务,一句SQL是一个事务,执行成功一句就提交一句。

手动开始事务,取消自动提交。
方式一:
set autocommit = false;
这次客户端连接,在你恢复自动提交之前,接下来所有的SQL执行都必须手动提交了,否则就不生效。

这个设置只管一个连接,和其他的连接(登录)无关。(若是未提交重新登录会发现事务没提交)

set autocommit = false;
....   都是需要手动提交的。
set autocommit = true;	

举例:
先登录数据库
在这里插入图片描述
设置为手动提交
在这里插入图片描述
在这里插入图片描述
上是sid,不是id
这时没写提交语句
再登录数据库查看所有数据会发现删除的数据还在,没提交就没生效

当只是部分的SQL需要构成事务,手动提交,而其他SQL还是想要自动提交的。
那么我们选择方式二。

方式二::更灵活

start transaction;//开始事务
....   一个事务
commit;rollback;//结束标志

start transaction;
… 另一个事务
commit;或rollback;

… 自动提交

举例:
在这里插入图片描述
第一个事务写commit了,后面一个事务没有写commit
再重新登录
在这里插入图片描述
会发现两个都执行了,说明第二个事务自动提交了

注意:javaJBDC中支持的是第一种,命令行都行,建议第二种

回滚演示:
在这里插入图片描述
在事务结束之前可以回滚撤回操作。
在这里插入图片描述
再查询没被删除

事务的隔离级别

同一个库的同一个表同一个记录,对于多个事务来说,就是共享数据。
多个事务被多个线程同时执行时,那么共享数据就会线程安全问题。

针对不同安全级别的要求,设置了不同的隔离级别:(隔离级别就是为了避免出现脏读、不可重复、幻读等现象而设定的)

  • (1)read uncommitted:可以读取未提交的
    事务1,可以读取到事务2已经修改,但是还没正式提交的数据
    会出现脏读、不可重复读、幻读,但快
  • (2)read committed:读取已提交的数据
    事务1,只能读取到事务2已提交的数据
    会出现不可重复读、幻读
  • (3)repeatable READ:可重复读
    原来:会出现幻读
    现在:幻读也可以避免
    行锁
  • (4)Serializable :序列化
    所有问题都可以避免。
    表锁

几种问题:

  • (1)脏读现象
    事务1对某个记录进行修改,还未提交。事务2就看到了。
    那么这个被事务1修改还未提交的数据就是脏数据。
    如何避免脏读,把事务隔离级别设置为(2)(3)(4)都可以避免。

  • (2)不可重复的
    事务1对某个表进行修改,已经提交。(记录数没变化,只是某个值变化了)
    但是事务2,在事务1提交之前,查询了一下这个记录,
    在事务1提交之后,又查询了一下这个记录,
    对于事务2来说,出现了不可重复读的现象。
    在同一个事务中,前后两次对同一个记录的读取发现不一样。
    如果想要避免不可重复读,那么需要设置隔离级别为(3)(4)

  • (3)幻读
    事务1给某个表增加了新的记录,或者删除了某个表的记录。(记录数有变化)
    并且提交了。
    事务2,在事务1提交之前,查询了这个表
    在事务1提交之后,查询了这个表
    对于事务2来说,前后两次的记录数不一样。好比出现幻觉一样。多出或少了记录。

如果想要避免幻读,那么需要设置隔离级别为(4)。

但是mysql在5.0之后,升级了。在隔离级别(3)的时候,就可以避免幻读了。

4、如何查询当前连接是什么隔离级别
在这里插入图片描述

mysql默认的隔离级别是:
±----------------+
| @@tx_isolation |
±----------------+
| REPEATABLE-READ |
±----------------+

用户要查看的话:select @@tx_isolation;

5、如何修改当前连接的隔离级别

set tx_isolation = 'read-uncommitted';
set tx_isolation = 'read-committed';
set tx_isolation = 'REPEATABLE-READ';
set tx_isolation = 'serializable';

举例:
先登录
在这里插入图片描述
在这里插入图片描述
设置
在这里插入图片描述
再开一个命令行客户端,另一个线程,登录
在这里插入图片描述
两边都开启事务
在这里插入图片描述
两边都查询表数据都行,没问题
在这里插入图片描述
一边改完数据还没提交
在这里插入图片描述
另一边能查询到修改但还没提交的数据,因为隔离级别设置为了可以读取到别人未提交的数据的了,脏读现象,因为若是修改数据的线程回滚,另一个线程再去读数据是之前的数据,前后两次查的数据不一样
在这里插入图片描述

若是将隔离等级设置为read-commmited,升一级,会发现一个线程修改数据还没提交时,另一个线程读到的是未修改前的数据,事务提交了,另一个线程再去读改变了,对于同一个事务来说,前后两次读数据不一样,不可重复读,

再开启一个事务
在这里插入图片描述
在这里插入图片描述
添加一组数据成功,但未提交
在这里插入图片描述
在这里插入图片描述
另一个事务查询没有新数据
增加数据事务提交后,另一个事务查询,会查询到新增的数据
在这里插入图片描述
这种现象叫做幻读,记录数有影响
增加数据的线程再删掉三条数据
在这里插入图片描述
在这里插入图片描述
没提交时,另一个线程查询看不出来,提交后,另一个线程再查询才能看出来,幻读现象

再往上提升隔离级别,repeatable-read
在这里插入图片描述
开启两个事务
在这里插入图片描述
一个事务修改数据成功,但没提交,另一个事务查询数据还没修改,若是这时另一个查询数据的事务也修改,并且改的是同一个人的姓名
在这里插入图片描述
查询数据的事务修改数据回车后会发现会卡住,阻塞了,这时之前修改数据的事务提交,提交的一瞬间,查询数据的线程也修改成功(注意,这个事务没提交)

这时两个事务都查询
在这里插入图片描述
会发现两个事务查询的都是各自修改的数据,后修改的线程因为是自己修改,所以查到自己修改的数据,而之前提交修改的事务查到自己修改的数据是因为这个事务默认的隔离级别repeatable-read可以避免没提交的数据

会发现有锁定现象,如果两个线程同时修改某一行记录,会锁定,若是同时操作不同行的记录,不会卡住,没有锁定

再提升隔离等级 Serializable
在这里插入图片描述
开启两个事务,一个线程修改一行数据未提交,另一个事务修改另一行数据会卡住,之前那个数据提交后,后一个修改的事务才能继续,Serializable一个表在操作时(insert、update、dalete等),另一个事务什么都不能做,要等那个正在操作的事务结束后才行,Serializable锁的表,性能很低下

补充:Oracle数据库隔离级别只有两级,不能读未提交的数据
在这里插入图片描述

要知道:四个隔离级别及其区别,避免什么现象
什么是脏读、不可重读、幻读(面试)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值