mysql 事务管理

什么是事务

简单的来说,事务是一组业务操作,这些业务操作要么全部执行成功,要么全部执行不成功。

事务的特性

事务具有四个特性

  • 原子性:事务是一个不可分割的基本单位,事务的业务操作要么全部成功,要么全部不成功
  • 一致性:事务执行前后数据的完整性必须一致
  • 隔离性:多个事务,事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
  • 持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是 永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
    参考链接:https://blog.csdn.net/qq_20042935/article/details/88944340

mysql 中常见事务操作

开启事务

start TRANSACTION;
# or
BEGIN;

提交事务

commit

回滚

rollback

关闭自动提交事务

SET autocommit = 0;

提交事务演示事例

现有一个数据库表,其中的数据如下:
在这里插入图片描述
为了更好的呈现出实验效果,我又在终端连接到了mysql数据库
所以说现在一共有两个连接,一个是mysqlworkbench,一个是终端。
我在终端开启事务并向表中插入一条语句,然后在终端查看表中的数据
注意:我没有提交事务
在这里插入图片描述
可以看到,在终端中显示插入数据成功。
下面我们看一下mysqlworkbench中的表情况:
在这里插入图片描述
可以看到,workbench中并没有新插入的行,这是由于没有提交事务造成的。
我们再在终端提交事务,然后再次查看workbench中的数据。
在这里插入图片描述
发现插入成功,这说明一旦开启事务,需要手动commit,不然sql语句是不会生效的。
我们也可以设置关闭自动提交事务来避免每次都要手动开启事务,这样我们每次写完sql语句都需要手动commit才能使sql语句生效。
在这里插入图片描述
这里我设置关闭自动提交事务,然后执行一条更新语句,之后查询数据发现更新成功。
下面我们看下workbench中的情况。

在这里插入图片描述
发现并没有更新成功,之后我们commit。
在这里插入图片描述
发现更新成功。所以说我们需要手动提交才能生效。

事务隔离问题

脏读: 一个事务读到另一个事务未提交的数据

不可重复读: 一个事务读到另一个事务已提交的数据(update)

虚读(幻读): 一个事务读到另一个事务已提交的数据(insert)

mysql 事务隔离级别

read uncommitted(读未提交): 3个问题都没解决

read committed(读已提交):解决脏读

repeatable read(可重复读):解决脏读,不可重复读

serializable(串行化):都解决,单事务处理模式
注意:隔离级别越高,则性能越差

解决脏读

在这里说一下查看数据库的隔离级别:

select @@transaction_isolation

设置数据库的隔离级别:

set session transaction isolation level XXX;

首先我们先把两个数据库会话的隔离级别调成read uncommited;
之后我们在终端插入一条数据,然后查询数据,终端插入成功(并未进行commit)
在这里插入图片描述
然后我们查看workbench中的数据
在这里插入图片描述
发现也能显示插入的数据,然而终端并没有执行commit操作,我们将这种情况称为脏读。
接下来我在终端运行rollback操作。
在这里插入图片描述
发现,workbench也发生了变化。
我们将workbench 中的隔离级别改成read commited。
然后重复上面操作。
在这里插入图片描述
在这里插入图片描述
发现没有出现脏读的情况,说明read commited确实解决了脏读问题。

解决不可重复读

在workbech中隔离级别为 read committed 下,我们做如下实验:
在终端中更新一条数据,然后提交。
在这里插入图片描述
然后在workbench中开启事务,查询数据:
在这里插入图片描述
没有发现问题。
然后再在终端中重复上述步骤。
在这里插入图片描述
然后再次在workbench查询数据
在这里插入图片描述
发现workbech中的数据也发生了更新。在一个事务中重复读数据发现出现了不同的结果,说明还是受到了其他事务的影响,这违背了事务的隔离性,我们称这个问题为不可重复读。
解决这个问题我们可以设置workbench中的隔离级别为repeatable read。
设置workbench中的隔离级别为repeatable read之后,我们再次重复上面的实验。
第一次更新
在这里插入图片描述
查看workbech数据中的情况
在这里插入图片描述
第二次更新
在这里插入图片描述
workbench中的情况
在这里插入图片描述
我们发现没有发生变化,repeatable read 解决了不可重复读问题。

解决幻读

现在workbench中隔离级别为 repeatable read。
我们先在workbench中开启事务查看数据
在这里插入图片描述
一共10条数据
然后我们再在终端开启事务,向数据表中添加一条记录并提交。
在这里插入图片描述
此时,查看workbench中的数据
在这里插入图片描述
还是原来的10条数据
但是我们再workbench中执行更新操作,却发现影响了11条数据。
在这里插入图片描述
我们再将workbench中的事务提交,然后再查看数据
在这里插入图片描述
发现新插入的最后一条数据的sage也发生了更改,这就是幻读。
我们将workbench和终端中的隔离级别设为serializable
我们将最新一条的数据删掉,这样原表中还是10条数据。
然后重复上面的步骤
我们先在workbench中开启事务,查询数据,然后在终端插入一条数据。
在这里插入图片描述
终端在执行insert当中卡住了,之后又报错了。
原来serializable在同一时间仅允许一个事务执行,别的事务会被锁住,当此事务提交之后别的事务才会被执行。
一般在工作中,会将隔离级别设为repeatable read,因为serializable效率低下。

java 执行mysql事务操作的基本格式

ABCD 一个事务

Connection conn = null

try

{
    // 1. 获得连接
    conn = ...;
    // 2.开启事务
    conn.setAutoCommit(false);
    A
    B
    C
    D
    //3.提交事务
    conn.commit();

}catch(){
    //4.回滚事务
    conn.rollback();
}

java 执行mysql事务操作的基本格式----savepoint

AB(必须)CD(可选)
Connection conn = null;
//保存点,记录当前操作位置,之后可以回滚到指定位置(可以回滚一部分)
Savepoint savepoint = null;
try
{
   	// 1. 获得连接
    conn = ...;
    // 2.开启事务
    conn.setAutoCommit(false);
    A
    B
    savepoint = conn.setSavepoint();
    C
    D
    //3.提交事务
    conn.commit();  
}catch()
{
    if(savepoint!=null) //CD异常
    {
        conn.rollback(savepoint); // 回滚到CD之前
        conn.commit();  // 提交AB
    }
    else
    {
        conn.rollback(); // 回滚AB
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值