MYSQL事务超全知识总结#yyds干货盘点#

Posted toplabs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MYSQL事务超全知识总结#yyds干货盘点#相关的知识,希望对你有一定的参考价值。

@toc

  • 为什么要有事务?

1.1 命令行演示

  1. 开启事务
    start transaction;
  2. 提交或者回滚事务
    commit; -- 提交事务,数据将会写到磁盘上的数据库
    rollback; -- 数据回滚,回到最初的状态。
  3. 关闭自动提交功能
  4. 演示事务

    1.2 代码演示

  5. 通过conn.setAutoCommit(false);来关闭自动提交的设置。
  6. 提交事务conn.commit();
  7. 回滚事务conn.rollback();

    @Test
    public void testTransaction()
    
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try 
            conn = JDBCUtil.getConn();
            // 连接,事务默认就是自动提交的。关闭自动提交。
            conn.setAutoCommit(false);
            String sql = "update account set money = money - ? where id = ?";
            ps = conn.prepareStatement(sql);
            // 扣钱,扣ID为1的100块钱
            ps.setInt(1, 100);
            ps.setInt(2, 1);
            ps.executeUpdate();
            int a = 10 / 0 ;
    
            //加钱,给ID为2 加100块钱
            ps.setInt(1, -100);
            ps.setInt(2, 2);
            ps.executeUpdate();
            //成功: 提交事务。
            conn.commit();
    
         catch (SQLException e) 
            try 
                //事变:回滚事务
                conn.rollback();
             catch(SQLException e1) 
                e1.printStackTrace();
            
            e.printStackTrace();
         finally 
            JDBCUtil.release(conn, ps, rs);
        
    

    1.3 事务的特性

  • 原子性: 事务中包含的逻辑,不可分割。

  • 一致性: 事务执行前后。数据完整性

  • 隔离性: 事务在执行期间不应该受到其他事务的影响

  • 持久性: 事务执行成功,那么数据应该持久保存到磁盘上

1.4 事务的安全隐患

1.4.1 读

  1. 丢失更新: 如果多个线程操作,基于同一个查询结构对表中的记录进行修改,那么后修改的记录将会覆盖前面修改的记录,前面的修改就丢失掉了。

1.5 隔离级别

  1. 读未提交(Read uncommitted)

  2. 读已提交(Read committed)

  3. 可重复读(Repeatable read)

  4. 可串行化(Serializable)
  • 按效率划分,从高到低

  • 按拦截程度 ,从高到底

  • mysql 默认的隔离级别是: 可重复读

  • Oracle 默认的隔离级别是: 读已提交
√:可能出现  ×:不会出现 脏读 不可重复读 幻读
Read uncommitted
Read committed ×
Repeatable read × ×
Serializable × × ×

1.5.1 读未提交

  1. 查看事务的隔离级别
    -- 我安装的是MySQL8,原先的select @@tx_isolation;不能用了
    select @@transaction_isolation;
  2. 设置隔离级别为读未提交
    -- read uncommitted 读未提交
    set session transaction isolation level read uncommitted;
  3. 引发的问题:两个并发的事务,"事务A:更新"、"事务B:查询",事务B读取了事务A尚未提交的数据,即我们所说的脏读。

1.5.2 读已提交

  1. 设置隔离级别为读已提交,可解决脏读。
    -- read committed 读已提交
    set session transaction isolation level read committed;
  2. 引发的问题:两个并发的事务,"事务A:查询"、"事务B:更新",事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变,即我们所说的不可重复读。

1.5.3 不可重复读

  1. 设置隔离级别为不可重复读,可解决不可重复读。
    -- repeatable read 不可重复读
    set session transaction isolation level repeatable read;
  2. 引发的问题:两个并发的事务,"事务A:更新"、"事务B:更新",事务A事先更新了数据,事务B紧接着又把更新了回来,并提交了事务,而事务A再次读取该数据时,发现数据没有发生改变,即我们所说的幻读。

1.5.4 可串行化

  1. 设置隔离级别为可串行化,可解决一切问题。
    -- serializable 可串行化
    set session transaction isolation level serializable;
  2. 如果有一个连接的隔离级别设置为了串行化,那么谁先打开了事务,谁就有了先执行的权利,谁后打开事务,谁就只能等着,等前面的那个事务,提交或者回滚后,才能执行。这种隔离级别一般比较少用,容易造成性能上的问题,效率比较低。

1.6 锁机制

  1. 解决丢失更新问题
    • 悲观锁(Pessimistic Locking)
    • 乐观锁(Optimistic Locking)

1.6.1 悲观锁

  1. 悲观锁原理:使用数据库内部锁机制,进行数据库表的锁定。就是在A管理员修改数据时,A管理员就将数据锁定,此时B管理员无法进行修改、查询。避免两个事务同时修改,也就解决了丢失更新问题。
  2. 在查询的时候,加入for update

    1.6.2 乐观锁

  3. 乐观锁原理:使用的不是数据库的锁机制,而是一个特殊标记字段,通过控制字段状态和内容得知数据是否发生了并发访问。进行数据修改时,数据库会检测version字段或者时间戳是否与原来的一致。若不一致,抛出异常,提醒更新。
  4. 要求程序员自己控制。可以通过给数据表添加自增的version字段或时间戳timestamp

END

感谢看到这里的各位读者朋友们,如果你感到本文写的不错,就顺手点个赞

以上是关于MYSQL事务超全知识总结#yyds干货盘点#的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点# 超全面Git知识总结!

#yyds干货盘点# MySQL RC事务隔离级别的实现

#yyds干货盘点#MySQL学习-为啥有时候事务的隔离没有生效

微服务架构 | 11. 分布式事务 #yyds干货盘点#

#yyds干货盘点#愚公系列2023年02月 .NET/C#知识点-程序运行计时的总结

#yyds干货盘点#盘点MySQL中的那些日志文件