精华内容
下载资源
问答
  • mysql 事务等待锁超时分析
  • MySql事务

    万次阅读 2018-11-04 23:57:01
    MySql事务  事务是什么  事务的ACID特性  事务的隔离级别  锁机制 1,事务是什么?  事务是一组SQL语句,要么全部执行成功,要么全部执行失败。通常一个事务对应一个完整的业务(例如银行账户转账业务,该...

                                                       MySql事务

    •  事务是什么
    •  事务的ACID特性
    •  事务的隔离级别
    •  锁机制

    1,事务是什么?

          事务是一组SQL语句,要么全部执行成功,要么全部执行失败。通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)

    事务的提交:COMMIT

    事务的回滚:ROLLBACK

    事务的关闭:CLOSE

    默认情况下一个SQL语句为一个事务。

    举例说明:

           

    这是两张表 user和user1

    现在我们需要让丽颖给刘昊然转十块钱。

    public static void main(String[] args) {
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            try {
                Class.forName("com.mysql.jdbc.Driver");
                String url = "jdbc:mysql://localhost:3306/shiwu";
                connection = DriverManager.getConnection(url,"root","132990");
    
    //            // 禁止jdbc自动提交事务
    //            connection.setAutoCommit(false);
    
                preparedStatement = connection.prepareStatement("update user set money = money-? where id= ?");
                preparedStatement.setInt(1,10);
                preparedStatement.setInt(2,1);
                preparedStatement.executeUpdate();
    
    
                String str = null;
                if(str.equals("")){
    
                }
    
                preparedStatement = connection.prepareStatement("update user1 set money = money+? where id = ?");
                preparedStatement.setInt(1,10);
                preparedStatement.setInt(2,1);
                preparedStatement.executeUpdate();
    
    
    //            // 提交事务
    //            connection.commit();
    
            } catch (Exception e) {
                e.printStackTrace();
    //            // 回滚事务
    //            try {
    //                connection.rollback();
    //            } catch (SQLException e1) {
    //                e1.printStackTrace();
    //            }
    
            }finally {
                try {
                    preparedStatement.close();
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    我们可以观察出两个SQL语句中间会报空指针异常,这个时候我们来 看一下运行结果。

    我们可以看到丽颖少了十块钱,但是刘昊然没有多十块钱,这显然是不应该被允许的。这个转账过程是一个事务,这两个SQL语句要么全部执行失败,要不全部成功。

    所以这个时候我们应该禁止jdbc自动提交事务

    connection.setAutoCommit(false);

    然后再两条SQl语句执行完之后提交事务

    connection.commit();

    如果有异常则回滚事务

          catch (Exception e) {
                e.printStackTrace();
                // 回滚事务
                try {
                    connection.rollback();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
    
            }

    2,事务的ACID特性

           事务的原子性

                事务是最小单元,不可再分,要么全部执行成功,要么全部失败回滚。

           事务的一致性

                一致性是指事务必须使数据库从一个一致的状态变到另外一个一致的状态,也就是执行事务之前和之后的状态都必须处于一致          的状态。不一致性包含三点:脏读,不可重复读,幻读

          事务的隔离性

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

         事务的持久性

                DBMS(数据库管理系统)对数据的修改是永久性的。

    3,事务的四个隔离级别

          脏读:一个事务处理过程里读取了另一个未提交的事务中的数据

          可重复读:一个事务在它运行期间,两次查找相同的表,出现了不同的数据

          幻读:在一个事务中读取到了别的事务插入的数据,导致前后不一致

                    A事务读取了B事务已经提交的新增数据。和不可重复读的区别,这里是新增,不可重复读是更改(或删除)。                   这两种情况对策是不一样的,对于不可重复读,只需要采取行级锁防止该记录数据被更改或删除,然而对于幻读必                   须加表级锁,防止在这个表中新增一条数据。

    • 未提交读

           读未提交,即能够读取到没有被提交的数据,所以很明显这个级别的隔离机制无法解决脏读、不可重复读、幻读中的任何一种。

    • 已提交读

           读已提交,即能够读到那些已经提交的数据,自然能够防止脏读,但是无法限制不可重复读和幻读

    • 可重复读

           可重复读,读取了一条数据,这个事务不结束,别的事务就不可以改这条记录,这样就解决了脏读、不可重复读的问题,

    • 串行化

           串行化,多个事务时,只有运行完一个事务之后,才能运行其他事务。

         

    我们来演示一下:
    SELECT @@AUTOCOMMIT;    查看MySQL是否自动提交事务  0表示手动提交事务    1表示自动提交事务
    SET AUTOCOMMIT = 0;    设置事务提交方式  0表示手动提交事务    1表示自动提交事务

    SELECT  @@TX_ISOLATION;查询事务的隔离级别

    未提交读的隔离级别

    默认为可重复读。我们来将它改成未提交读。

       脏读:

              

    我们可以看到左边的事务还未提交,右边查到了左边没有的事务。

    可提交读的隔离级别

    我们可以看到在可提交读隔离级别上解决了脏读

    可重复读

    一个事务在它运行期间,两次查找相同的表,出现了不同的数据


    可重复读隔离级别

    可重复读:

    我么可以看到这个隔离级别解决了可重复读

    幻读:

    我们可以看到这个并没有出现幻读。因为高版本MySQL Server做的一些优化,在高版本的MySQL用户手册里面,说在可重复读这个级别下,也会对幻读进行一定的防止,但是不能保证绝对不出现幻读。因为串行化一般是不会用到的,效率太低,MySQL默认工作在第三级别,可重复读情况下,所以对这个隔离级别做了优化。

    4,锁机制

    MySQL大致可归纳为以下3种锁:

    • 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
    • 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
    • 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

    表锁:对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写请求;

    读读:可以允许

    读写:不允许

    写写:不允许

    InnoDB采用行锁

    InnoDB实现了以下两种类型的行锁。

    • 共享锁(s):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
    • 排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务取得相同的数据集共享读锁和排他写锁。

      InnoDB行锁是通过索引上的索引项来实现的。InnoDB这种行锁实现特点意味者:只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB将使用表锁!

    对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;对于普通SELECT语句,InnoDB不会加任何锁。

    间隙锁(Next-Key锁)

        当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁。

    比如会给between and 中间所有存在或者不存在数据加锁。可以防止幻读。

    MVCC(无锁实现) 多版本并发控制机制 --》给每一个事务维护一个数据最初的快照

    1,未提交读:

          读读/读写:事务不做任何隔离操作

           写写:获取记录的排他锁,不能同时进行,除非一个事务 提交或回滚

    2,已提交读

       (其他事务提交或者回滚,它会立即读到)

         读读:事务读的是事务最初的快照 mvcc机制

         读写:读的是快照数据,写的也是快照数据 mvcc机制

         写写:获取记录的排他锁,不能同时进行,除非一个事务 提交或回滚

    3,可重复读 (jdbc默认隔离级别)

         读读:事务读的是快照数据 mvcc机制

         读写:读的是快照数据,写的也是快照数据(除非当前事务提交或回滚,否则访问的都是快照数据) mvcc机制

         写写:获取记录的排他锁,不能同时进行,除非一个事务 提交或回滚

    4,串行化

                读读 :共享锁多个事务可以同时获取

                读写 : 共享锁和排它锁

                写写 : 排它锁和排它锁

    展开全文
  • Spring事务和MySQL事务详解面试

    万次阅读 多人点赞 2020-09-10 23:56:36
    文章目录数据库事务事务是什么事务的四大特性MySQL事务隔离级别查看MySQL当前事务隔离级别MySQL默认操作模式为自动提交模式JDBC处理事务Spring事务Spring的事务传播PROPAGATION_REQUIREDPROPAGATION_...

    数据库事务

    事务是什么

    是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合。

    事务的四大特性

    1. 原子性
      事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做

    2. 一致性
      事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。

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

    4. 持续性
      也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。

    MySQL事务隔离级别

    隔离级别隔离级别的值导致的问题
    Read-Uncommitted0导致脏读
    Read-Committed1避免脏读,允许不可重复读和幻读
    Repeatable-Read2MySQL默认的隔离级别。避免脏读,不可重复读,允许幻读
    Serializable3串行化读,事务只能一个一个执行,避免了 脏读、不可重复读、幻读。执行效率慢,使用时慎重

    1. 脏读

    一个事务对数据进行了增删改查,但是未提交事务。另一个事物可以读取到未提交的数据,如果第一个事务进行了回滚,那么第二个事务就读到了脏数据。

    例子:

    领导给张三发工资,10000元已打到张三账户,但该事务还未提交,正好这时候张三去查询工资,发现10000元已到账。这时领导发现张三工资算多了5000元,于是回滚了事务,修改了金额后将事务提交。最后张三实际到账的只有5000元。

    2. 不可重复度

    一次事务发生了两次读操作,两个读操作之间发生了另一个事务对数据修改操作,这时候第一次和第二次读到的数据不一致。

    不可重复度关注点在数据更新和删除,通过行级锁可以实现可重复读的隔离级别。

    例子:

    张三需要转正1000元,系统读到卡余额有2000元,此时张三老婆正好需要转正2000元,并且在张三提交事务前把2000元转走了,当张三提交转账是系统提示余额不足。

    3. 幻读

    幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行。

    相对于不可重复读,幻读更关注其它事务的新增数据。通过行级锁可以避免不可重复读,但无法解决幻读的问题,想要解决幻读,只能通过Serializable隔离级别来实现。

    例子:

    张三老婆准备打印张三这个月的信用卡消费记录,经查询发现消费了两次共1000元,而这时张三刚按摩完准备结账,消费了1000元,这时银行记录新增了一条1000元的消费记录。当张三老婆将消费记录打印出来时,发现总额变为了2000元,这让张三老婆很诧异。

    4. 串行化读

    Serializable是最高的隔离级别,性能很低,一般很少用。在这级别下,事务是串行顺序执行的,不仅避免了脏读、不可重复读,还避免了幻读。

    查看MySQL当前事务隔离级别

    MySQL InnoDB默认的事务隔离级别为REPEATABLE-READ

    mysql> select @@tx_isolation;
    +-----------------+
    | @@tx_isolation  |
    +-----------------+
    | REPEATABLE-READ |
    +-----------------+
    

    MySQL默认操作模式为自动提交模式

    除非显示的开启一个事务,否则每个查询都被当成一个单独的事务自动执行。可以通脱设置autocommit的值改变默认的提交模式。

    1. 查看当前提交模式
    mysql> show variables like 'autocommit';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | ON    |
    +---------------+-------+
    
    1. 关闭自动提交。0代表关闭,1代表开启。
    mysql> set autocommit = 0;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> show variables like 'autocommit';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | autocommit    | OFF   |
    +---------------+-------+
    

    JDBC处理事务

    Connection connection = null;
    PreparedStatement pstmt = null;
    ResultSet resultSet = null;
    
    try {
        Class.forName("com.mysql.jdbc.Driver");
        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname?characterEncoding=utf-8","username", "password");
    
        connection.setAutoCommit(false);
        
        // others ......
        
        connection.commit();
    } catch (Exception e) {
        connection.rollback();
    } finally {
        connection.setAutoCommit(true);
        // close connection
    }
    

    Spring事务

    Spring事务本质是对数据库事务的支持,如果数据库不支持事务(例如MySQL的MyISAM引擎不支持事务),则Spring事务也不会生效。

    Spring的事务传播

    事务传播行为是指一个事务方法A被另一个事务方法B调用时,这个事务A应该如何处理。事务A应该在事务B中运行还是另起一个事务,这个有事务A的传播行为决定。

    事务传播属性定义TransactionDefinition

    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
    
    常量名称常量解释
    PROPAGATION_REQUIRED支持当前事务,如果当前没有事务,就新建一个事务。这是Spring 默认的事务的传播。
    PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
    PROPAGATION_MANDATORY支持当前事务,如果当前没有事务,就抛出异常。
    PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后, 不能回滚内层事务执行的结果,内层事务失败抛出异常,外层事务捕获, 也可以不处理回滚操作。 使用JtaTransactionManager作为事务管理器
    PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。使用JtaTransactionManager作为事务管理器
    PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
    PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。

    PROPAGATION_REQUIRED

    如果存在一个事务,则支持当前事务,如果没有事务则开启事务。
    image

    如下例子,单独调用methodB时,当前上下文没有事务,所以会开启一个新的事务。

    调用methodA方法时,因为当前上下文不存在事务,所以会开启一个新的事务。当执行到methodB时,methodB发现当前上下文有事务,因此就加入到当前事务A中来。

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        methodB();
        // do something
    }
     
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        // do something
    }
    

    PROPAGATION_SUPPORTS

    如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行.
    image

    单独的调用methodB时,methodB方法是非事务的执行的。当调用methdA时,methodB则加入了methodA的事务中,事务地执行。

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        methodB();
        // do something
    }
     
    // 事务属性为SUPPORTS
    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodB() {
        // do something
    }
    

    PROPAGATION_MANDATORY

    如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
    image

    当单独调用methodB时,因为当前没有一个活动的事务,则会抛出异常throw new IllegalTransactionStateException(“Transaction propagation ‘mandatory’ but no existing transaction found”)

    当调用methodA时,methodB则加入到methodA的事务中,以事务方式执行。

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        methodB();
        // do something
    }
    
    @Transactional(propagation = Propagation.MANDATORY)
    public void methodB() {
        // do something
    }
    

    PROPAGATION_REQUIRES_NEW

    使用PROPAGATION_REQUIRES_NEW,需要使用 JtaTransactionManager作为事务管理器。
    它会开启一个新的事务。如果一个事务已经存在,则先将这个存在的事务挂起。
    image

    从下面代码可以看出,事务B与事务A是两个独立的事务,互不相干。事务B是否成功并不依赖于 事务A。如果methodA方法在调用methodB方法后的doSomeThingB方法失败了,而methodB方法所做的结果依然被提交。而除了 methodB之外的其它代码导致的结果却被回滚了

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        doSomeThingA();
        methodB();
        doSomeThingB();
        // do something else
    }
     
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB() {
        // do something
    }
    

    当调用methodA(),相当于

    public static void main(){
        TransactionManager tm = null;
        try{
            //获得一个JTA事务管理器
            tm = getTransactionManager();
            tm.begin();//开启一个新的事务
            Transaction ts1 = tm.getTransaction();
            doSomeThing();
            tm.suspend();//挂起当前事务
            try{
                tm.begin();//重新开启第二个事务
                Transaction ts2 = tm.getTransaction();
                methodB();
                ts2.commit();//提交第二个事务
            } Catch(RunTimeException ex) {
                ts2.rollback();//回滚第二个事务
            } finally {
                //释放资源
            }
            //methodB执行完后,恢复第一个事务
            tm.resume(ts1);
            doSomeThingB();
            ts1.commit();//提交第一个事务
        } catch(RunTimeException ex) {
            ts1.rollback();//回滚第一个事务
        } finally {
            //释放资源
        }
    }
    

    PROPAGATION_NOT_SUPPORTED

    总是非事务地执行,并挂起任何存在的事务。

    使用PROPAGATION_NOT_SUPPORTED,也需要使用JtaTransactionManager作为事务管理器。

    image

    PROPAGATION_NEVER

    总是非事务地执行,如果存在一个活动事务,则抛出异常。

    PROPAGATION_NESTED

    如果一个活动的事务存在,则运行在一个嵌套的事务中。

    如果没有活动事务,则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。

    这是一个嵌套事务,使用JDBC3.0驱动时,仅仅支持DataSourceTransactionManager作为事务管理器。 需要JDBC 驱动的java.sql.Savepoint类。使用PROPAGATION_NESTED,还需要把PlatformTransactionManager的nestedTransactionAllowed属性设为true(属性值默认为false)。

    image

    @Transactional(propagation = Propagation.REQUIRED)
    methodA(){
        doSomeThingA();
        methodB();
        doSomeThingB();
    }
     
    @Transactional(propagation = Propagation.NEWSTED)
    methodB(){
        // do something
    }
    

    单独调用methodB方法,则按REQUIRED属性执行。如果调用methodA方法,则相当于:

    main(){
        Connection con = null;
        Savepoint savepoint = null;
        try{
            con = getConnection();
            con.setAutoCommit(false);
            doSomeThingA();
            savepoint = con2.setSavepoint();
            try{
                methodB();
            } catch(RuntimeException ex) {
                con.rollback(savepoint);
            } finally {
                //释放资源
            }
            doSomeThingB();
            con.commit();
        } catch(RuntimeException ex) {
            con.rollback();
        } finally {
            //释放资源
        }
    }
    

    当methodB方法调用之前,调用setSavepoint方法,保存当前的状态到savepoint。如果methodB方法调用失败,则恢复到之前保存的状态。

    需要注意的是,这时的事务并没有进行提交,如果后续的代码(doSomeThingB()方法)调用失败,则回滚包括methodB方法的所有操作。嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。

    Spring事务的隔离级别

    事务隔离级别定义TransactionDefinition

    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    
    隔离级别解释
    ISOLATION_DEFAULT这是个 PlatfromTransactionManager 默认的隔离级别, 使用数据库默认的事务隔离级别。另外四个与 JDBC 的 隔离级别相对应。
    ISOLATION_READ_UNCOMMITTED这是事务最低的隔离级别,它允许另外一个事务可以看 到这个事务未提交的数据。这种隔离级别会产生脏读, 不可重复读和幻像读。
    ISOLATION_READ_COMMITTED保证一个事务修改的数据提交后才能被另外一个事务读 取。另外一个事务不能读取该事务未提交的数据。 ISOLATION_REPEATABLE_READ
    ISOLATION_SERIALIZABLE这是花费最高代价但是最可靠的事务隔离级别。事务被 处理为顺序执行。

    Spring事务基本配置样例

    <aop:aspectj-autoproxy proxy-target-class="true"/>
    	
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource"/>
    </bean>
    
    <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
    	<tx:attributes>
    		<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception,RuntimeException,SQLException"/>
    		<tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception,RuntimeException,SQLException"/>
    		<tx:method name="edit*" propagation="REQUIRED" rollback-for="Exception,RuntimeException,SQLException"/>
    		<tx:method name="login" propagation="NOT_SUPPORTED"/>
    		<tx:method name="query*" read-only="true"/>
    	</tx:attributes>
    </tx:advice>
    
    <aop:config>
    	<aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionPointcut"/>
        <aop:aspect ref="dataSource">
            <aop:pointcut id="transactionPointcut" expression="execution(public * com.gupaoedu..*.service..*Service.*(..))" />
        </aop:aspect>
    </aop:config>
    
    展开全文
  • 面试官:MySQL事务是怎么实现的

    万次阅读 多人点赞 2020-03-10 23:03:17
    用过MySQL的同学都知道,它的InnoDB存储引擎,是通过事务来保证数据的一致性的。 数据库事务通常包含了一个序列的对数据库的读/写操作。包含有以下两个目的: 为数据库操作序列提供了一个从失败中恢复到正常状态的...

    前言

    用过MySQL的同学都知道,它的InnoDB存储引擎,是通过事务来保证数据的一致性的。

    数据库事务通常包含了一个序列的对数据库的读/写操作。包含有以下两个目的:
    为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
    当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

    特性

    说到事务就不得不说它的四个特性:ACID。分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)

    • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
    • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
    • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
    • 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。

    其中一致性不太好理解,一致性是说无论事务提交还是回滚,不会破坏数据的完整性。比如A给B转100元,如果成功了,A的账户必定会扣100元,而B的账户必定会增加100元;如果失败了,A和B的账户余额不会改变。不会存在其他的情况,这样就是符合一致性的。

    事实上,原子性、持久性和隔离性都是为了保证一致性

    原子性

    事务的原子性是指:一个事务中的多个操作都是不可分割的,只能是全部执行成功、或者全部执行失败。
    MySQL事务的原子性是通过undo log来实现的。undo log是InnoDB存储引擎特有的。具体的实现方式是:将所有对数据的修改(增、删、改)都写入日志(undo log)。如果一个事务中的一部分操作已经成功,但另一部分操作,由于断电/系统崩溃/其它的软硬件错误而无法成功执行,则通过回溯日志,将已经执行成功的操作撤销,从而达到全部操作失败的目的。

    undo log逻辑日志,可以理解为:记录和事务操作相反的SQL语句,事务执行insert语句,undo log就记录delete语句。它以追加写的方式记录日志,不会覆盖之前的日志。除此之外undo log还用来实现数据库多版本并发控制(Multiversion Concurrency Control,简称MVCC)

    持久性

    事务的持久性是指:一个事务对数据的所有修改,都会永久的保存在数据库中。
    MySQL事务的持久性是通过redo log来实现的。redo log也是InnoDB存储引擎特有的。具体实现方式是:当发生数据修改(增、删、改)的时候,InnoDB引擎会先将记录写到redo log中,并更新内存,此时更新就算完成了。同时InnoDB引擎会在合适的时机将记录刷到磁盘中。
    redo log物理日志,记录的是在某个数据页做了什么修改,而不是SQL语句的形式。它有固定大小,是循环写的方式记录日志,空间用完后会覆盖之前的日志。

    undo logredo log并不是直接写到磁盘上的,而是先写入log buffer。再等待合适的时机同步到OS buffer,再由操作系统决定何时刷到磁盘,具体过程如下:
    在这里插入图片描述

    既然undo logredo log都是从log bufferOS buffer,再到磁盘。所以中途还是有可能因为断电/硬件故障等原因导致日志丢失。为此MySQL提供了三种持久化方式,之前的博客:MySQL优化:参数 中提到过一个参数innodb_flush_log_at_trx_commit,这个参数主要控制InnoDB将log buffer中的数据写入OS buffer,并刷到磁盘的时间点,取值分别为0,1,2,默认是1。这三个值的意思分别如下
    log file刷盘策略
    首先查看MySQL默认设置的方式1,也就是每次提交后直接写入OS buffer,并且调用系统函数fsync()把日志写到磁盘上。就保证数据一致性的角度来说,这种方式无疑是最安全的。但是我们都知道,安全大多数时候意味着效率偏低。每次提交都直接写入OS buffer并且写到磁盘,无疑会导致单位时间内IO的次数过多而效率低下。除此之外,还有方式0和方式2。基本上都是每秒写入磁盘一次,所以效率都比方式1更高。但是方式0是把数据先写入log buffer再写入OS buffer再写入磁盘,而方式2是直接写入OS buffer,再写入磁盘,少了一次数据拷贝的过程(从log bufferOS buffer),所以方式2比方式0更加高效。

    了解了undo logredo log的作用和实现过程之后,再来看一下这两个日志具体是怎么让数据库从异常的状态恢复到正常状态的。
    数据库系统崩溃后重启,此时数据库处于不一致的状态,必须先执行一个crash recovery的过程:首先读取redo log,把成功提交但是还没来得及写入磁盘的数据重新写入磁盘,保证了持久性。再读取undo log将还没有成功提交的事务进行回滚,保证了原子性。crash recovery结束后,数据库恢复到一致性状态,可以继续被使用。

    隔离性

    数据库事务的隔离性是指:多个事务并发执行时,一个事务的执行不应影响其他事务的执行。正常情况下,肯定是多个事务同时操作同一个数据库,所以事务之间的隔离就显得必不可少。先看一下,如果没有隔离性,会发生哪些问题。

    第一类丢失更新

    第一类丢失更新是指:一个事务在撤销的时候,覆盖了另一个事务已提交的更新数据
    假设事务A和事务B操作同一个账户的金:

    时间事务A事务B
    T1开启事务开启事务
    T2查询账户余额:500元查询账户余额:500元
    T3取走100元,剩余400元取走100元,剩余400元
    T4提交事务,账户余额:400元-
    T5-撤销事务,账户余额:500元

    事务B在撤销事务的时候,覆盖了事务A在T4的时候已经提交的更新数据。A在T3的时候已经取走了100元,此时的余额应该是400元,但是由于事务B开始的时候,余额是500元,所以回滚后,余额也会变成500元。

    脏读

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

    时间事务A事务B
    T1开启事务开启事务
    T2查询账户余额:500元-
    T3取走100元,剩余400元-
    T4-查询余额:400元
    T5撤销事务,账户余额:500元-

    事务A在T3的时候取走了400元,但是未提交。事务B在T4时查询余额就能看到事务A未提交的更新。

    幻读

    幻读(虚读)是指:一个事务读到了另一个事务已提交的新增数据

    时间事务A事务B
    T1开启事务开启事务
    T2-执行select count统计
    T3新增一条数据-
    T4提交事务-
    T5-执行select count统计

    事务B在同一个事务中执行两次统计操作,得到的结果不一样

    不可重复读

    不可重复读:一个事务读到了另一个事务已提交的更新数据

    时间事务A事务B
    T1开启事务开启事务
    T2查询余额:500元查询余额:500元
    T3取走100元,剩余:400元-
    T4提交事务-
    T5-查询余额:400元

    事务B在同一个事务中,两次读取余额,得到的结果却不一样。

    第二类丢失更新

    第二类丢失更新是指:一个事务在提交的时候,覆盖了另一个事务已提交的更新数据

    时间事务A事务B
    T1开启事务开启事务
    T2查询账户余额:500元查询账户余额:500元
    T3取走100元,剩余400元取走100元,剩余400元
    T4提交事务,账户余额:400元-
    T5-提交事务,账户余额:400元

    事务A和事务B分别取了100元,所以余额应该为300元。但是事务B在提交的时候,覆盖了事务A已提交的更新数据,所以导致结果出错。

    为了解决这五类问题,MySQL提供了四种隔离级别

    • Serializable(串行化):事务之间以一种串行的方式执行,安全性非常高,效率低
    • Repeatable Read(可重复读):是MySQL默认的隔离级别,同一个事务中相同的查询会看到同样的数据行,安全性较高,效率较好
    • Read Commited(读已提交):一个事务可以读到另一个事务已经提交的数据,安全性较低,效率较高
    • Read Uncommited(读未提交):一个事务可以读到另一个事务未提交的数据,安全性低,效率高

    隔离级别与并发性能的关系图如下
    隔离级别与并发性
    需要注意的是,除了Serializable能完完全全的解决这五类问题之外,其余的三种隔离级别都不能完全解决这五类问题。各种隔离级别能解决的问题对应如下

    隔离级别是否出现第一类丢失更新是否出现脏读是否出现虚读是否出现不可重复读是否出现第二类丢失更新
    Serializable
    Repeatable Read
    Read Commited
    Read Uncommited

    Repeatable Read

    Repeatable Read(可重复读)是MySQL默认的隔离级别,也是使用最多的隔离级别,所以单独拿出来深入理解很有必要。Repeatable Read无法解决虚读(幻读)问题。下面来看一个实例
    SQL脚本

    # 建表
    CREATE TABLE student  (
      id int(4) primary key auto_increment,
      name varchar(10)
    ) ENGINE = InnoDB;
    
    # 插入一条数据
    insert into student(name) values('zhangsan');
    

    开启两个操作窗口,均关闭自动提交set autocommit = 0,其余的操作的时间线如下:

    时间事务A事务B
    T1select * from student-
    T2-insert into student(name) vaues ('lisi')
    T3-commit
    T4select * from student-

    按照上述理论,会出现幻读现象。也就是事务A的第二次select会看到事务B提交的新增数据。
    执行结果如下

    mysql> select * from student;
    +----+----------+
    | id | name     |
    +----+----------+
    |  1 | zhangsan |
    +----+----------+
    1 row in set (0.00 sec)
    

    和预期的结果并不一致,没有出现幻读现象。
    实际上MySQL在Repeatable Read隔离级别下,用MVCC(Multiversion Concurrency Control,多版本并发控制)解决了select普通查询的幻读现象。
    具体的实现方式就是事务开始时,第一条select语句查询结果集会生成一个快照(snapshot),并且这个事务结束前,同样的select语句返回的都是这个快照的结果,而不是最新的查询结果,这就是MySQL在Repeatable Read隔离级别对普通select语句使用的快照读(snapshot read)。

    快照读MVCC是什么关系呢?

    MVCC是多版本并发控制,快照就是其中的一个版本。所以可以说MVCC实现了快照读,具体的实现方式涉及到MySQL的隐藏列。MySQL会给每个表自动创建三个隐藏列

    • DB_TRX_ID:事务ID,记录操作(增、删、改)该数据事务的事务ID
    • DB_ROLL_PTR:回滚指针,记录上一个版本的数据在undo log中的位置
    • DB_ROW_ID:隐藏ID ,创建表没有合适的索引作为聚簇索引时,会用该隐藏ID创建聚簇索引

    由于undo log中记录了各个版本的数据,并且通过DB_ROLL_PTR可以找到各个历史版本,并且由DB_TRX_ID决定使用哪个版本(快照)。所以相当于undo log实现了MVCC,MVCC实现了快照读。

    如此看来,MySQL的Repeatable Read隔离级别利用快照读,已经解决了幻读的问题。但是事实并非如此,接下来再看一个例子
    继续上面的操作(注意:开始前,先提交上一次操作的事务)

    时间事务A事务B
    T1select * from student-
    T2-insert into student(name) values('wangwu')
    T3-commit
    T4update student set name = 'zhaoliu' where name = 'wangwu'-
    T5select * from student-

    事务A在T1的时候生成快照,事务B在T2的时候插入一条数据wangwu,然后提交。在T4的时候把wangwu更新成zhaoliu,根据上一个例子的经验,此时事务A是看不到wangwu这条数据的,所以更新也不会成功,并且在T5的时候查询,和T1时候一样,只有zhangsanlisi两条数据。
    执行结果如下

    mysql> select * from student;
    +----+----------+
    | id | name     |
    +----+----------+
    |  1 | zhangsan |
    |  2 | lisi     |
    |  3 | zhaoliu  |
    +----+----------+
    3 rows in set (0.00 sec)
    

    但是执行结果却不是预期的那样,事务A不仅看到了wangwu,还把它成功的改成了zhaoliu。即使事务A成功commit之后,再次查询还是这样。

    这其实是MySQL对insertupdatedelete语句所使用的当前读(current read)。因为涉及到数据的修改,所以MySQL必须拿到最新的数据才能修改,所以涉及到数据的修改肯定不能使用快照读(snapshot read)。由于事务A读到了事务B已提交的新增数据,所以就产生了前文所说的幻读

    那么在Repeatable Read隔离级别是怎么解决幻读的呢?

    是通过间隙锁(Gap Lock)来解决的。我们都知道InnoDB支持行锁,并且行锁是锁住索引。而间隙锁用来锁定索引记录间隙,确保索引记录的间隙不变。间隙锁是针对事务隔离级别为Repeatable Read或以上级别而已的,间隙锁和行锁一起组成了Next-Key Lock。当InnoDB扫描索引记录的时候,会首先对索引记录加上行锁,再对索引记录两边的间隙加上间隙锁(Gap Lock)。加上间隙锁之后,其他事务就不能在这个间隙插入记录。这样就有效的防止了幻读的发生。

    默认情况下,InnoDB工作在Repeatable Read的隔离级别下,并且以Next-Key Lock的方式对索引行进行加锁。当查询的索引具有唯一性(主键唯一索引)时,Innodb存储引擎会对Next-Key Lock进行优化,将其降为行锁,仅仅锁住索引本身,而不是范围(除非锁定不存在的值)。若是普通索引,则会使用Next-Key Lock将记录和间隙一起锁定。

    • 使用快照读的语句
      select * from ...
      
    • 使用当前读的语句
      select * from ... lock in share mode
      select * from ... for update
      insert into table...
      update table set ...
      delete table where ...
      

    更新

    感谢@mo_qy在评论区的提醒

    前一节Repeatable Read中部分内容描述有误,第二个实验

    时间事务A事务B
    T1select * from student-
    T2-insert into student(name) values('wangwu')
    T3-commit
    T4update student set name = 'zhaoliu' where name = 'wangwu'-
    T5select * from student-

    事务A在T1时刻和T5时刻,两条相同的查询语句在同一事务中看到了不同的结果集,这是符合幻读的定义的,MySQL官方定如下

    The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times.
    —— https://dev.mysql.com/doc/refman/5.6/en/innodb-next-key-locking.html

    这个实验中出现幻读的原因是事务A中没有使用到Next-Key Lock。仅仅是select子句只会产生快照读,不会加锁。要想使用Next-Key Lock需要改成select ... lock in share mode或者select ... for update。现在改造下上面的实验,首先看下表中数据

    mysql> select * from student;
    +----+----------+
    | id | name     |
    +----+----------+
    |  2 | lisi     |
    |  1 | zhangsan |
    +----+----------+
    2 rows in set (0.00 sec)
    

    实验步骤如下(记得关闭事务自动提交

    时间事务A事务B
    T1select * from student where id > 1 lock in share mode-
    T2-insert into student(id, name) values(3, 'wangwu')
    这条语句会被阻塞,直到事务A提交或者回滚,或者超时
    T3update student set name = 'zhaoliu' where id = 3
    这条语句会执行成功,但是不会修改任何数据
    -
    T4select * from student where id > 1-

    事务A在T1时刻执行的语句会给id > 1的索引和间隙加上Next-Key Lock,此时事务B便不能在记录2的后面插入新的数据,所以事务A在T1是可和T4时刻会查询到相同的结果集,这样就解决了幻读问题。

    总结

    本文主要讲解了MySQL事务的ACID四大特性、undo logredo log分别实现了原子性和持久性、log持久化的三种方式、数据库并发下的五类问题、四种隔离级别、RR隔离级别下select幻读通过MVCC机制解决、select ... lock in share mode/select ... for update/insert/update/delete的幻读通过间隙锁来解决。

    参考

    • https://dev.mysql.com/doc/refman/5.6/en/innodb-transaction-isolation-levels.html
    • https://www.cnblogs.com/zhoujinyi/p/3435982.html
    • https://dev.mysql.com/doc/refman/5.6/en/innodb-next-key-locking.html
    展开全文
  • MySQL事务

    万次阅读 2020-06-23 09:53:05
    1、INNODB事务原理 事务(Transaction)是数据库区别于文件系统的重要特性之一,事务会把数据库从一种一致性状态转换为另一种一致性状态。 在数据库提交时,可以确保要么所有修改都已保存,要么所有修改都不保存。 ...

    1、INNODB事务原理

    1. 事务(Transaction)是数据库区别于文件系统的重要特性之一,事务会把数据库从一种一致性状态转换为另一种一致性状态。
    2. 在数据库提交时,可以确保要么所有修改都已保存,要么所有修改都不保存。

    2、事务的特性

    1. 原子性(Atomicity):整个事物的所有操作要么全部提交成功,要么全部失败回滚(不会出现部分执行的情况)。
    2. 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致。
    3. 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
    4. 持久性(Durability): 一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

    3、事务隔离级别

    3.1 未提交读: 脏读(READ UNCOMMITTED)
    1)事务2查询到的数据是事务1中修改但未提交的数据,但因为事务1回滚了数据
    2)所以事务2查询的数据是不正确的,因此出现了脏读的问题。

    3.2 提交读: 不可重复读(READ COMMITTED)
    1)事务2执行update语句但未提交前,事务1的前两个select操作返回结果是相同的。
    2)但事务2执行commit操作后,事务1的第三个select操作就读取到事务2对数据的改变。
    3)导致与前两次select操作返回不同的数据,因此出现了不可重复读的问题。

    3.3 可重复读: 幻读(REPEATABLE READ):这是MySQL的默认事务隔离级别
    1)事务每开启一个实例,都会分配一个版本号给它,如果读取的数据行正在被其它事务执行DELETE或UPDATE操作(即该行上有排他锁)
    2)这时该事物的读取操作不会等待行上的锁释放,而是根据版本号去读取行的快照数据(记录在undo log中)
    3)这样,事务中的查询操作返回的都是同一版本下的数据,解决了不可重复读问题。
    4)虽然该隔离级别下解决了不可重复读问题,但理论上会导致另一个问题:幻读(Phantom Read)。
    5)一个事务在执行过程中,另一个事物对已有数据行的更改,MVCC机制可保障该事物读取到的原有数据行的内容相同
    6)但并不能阻止另一个事务插入新的数据行,这就会导致该事物中凭空多出数据行,像出现了幻读一样,这便是幻读问题。

    3.4 可串行读(SERIALIZABLE)
    1)这是事务的最高隔离级别,通过强制事务排序,使之不可能相互冲突,就是在每个读的数据行加上共享锁来实现
    2)在该隔离级别下,可以解决前面出现的脏读、不可重复读和幻读问题,但也会导致大量的超时和锁竞争现象,一般不推荐使用

    4、关于事务的术语

    开启事务:Start Transaction
    事务结束:End Transaction
    提交事务:Commit Transaction
    回滚事务:Rollback Transaction

    5、事务开启和结束的标志

    5.1 开启标志

    • 任何一条DML语句(insert、update、delete)执行,标志事务的开启
      5.2 结束标志
    • 提交:成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步
    • 回滚:失败的结束,将所有的DML语句操作历史记录全部清空

    6、事务与数据库底层数据

    在事物进行过程中,未结束之前,DML语句是不会更改底层数据,只是将历史操作记录一下,在内存中完成记录。只有在事物结束的时候,而且是成功的结束的时候,才会修改底层硬盘文件中的数据

    7、mysql事务提交与回滚

    在MySQL中,默认情况下,事务是自动提交的,也就是说,只要执行一条DML语句就开启了事物,并且提交了事务
    自动提交机制是可以关闭的
    对t_user进行提交和回滚操作

    提交操作(事务成功)
    start transaction
    DML语句
    commit

    mysql> start transaction;#手动开启事务
    mysql> insert into t_user(name) values('pp');
    mysql> commit;#commit之后即可改变底层数据库数据
    mysql> select * from t_user;
    +----+------+
    | id | name |
    +----+------+
    |  1 | jay  |
    |  2 | man  |
    |  3 | pp   |
    +----+------+
    3 rows in set (0.00 sec)
    

    回滚操作(事务失败)
    start transaction
    DML语句
    rollback

    mysql> start transaction;
    mysql> insert into t_user(name) values('yy');
    mysql> rollback;
    mysql> select * from t_user;
    +----+------+
    | id | name |
    +----+------+
    |  1 | jay  |
    |  2 | man  |
    |  3 | pp   |
    +----+------+
    3 rows in set (0.00 sec)
    
    
    展开全文
  • nodejs + mysql 事物处理问题 呵呵 看了就知道 记得npm install啊 需要的东西啊 本想免费 苦于没积分 ,需要的的同学,给点分吧
  • Spring事务和MySQL事务详解

    万次阅读 2020-04-24 01:06:49
    文章目录数据库事务事务是什么事务的四大特性MySQL事务隔离级别查看MySQL当前事务隔离级别MySQL默认操作模式为自动提交模式JDBC处理事务Spring事务Spring的事务传播PROPAGATION_REQUIREDPROPAGATION_...
  • Mysql 事务

    千次阅读 2017-04-17 11:29:40
    SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。 一、Read Uncommitted(读取未提交内容) ...
  • mysql事务的使用

    千次阅读 2019-04-04 11:26:05
    本文实验的测试环境:Windows 10+cmd+MySQL5.6.36+InnoDB 一、事务的基本要素(ACID)  1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,...
  • MySQL 事务和锁

    2021-02-27 15:41:49
    Re: MySQL 事务和锁  ========================================== # 事务是什么 特性:原子性、一致性、隔离性和持久性 类型:自动提交事务(default)、隐式事务、显式事务和分布式事务 事务并发带来的若干...
  • mysql事务管理及python操作

    千次阅读 2019-05-08 20:29:23
    在用户操作MySQL过程中,对于一般简单的业务逻辑或中小型程序而言,无需考虑应用MySQL事务。但在比较复杂的情况下,往往用户在执行某些数据操作过程中,需要通过一组SQL语句执行多项并行业务逻辑或程序,这样,就...
  • mysql事务提交和回滚机制

    千次阅读 2020-02-06 10:28:03
     mysql事务回滚怎样实现的代码可以参考此bolg:http://bbs.csdn.net/topics/390876901   要同时修改数据库中两个不同表时,如果它们不是一个事务的话,当第一个表修改完,可能第二个表修改过程中出现了异常而...
  • Mysql事务的实现原理

    万次阅读 2019-08-16 17:56:53
    MySQL 是一个支持多引擎的系统,但并不是所有的引擎都支持事务。比如 MySQL 原生的 MyISAM 引擎就不支持事务,这也是 MyISAM 被 InnoDB 取代的重要原因之一。 4个隔离级别:read uncommited ,read commited ...
  • MySQL事务的实现原理

    千次阅读 2020-01-13 18:01:00
    点击上方“朱小厮的博客”,选择“设为星标”后台回复”1024“获取公众号专属1024GB资料来源:rrd.me/fDv2c1. 开篇相信大家都用过事务以及了解他的特点,如原子性(Atom...
  • MySQL事务底层实现原理

    千次阅读 2019-10-23 16:37:36
    事务特性 事务特性分为: 原子性 每一个事务都是不可分割的整体,要么全部成功要么全部失败; 一致性 事务执行后的结果是和预设的规则完全符合的,不会因为出现系统意外等原因和预测的结果不一致; 隔离性 事务与...
  • MySQL事务隔离级别详解

    万次阅读 多人点赞 2018-12-27 00:45:23
    MySQL中,事务支持实在引擎层实现的,MySQL是一个支持多引擎的系统,但并不是所有引擎都支持事务。比如MySQL原生的 MyISAM 引擎就不支持事务,这也是 MyISAM 被取代的原因之一。 隔离性 事务的四大特性AC...
  • MySQL事务与锁详解

    千次阅读 2018-10-13 17:05:01
    事务 事务支持ACID特性 A原子性:所有操作要么都做要么都不做 C一致性:事务将数据库从一种状态变为另一种状态一致性,保证数据库完整性约束,例如唯一索引约束等 I隔离性:事务事务之间是不可见的 D持久性:事务一旦...
  • MySQL事务保存点

    千次阅读 2021-01-09 20:18:20
    一:我们在这里提出一个事务“保存点”的概念 那什么是保存点?粗略来讲相当于Java中的“断点”,设置一个断点,当你在数据库中插入一条数据后,在这条语句后面设置一个savepoint,当你需要rollback的时候,只需要...
  • MySQL事务隔离性说明

    千次阅读 2019-03-24 18:33:13
    MySQL定义了4类隔离级别,包括一些具体规则,用来限定事物内外的哪些改变时可见的,哪些改变时不可见的,低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。 第一类: Read Uncommitted(读取未提交的...
  • mysql事务的面试题

    千次阅读 2019-08-15 18:24:45
    1.Mysql中InnoDB支持的四种事务隔离级别名称,以及逐级之间的区别? SQL标准定义的四个隔离级别为: read uncommited :读到未提交数据 read committed:脏读,不可重复读 repeatable read:可重读 ...
  • Mysql事务以及InnoDB和MyISAM区别讲解

    千次阅读 多人点赞 2020-12-13 22:53:47
    【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,博客昵称是希望自己能不断精进,向着...文章目录一、数据库事务简介二、InnoDB 和 MyISAM三、MYSQL引擎简介 一、数据库事务简介 写这篇文章初衷是有一个大佬.
  • MySQL事务实现原理

    千次阅读 2019-05-09 22:54:45
    MySql事务实现原理--参考极客时间专栏《MySQL实战45讲》,博客 1.事务的基本要素(ACID) 原子性(Atomicity):事务内的操作要嘛全部完成,要嘛全部回滚。 一致性(Consistency):事务执行的前后都是合法的数据...
  • MySQL事务的启动和实现

    千次阅读 2019-03-26 14:40:20
    MySQL 中,实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值。 假设一个值从 1 被按顺序改成了 2、3、4,在回滚日志里面就...
  • NodeJS实现MySQL事务处理

    千次阅读 2019-09-16 01:02:29
    1、构建事务处理函数 execTrans(sqlparamsEntities, callback) { connection.beginTransaction(function (err) { if (err) { return callback(err, null); } console.log("开始执行trans...
  • MySQL 事务

    千次阅读 2020-07-06 17:45:30
    一篇文章让你看懂什么是 MySQL 事务
  • nodejs之mysql事务封装与使用

    千次阅读 2018-11-10 15:54:10
    nodejs之mysql事务封装简介所需模块文件结构干货部分1 此部分为mysql初始化配置信息:2 数据库连接3 orderModel的封装和对数据库的使用4 model使用到这里我们就结束了,如果你喜欢,那谢谢你的浏览,如果不喜欢,...
  • Mysql事务及性能优化

    千次阅读 2018-09-04 15:42:20
    一、事务的基本要素(ACID)  1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也...
  • mysql事务隔离级别

    千次阅读 2019-06-01 08:13:07
    MySQL是一个服务器/客户端架构的软件,对于同一个服务器来说,可以有若干个客户端与之连接,每个客户端与服务器连接上之后,就可以称之为一个会话(Session)。我们可以同时在不同的会话里输入各种语句,这些语句...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 409,931
精华内容 163,972
关键字:

mysql事务

mysql 订阅