MySQL事务

MySQL事务

  1. 事务的概念和特点

    事务,就是”要完成的一件事情”,比如转账,做饭,洗澡等等;

    做一件事情通常由多个步骤组成,如果某个步骤失败,那么这件事情将不会完成;

    事务Transaction,是指作为一个基本工作单元执行的一系列SQL语句的操作,要么完全的执行,要么完全的都不执行。

  2. 事务隔离级别

    事务隔离级别指的是在处理同一个数据的多个事务中,一个事务修改数据后,其他事务何时能看到修改后的结果。数据库事务的隔离级别有4个,由低到高依次为Read uncommitted 、Read committed 、Repeatable read 、Serializable ,这四个级别可以逐个解决脏读 、不可重复读 、幻读这几类问题。

  3. MySQL数据库事务隔离级别主要有四种:
    • Serializable:串行化,一个事务一个事务的执行。是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。

    • Repeatable read:重复读,无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响,可以避免不可重复读,但还有可能出现幻读 ;

    • Read committed:读取已提交,其他事务提交了对数据的修改后,本事务就能读取到修改后的数据值,避免了脏读,但是可能会造成不可重复读;

    • Read uncommitted:读取未提交,其他事务只要修改了数据,即使未提交,本事务也能看到修改后的数据值,就可能出现脏读;

    • MySQL数据库默认使用可重复读( Repeatable read)。

  4. 脏读,幻读,不可重复读
    1. 脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
  5. 不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容),例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。
    3. 幻读:是指当事务不是独立执行时发生的一种现象,例如:第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象
    发生了幻觉一样。

  6. 修改MySQL数据库事务隔离级别
    1. 场景

      ​ 使用乐观锁的时候,如果一个事务修改了库存并提交了事务,那其他的事务应该可以读取到修改后的数据值,所以不能使用可重复读的隔离级别,应该修改为读取已提交(Read committed)。

    2. 修改方式(ubuntu为例)

      # 修改配置文件
      cd /etc/mysql/mysql.conf.d/
      sudo vim mysqld.cnf
      
      # 添加以下代码
      transaction-isolation=READ-COMMITTED
      
  7. 事务四大特性(ACID)
    1. Atomicity(原子性):一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即事务不可分割、不可约简。
    2. Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
    3. Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括未提交读(Read uncommitted)、提交读(read committed)、可重复读(repeatable read)和串行化(Serializable)。
    4. Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
  8. 事务的使用

    在使用事务之前,先要确保表的存储引擎是 InnoDB 类型, 只有这个类型才可以使用事务,MySQL数据库中表的存储引擎默认是 InnoDB 类型。

    表的存储引擎说明:

    表的存储引擎就是提供存储数据一种机制,不同表的存储引擎提供不同的存储机制。

    查看MySQL数据库支持的表的存储引擎:

    -- 查看MySQL数据库支持的表的存储引擎
    show engines;
    

    说明:

    • 常用的表的存储引擎是 InnoDB 和 MyISAM
    • InnoDB 是支持事务的
    • MyISAM 不支持事务,优势是访问速度快,对事务没有要求或者以select、insert为主的都可以使用该存储引擎来创建表
    1. 开启事务
      begin;
      或者
      start transaction;
      
      说明:
      1. 开启事务后执行修改命令,变更会维护到本地缓存中,而不维护到物理表中;

      2. MySQL数据库默认采用自动提交(autocommit)模式,如果没有显示的开启一个事务,那么每条sql语句都会被当作一个事务执行提交的操作

      3. 当设置autocommit=0就是取消了自动提交事务模式,直到显示的执行commit和rollback表示该事务结束。

        • set autocommit = 0 表示取消自动提交事务模式,需要手动执行commit完成事务的提交
        set autocommit = 0;
        insert into students(name) values('刘三峰');
        -- 需要执行手动提交,数据才会真正添加到表中, 验证的话需要重新打开一个连接窗口查看表的数据信息,因为是临时关闭自动提交模式
        commit
        
        -- 重新打开一个终端窗口,连接MySQL数据库服务端
        mysql -uroot -p
        
        -- 然后查询数据,如果上个窗口执行了commit,这个窗口才能看到数据
        select * from students;
        
    2. 提交事务:
      commit;
      

      将缓存的数据变更维护到物理表中;当commit一瞬间才执行以上sql语句,完成数据的更新。;

    3. 回滚事务:放弃缓存变更的数据,表示事务执行失败,应该回到开始事务前的状态;

      rollback;
      
    4. 事务演练的SQL语句:
      begin;
      insert into students(name) values('李白');
      -- 查询数据,此时有新增的数据, 注意: 如果这里后续没有执行提交事务操作,那么数据是没有真正的更新到物理表中
      select * from students;
      -- 只有这里提交事务,才把数据真正插入到物理表中
      commit;
      
      -- 新打开一个终端,重新连接MySQL数据库,查询students表,这时没有显示新增的数据,说明之前的事务没有提交,这就是事务的隔离性
      -- 一个事务所做的修改操作在提交事务之前,对于其他事务来说是不可见的
      select * from students;
      
    总结:
    1. 事务的特性:
      • 原子性: 强调事务中的多个操作时一个整体;
      • 一致性: 强调数据库中不会保存不一致状态;
      • 隔离性: 强调数据库中事务之间相互不可见;
      • 持久性: 强调数据库能永久保存数据,一旦提交就不可撤销;
    2. MySQL数据库默认采用自动提交(autocommit)模式,也就是说修改数据(insert、update、delete)的操作会自动的触发事务,完成事务的提交或者回滚;
    3. 开启事务使用 begin 或者 start transaction;
    4. 回滚事务使用 rollback;
    5. pymysql 里面的 conn.commit() 操作就是提交事务;
    6. pymysql 里面的 conn.rollback() 操作就是回滚事务;

你可能感兴趣的:(数据库,MySQL事务)