精华内容
下载资源
问答
  • mysql事务管理
    千次阅读
    2019-05-08 20:29:23

    在用户操作MySQL过程中,对于一般简单的业务逻辑或中小型程序而言,无需考虑应用MySQL事务。但在比较复杂的情况下,往往用户在执行某些数据操作过程中,需要通过一组SQL语句执行多项并行业务逻辑或程序,这样,就必须保证所用命令执行的同步性。使执行序列中,产生依靠关系的动作能够同时操作成功或同时返回初始状态。在此情况下,就需要用户优先考虑使用MySQL事务处理。

    在MySQL中,事务由单独单元的一个或多个SQL语句组成。在这个单元中,每个MySQL语句是相互依赖的。而整个单独单元作为一个不可分割的整体,如果单元中某条SQL语句一旦执行失败或产生错误,整个单元将会回滚。所有受到影响的数据将返回到事务开始以前的状态;如果单元中的所有SQL语句均执行成功,则事务被顺利执行。

    通过InnoDB和BDB类型表,MySQL事务能够完全满足事务安全的ACID测试,但是并不是所有表类型都支持事务,如MyISAM类型表就不能支持事务,只能通过伪事务对表实现事务处理。

    MySQL事务的创建与存在周期

    创建事务

    创建事务的一般过程是:初始化事务、创建事务、应用SELECT语句查询数据是否被录入和提交事务。如果用户不在操作数据库完成后执行事务提交,则系统会默认执行回滚操作。如果用户在提交事务前选择撤销事务,则用户在撤销前的所有事务将被取消,数据库系统会回到初始状态。

    默认情况下,在MySQL中创建的数据表类型都是MyISAM,但是该类型的数据表并不能支持事务。所以,如果用户想让数据表支持事务处理能力,必须将当前操作数据表的类型设置为InnoDB或BDB。

    在创建事务的过程中,用户需要创建一个InnoDB或BDB类型的数据表,其基本命令结构如下:

    CREATE TABLE table_name(field-defintions)TYPE=INNODB/BDB;

    其中,table_name为表名,而field_defintions为表内定义的字段等属性,TYPE为数据表的类型,既可以是InnoDB类型,同样也可以是BDB类型。

    当用户希望已经存在的表支持事务处理,则可以应用ALTER TABLE命令指定数据表的类型实现对表的类型更改操作,使原本不支持事务的数据表更改为支持事务处理的类型。其命令如下:

    ALTER TABLE table_name TYPE=INNODB/BDB;

    当用户更改完表的类型后,即可使数据表支持事务处理。

    应用ALTER TABLE操作可能会导致数据库中数据丢失,因此为了避免非预期结果出现,在使用ALTER TABLE命令之前,用户需要创建一个表备份。

    初始化事务

    初始化MySQL事务,首先声明初始化MySQL事务后所有的SQL语句为一个单元。在MySQL中,应用START TRANSACTION命令来标记一个事务的开始。初始化事务的结构如下:

    START TRANSACTION;

    另外,用户也可以使用BEGIN或者BEGIN WORK命令初始化事务,通常START TRANSACTION命令后面跟随的是组成事务的SQL语句。

    在命令提示符中输入如下命令:

    start transaction;

    如果在用户输入以上代码后,MySQL数据库没有给出警告提示或返回错误信息,则说明事务初始化成功,用户可以继续执行下一步操作。

    创建事务

    insert into connection(email, cellphone, QQ, sid)

    values('barrystephen@126.com',13456000000,187034000,3);

    应用SELECT语句查看数据是否被正确输入

    SELECT * FROM connection WHERE sid=3;

    ps:在用户插入新表为"InnoDB"类型或更改原来表类型为"InnoDB"时,如果在输入命令提示后,MySQL提示"The 'InnoDB' feature is disabled;you needInnoDB' to have it working"警告,则说明InnoDB表类型并没有被开启,用户需要找到MySQL文件目录下的"my.ini"文件,定位"skip_innodb"选项位置,将原来的"skip_innodb"改为"#skip_innodb"后保存该文件,重新启动MySQL服务器,即可令数据库支持"InnoDB"类型表。 

    提交事务

    在用户没有提交事务之前,当其他用户连接MySQL服务器时,应用SELECT语句查询结果,则不会显示没有提交的事务。当且仅当用户成功提交事务后,其他用户才可能通过SELECT语句查询事务结果,由事务的特性可知,事务具有孤立性,当事务处在处理过程中,其实MySQL并未将结果写入磁盘中,这样一来,这些正在处理的事务相对其他用户是不可见的。一旦数据被正确插入,用户可以使用COMMIT命令提交事务。提交事务的命令结构如下:

    COMMIT

    一旦当前执行事务的用户提交当前事务,则其他用户就可以通过会话查询结果。

    撤销事务(事务回滚)

    撤销事务,又被称作事务回滚。即事务被用户开启、用户输入的SQL语句被执行后,如果用户想要撤销刚才的数据库操作,可使用ROLLBACK命令撤销数据库中的所有变化。ROLLBACK命令结构如下:

    ROLLBACK

    输入回滚操作后,如何判断是否执行回滚操作了呢?可以通过SELECT语句查看11.2.2小节中插入的数据是否存在.

    如果执行一个回滚操作,则在输入START TRANSACTIONA命令后的所有SQL语句都将执行回滚操作。故在执行事务回滚前,用户需要慎重选择执行回滚操作。如果用户开启事务后,没有提交事务,则事务默认为自动回滚状态,即不保存用户之前的任何操作。

    事务的存在周期

    事务的周期由用户在命令提示符中输入START TRANSACTION指令开始,直至用户输入COMMIT结束.

    事务不支持嵌套功能,当用户在未结束第一个事务又重新打开一个事务,则前一个事务会自动提交,同样MySQL命令中很多命令都会隐藏执行COMMIT命令。

    MySQL行为

    在MySQL中,存在两个可以控制行为的变量,它们分别是AUTOCOMMIT变量和TRANSACTION ISOLACTION LEVEL变量。

    自动提交

    在MySQL中,如果不更改其自动提交变量,则系统会自动向数据库提交结果,用户在执行数据库操作过程中,不需要使用START TRANSACTION语句开始事务,应用COMMIT或者ROLLBACK提交事务或执行回滚操作。如果用户希望通过控制MySQL自动提交参数,可以更改提交模式,这一更改过程是通过设置AUTOCOMMIT变量来实现。

    下面通过一个示例向读者展示如何关闭自动提交参数。在命令提示符中输入以下命令:

    SET AUTOCOMMIT=0;

    只有当用户输入COMMIT命令后,MySQL才将数据表中的资料提交到数据库中,如果不提交事务,而终止MySQL会话,数据库将会自动执行回滚操作。

    可以通过查看"@@AUTOCOMMIT"变量来查看当前自动提交状态,查看此变量SELECT @@AUTOCOMMIT。

    事务的隔离级别

    基于ANSI/ISO SQL规范,MySQL提供4种孤立级:

    SERIALIZABLE(序列化)

    REPEATABLE READ(可重读)

    READ COMMITTED(提交后读)

    READ UNCOMMITTED(未提交读)

    在MySQL中,可以使用TRANSACTION ISOLATION LEVEL变量来修改事务孤立级,其中,MySQL的默认隔离级别为REPEATABLE READ(可重读),用户可以使用SELECT命令获取当前事务孤立级变量的值,其命令如下:

    SELECT @@tx_isolation;

    如果用户想要修改事务的隔离级别,必须首先获取SUPER优先权,以便用户可以顺利执行修改操作,set。

    事务的使用技巧和注意事项

    应用小事务,保证每个事务不会在执行前等待很长时间,从而避免各个事务因为互相等待而导致系统性能的大幅度下降。

    选择合适的孤立级,因为事务的性能与其对服务器产生的负载成反比,即当事务孤立级越高,其性能越低,但是其安全性也越高。只有选择适当的孤立级,才能有效地提高MySQL系统性能和应用性。

    死锁的概念与避免,即当两个或者多个处于不同序列的用户打算同时更新某相同的数据库时,因互相等待对方释放权限而导致双方一直处于等待状态。在实际应用中,两个不同序列的客户打算同时对数据执行操作,极有可能产生死锁。更具体地讲,当两个事务相互等待操作对方释放所持有的资源,而导致两个事务都无法操作对方持有的资源,这样无限期的等待被称作死锁。MySQL的InnoDB表处理程序具有检查死锁这一功能,如果该处理程序发现用户在操作过程中产生死锁,该处理程序立刻通过撤销操作来撤销其中一个事务,以便使死锁消失。这样就可以使另一个事务获取对方所占有的资源而执行逻辑操作。

    MySQL伪事务

    在MySQL中,InnoDB和BDB类型表可以支持事务处理,但是MySQL中MyISAM类型表并不能支持事务处理,对于某些应用该类型的数据表,用户可以选择应用表锁定来替代事务。这种引用表锁定来替代事务的事件被称作伪事务。使用表锁定来锁定表的操作,可以加强非事务表在执行过程的安全性和稳定性。

    用表锁定代替事务

    在MySQL的MyISAM类型数据表中,并不支持COMMIT(提交)和ROLLBACK(回滚)命令。当用户对数据库执行插入、删除、更新等操作时,这些变化的数据都被立刻保存在磁盘中。这样,在多用户环境中,会导致诸多问题。为了避免同一时间有多个用户对数据库中指定表进行操作,可以应用表锁定来避免在用户操作数据表过程中受到干扰。当且仅当该用户释放表的操作锁定后,其他用户才可以访问这些修改后的数据表。

    设置表锁定代替事务基本步骤如下:

    (1)为指定数据表添加锁定。其语法如下:

    LOCK TABLES table_name lock_type,……

    其中,table_name为被锁定的表名,lock_type为锁定类型,该类型包括以读方式(READ)锁定表,以写方式(WRITE)锁定表。

    (2)用户执行数据表的操作,可以添加、删除或者更改部分数据。

    (3)用户完成对锁定数据表的操作后,需要对该表进行解锁操作,释放该表的锁定状态。其语法如下:

    UNLOCK TABLES

    以读方式锁定数据表,该方式是设置锁定用户的其他方式操作,如删除、插入、更新都不被允许,直至用户进行解锁操作。

    lock table studentinfo read;

    其中的lock_type参数中,用户指定数据表以读方式(READ)锁定数据表的变体为READ LOCAL锁定,其与READ锁定的不同点是,该参数所指定的用户会话可以执行INSERT操作,它是为了使用MySQL dump工具而创建的一种变体形式。

    以写方式锁定数据表,该方式是是设置用户可以修改数据表中的数据,但是除自己以外其他会话中的用户不能进行任何读操作。在命令提示符中输入如下命令:

    lock table studentinfo write;

    当数据表被释放锁定后,其他访问数据库的用户即可查看数据表的内容。

    应用表锁实现伪事务

    通过使用表锁定对MyISAM表进行锁定操作,以此过程来代替事务型表InnoDB,即应用表锁定来实现伪事务。实现伪事务的一般步骤如下:

    (1)对数据库中的数据表进行锁定操作,可以对多个表做不同的方式锁定,其代码格式如下:

    LOCK TABLE table_name1 lock_type1,table_name2 lock_type2,……

    (2)执行数据库操作,向锁定的数据表中执行添加、删除、修改操等操作。

    如前面提到的INSERT、UPDATE、DELETE等操作。用户可以对锁定的数据表执行上述操作,在执行过程中,该伪事务所产生的结果是不会被其他用户更改的。

    (3)释放锁定的数据表,以便让正在队列中等待查看或操作的其他用户可以浏览数据表中的数据或对操作表执行各种数据的操作。

    如果存在其他会话要求访问已锁定的多个表格,则该会话必须被迫等待当前锁定用户释放锁定表。才允许其他会话访问该数据表,表锁定使不同会话执行的数据库操作彼此独立。应用数据表锁定方式可以使不支持事务类型的表实现伪事务。

    Python 执行 MySQL 事务

    一、MySQL 事务

    事务就是指逻辑上的一组 SQL 操作,组成这组操作的各个 SQL 语句,执行时要么全成功要么全失败。

    举个例子,小明给小红转账100元,转账过程实际上就是小明的账户减少100元,小红的账户增加100元,对应的SQL语句为:

    update account set money=money-5 where name='xiaoming';

    update account set money=money+5 where name='xiaohong';

    上述的两条SQL操作,在事务中的操作就是要么都执行成功,要么都执行失败,如果只有第一条成功,那么小明就损失100元,而小红并没有收到100元,这是不可取的,所以这就是事务,事务就是指逻辑上的一组SQL 操作,组成这组操作的各个 SQL 语句,执行时要么全成功要么全失败。事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行,在 MySQL 中只有使用了 Innodb 库引擎的数据库或表才支持事务,所以很多情况下我们都使用 Innodb 引擎.

    事务的特性如下:

    原子性:事务是一个不可分割的单位,事务中的所有 SQL 操作要么都成功,要么都失败

    一致性:事务发生前和发生后,数据的完整性必须保持一致

    隔离性:当并发访问数据库时,一个正在执行的事务在执行完毕前,对于其它的会话是不可见的,多个并发事务之间的数据是相互隔离的

    持久性:一个事务一旦被提交,它对数据库中的数据改变就是永久性的,如果出了错误,事务也不允许撤销,只能通过 "补偿性事务"

    mysql> begin # 开启事务
    mysql> rollback # 回滚事务
    mysql> commit # 提交事务

    数据库默认事务是自动提交的,也就是说,当我们执行 select,insert,update,delete 等操作时,就会自动提交事务,如果关闭事务的自动提交,那么我们执行完 select,insert,update,delete 操作后需要再执行 commit 来提交事务,否则就不会执行

    二、游标

    游标是系统为用户开设的一个数据缓冲区,存放 SQL 语句的执行结果,用法如下:

    In [1]: import pymysql

    In [2]: c = MySQLdb.connect(user='root', passwd='root', db='test') # 连接数据库

    In [3]: cus = c.cursor() # 创建一个游标对象

    In [4]: cus.execute('select * from user;') # 使用execute()方法可以执行SQL语句,执行后的结果会存在缓冲区
    Out[4]: 4L

    In [5]: result1 = cus.fetchone() # 可以使用fetchone()来查看缓冲区的一条记录

    In [6]: result2 = cus.fetchmany(3) # 可以使用fetchmany()来查看缓冲区的多条记录

    In [7]: result3 = cus.fetchall() # 可以使用fetchall()来查看所有的记录

    三、根据游标执行 MySQL 事务

    #!/usr/bin/env python
    import pymysql

    def connect_mysql():
    db_config = {
    'host': '127.0.0.1',
    'port': 3306,
    'user': 'root',
    'passwd': 'pzk123'
    }
    c = pymysql.connect(**db_config)
    return c

    if __name__ == '__main__':
    c = connect_mysql() # 首先连接数据库
    cus = c.cursor() # 生成游标对象
    sql = 'drop database test;' # 定义要执行的SQL语句
    try:
    cus.execute(sql) # 执行SQL语句
    c.commit() # 如果执行成功就提交事务
    except Exception as e: 
    c.rollback() # 如果执行失败就回滚事务
    raise e
    finally:
    c.close() # 最后记得关闭数据库连接

    更多相关内容
  • 本文实例讲述了mysql事务管理操作。分享给大家供大家参考,具体如下: 本文内容: 什么是事务管理 事务管理操作 回滚点 默认的事务管理 首发日期:2018-04-18 什么是事务管理: 可以把一系列要执行的操作称为...
  • MySQL事务管理

    2022-01-20 23:59:19
    事务的隔离级别

    目录

    1. 事务的特性

    2. 事务的隔离级别

     3. 隔离级别验证

    3.1 读取未提交

    3.2 读取已提交

    3.3  可重复读

    3.4 串行化


    1. 事务的特性

    有四个,总结起来叫做ACID(与一些标准的解释可能不太一致):

    A (atomicity)原子性 :一个事务的执行操作序列是一个整体,要们全部全部执行成功,要么都都执行失败,不存在部分执行成功部分失败的情况

    C(consistency)一致性 :数据库会有增删改的操作,在这个操作前后保持业务逻辑一致

    I (Isolation) 隔离性:并发事务中有的概念,单个事务不会出问题,但多个事务并发执行就会出现各种数据问题,事务隔离级别解决了各种问题

    D (Durability)持久性:对数据操作完成后,效果是持久的,不回因为断电等原因而消失,就是存储到了磁盘上了,不是存在内存中就完事了

    最终的目标是为了保证数据库数据的一致性

    2. 事务的隔离级别

    如果不考虑事务的隔离级别,会有什么问题?会有脏读、不可重复度、幻读的问题,不同事务的隔离级别解决对应的问题。

    脏读

      

    不可重复读

    幻读

    事务的隔离级别如表格所示

    注意:对于幻读,一般数据库在可重读的级别是有幻读的问题,在MySQL中通过Gap锁实现了在可重复度的幻读问题。 

     3. 隔离级别验证

    前提条件

    1. 针对的数据库为MySQL,版本为5.7.x
    2. MySQL查看事务隔离级别命令:
      -- 查看当前会话的隔离级别
      select @@tx_isolation;
      -- 查看全局的隔离级别
      select @@global.tx_isolation;
    3. MySQL数据库的隔离级别会话级设置命令:
      -- 设置读取未提交
      set session transaction isolation level READ UNCOMMITTED;
      -- 设置读取已经提交
      set session transaction isolation level READ COMMITTED;
      -- 设置可重复读
      set session transaction isolation level REPEATABLE READ;
      -- 设置串行化
      set session transaction isolation level SERIALIZABLE;
    4. MySQL事务常用操作:
      -- 设置事务提交模式,0表示禁止自动提交 1表示自动提交
      SET AUTOCOMMIT=0|1 
      -- 开始事务
      BEGIN; 
      -- 提交事务
      COMMIT
      -- 回滚事务
      ROLLBACK;
      

      5.准备一张表和数据

      CREATE TABLE IF NOT EXISTS `t_user`(
         `id` INT UNSIGNED AUTO_INCREMENT,
         `name` VARCHAR(100) NOT NULL comment '名字',
         `money` INT comment '账户金额',                        
         PRIMARY KEY ( `id` )
      )ENGINE=InnoDB DEFAULT CHARSET=utf8;
      
      
      BEGIN;
      INSERT INTO `t_user` VALUES (1, '张三', 100);
      INSERT INTO `t_user` VALUES (2, '李四', 100);
      INSERT INTO `t_user` VALUES (3, '王五', 100);
      COMMIT;

    3.1 读取未提交

    控制台打开两个界面开启两个会话,设置会话的隔离级别为“读取未提交”,确认两点,是否禁止自动提交,是否为“读取未提交”隔离级别:

    两个控制台的执行流程如下:

     分析:

    • (3)中第一次查询到money的数据为100,(4)步骤更新没有提交,但是再次查询得到money的结果为150,这里查到数据为脏数据
    • (3)(5)数据不一致出现不可重读

    3.2 读取已提交

    控制台打开两个界面开启两个会话,设置会话的隔离级别为“读取已提交”,确认两点,是否禁止自动提交,是否为“读取已提交”隔离级别:

     两个控制台的执行流程如下:

    分析:

    • (3)第一次查询money为100,(4)更新操作,(5)再次查询到结果仍然为100,所以没有脏读的问题
    • (6)对修改进行提交,(7)再次读取到的结果为150,还是有不可重复读问题 

    3.3  可重复读

    控制台打开两个界面开启两个会话,设置会话的隔离级别为“可重复读”,确认两点,是否禁止自动提交,是否为“可重复读”隔离级别:

     两个控制台的执行流程如下:

    分析:

    • (3)第一次查询money为100,(4)更新操作,(5)再次查询到结果仍然为100,所以没有脏读的问题
    • (6)对修改进行提交,(7)再次读取到的结果为100,解决了不可重复读问题 
    • (8)提交掉当前事务,新事务查询出的结果为150

    3.4 串行化

    控制台打开两个界面开启两个会话,设置会话的隔离级别为“串行化”,确认两点,是否禁止自动提交,是否为“串行化”隔离级别:

     两个控制台的执行流程如下:

     分析:

    • (3)事务执行的时候,另一个事务执行修改语句,就必须排队等待执行了,并且有超时机制,超过时间直接放弃修改
    • (3)执行查询,其他事务也可以执行查询
    展开全文
  • MySQL——事务管理

    千次阅读 2021-12-15 15:29:26
    一个MySQL数据库,肯定不是一个事务在运行,所以当出现冲突时,那些执行一半的sql语句组成的事务,应该怎么办呢? 备注: sql语句: DDL(定义数据库对象,表与列), DML(用于操作数据库表中的记录数据), ...

    当不控制创建,更新,读取,删除时,会出现什么问题?

     需要在购买后及时更新数据,避免发生错误。

    什么是事务?

    事务是一组数据库操作语句(DML),一组要么全部成功,要么全部失败。

    事务是多个操作构成的实现一个事情的整体。

    一个MySQL数据库,肯定不是一个事务在运行,所以当出现冲突时,那些执行一半的sql语句组成的事务,应该怎么办呢?

    备注:

    sql语句:

    • DDL(定义数据库对象,表与列),
    • DML(用于操作数据库表中的记录数据),
    • DQL(查询数据),
    • DCL(定义访问权限和安全级别)

    所以,事务不能单单是sql语句的组合,还需要有以下属性。

    • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
    • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
    • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Read uncommitted )、读提交( read committed )、可重复读( repeatable read )和串行化( Serializable )
    • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

    为什么会出现事务

    事务是为了当应用程序访问数据库时,可以简化我们的编程模型。

    事务的版本支持

    MySQL中只有使用了innodb数据库引擎的数据库或表才支持事务,myisam不支持。

    事务提交方式

    事务提交方式常见的有两种:

    • 自动提交
    • 手动提交

    查看事务提交方式

     用 SET 来改变 MySQL 的自动提交模式,记得改回来

     

     事务常见操作方式

    创建测试表

    证明事务的开始和回滚

     

     

    事务隔离级别

    数据库中,为了保证事务执行过程中不受干扰,就有了隔离性。

    数据库中,允许事务受不同程度的干扰,就有了隔离级别。

    隔离级别

    • 读未提交【Read Uncommitted】: 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。
    • 读提交【Read Committed】 :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。
    • 可重复读【Repeatable Read】: 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。
    • 串行化【Serializable】: 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决了幻读的问题。

    隔离基本是通过锁来实现的。

    查看全局隔离级别

     查看当前会话全局隔离级别

     设置当前会话or全局隔离级别语法

    SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED |REPEATABLE READ | SERIALIZABLE}

    把当前会话隔离级别设置为串行化

    我们再来看会话隔离级别就发生了变化

     

    读未提交

     开启事务

    再开一终端B,通过B访问

     一个事务在执行中,读到另一个执行中事务的更新(或其他操作)但是未commit的数据,这种现象叫做脏读(dirty read)。

    读提交

    可重复读

    串行化

    隔离级别对比

    展开全文
  • 数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。 二、事务的四大属性 分别是原子性、一致性、隔离性、持久性。 1、原子性(Atomicity) 原子性是指事务包含...
  • Mysql事务处理详解

    2020-12-15 23:38:24
    一、Mysql事务概念  MySQL 事务主要用于处理操作量大,复杂度高的数据。由一步或几步数据库操作序列组成逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。在 MySQL 中只有使用了 Innodb 数据库引擎的...
  • javaweb 实现企业日常事务管理系统,了解javaweb编程初步以及需要注意的地方。
  • 1,MySQL事务支持 1)MySQL事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关: Sql代码 代码如下: MyISAM:不支持事务,用于只读程序提高性能 InnoDB:支持ACID事务、行级锁、并发 Berkeley DB:支持...
  • 一、Spring事务管理之几种方式实现事务  二、SpringBoot事务管理  三、Redis的事务功能详解 (一)相关命令 1. MULTI 2. EXEC 3. DISCARD 4. WATCH 5. UNWATCH (二)使用方法 (三)事务内部的错误 ...

    目录

    一、Spring事务管理之几种方式实现事务 

    二、SpringBoot事务管理

     三、Redis的事务功能详解

    (一)相关命令

    1. MULTI

    2. EXEC

    3. DISCARD

    4. WATCH

    5. UNWATCH

    (二)使用方法

    (三)事务内部的错误

    (四)为什么Redis不支持回滚?

    (五)丢弃命令队列

    (六)通过CAS操作实现乐观锁

    (七)WATCH命令详解

    (八)Redis脚本和事务

    四、Mysql事务处理详解

    (一)Mysql事务概念

    (二)读取数据概念

    (三)事务隔离级别


    一、Spring事务管理之几种方式实现事务

    1、事务认识


    大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销。Spring事务管理基于底层数据库本身的事务处理机制。数据库事务的基础,是掌握Spring事务管理的基础。这篇总结下Spring事务。
    事务具备ACID四种特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写。
    (1)原子性(Atomicity)
    事务最基本的操作单元,要么全部成功,要么全部失败,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
    (2)一致性(Consistency)
    事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。
    (3)隔离性(Isolation)
    指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
    (4)持久性(Durability)
    指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。


    2、事务的传播特性


    事务传播行为就是多个事务方法调用时,如何定义方法间事务的传播。Spring定义了7中传播行为:
    (1)propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是Spring默认的选择。
    (2)propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
    (3)propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
    (4)propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
    (5)propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    (6)propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
    (7)propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作。


    3、事务的隔离级别


    (1)read uncommited:是最低的事务隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
    (2)read commited:保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。
    (3)repeatable read:这种事务隔离级别可以防止脏读,不可重复读。但是可能会出现幻象读。它除了保证一个事务不能被另外一个事务读取未提交的数据之外还避免了以下情况产生(不可重复读)。
    (4)serializable:这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读之外,还避免了幻象读
    (5)脏读、不可重复读、幻象读概念说明:
    a.脏读:指当一个事务正字访问数据,并且对数据进行了修改,而这种数据还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。
    b.不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事物内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。
    c.幻象读:一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读(两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中)


    4、事务几种实现方式


    (1)编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
    (2)基于 TransactionProxyFactoryBean的声明式事务管理
    (3)基于 @Transactional 的声明式事务管理
    (4)基于Aspectj AOP配置事务


    5、举例说明事务不同实现


    编程式事务基本已经OUT了,在上上家公司的老工程还能找到,所有就省略了,主要回顾 下声明式事务。
    以用户购买股票为例
    新建用户对象、股票对象、以及dao、service层
    --------------------- 
    作者:WilliamDream  
    原文:https://blog.csdn.net/chinacr07/article/details/78817449

     

    spring事务回滚规则

    指示spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。

    默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。
    可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也可以明确定义那些异常抛出时不回滚事务。

    还可以编程性的通过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的唯一操作就是回滚。

    @Transactional注解

    @Transactional属性

     
    属性类型描述
    valueString可选的限定描述符,指定使用的事务管理器
    propagationenum: Propagation可选的事务传播行为设置
    isolationenum: Isolation可选的事务隔离级别设置
    readOnlyboolean读写或只读事务,默认读写
    timeoutint (in seconds granularity)事务超时时间设置
    rollbackForClass对象数组,必须继承自Throwable导致事务回滚的异常类数组
    rollbackForClassName类名数组,必须继承自Throwable导致事务回滚的异常类名字数组
    noRollbackForClass对象数组,必须继承自Throwable不会导致事务回滚的异常类数组
    noRollbackForClassName类名数组,必须继承自Throwable不会导致事务回滚的异常类名字数组

     

    用法

    @Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。

    虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。

    默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。

     1 @Transactional(readOnly = true)
     2 public class DefaultFooService implements FooService {
     3  
     4   public Foo getFoo(String fooName) {
     5     // do something
     6   }
     7  
     8   // these settings have precedence for this method
     9   //方法上注解属性会覆盖类注解上的相同属性
    10   @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    11   public void updateFoo(Foo foo) {
    12     // do something
    13   }
    14 }

    二、SpringBoot事务管理

    1、需要的注解为@EnableTransactionManagement 和@Transactional 两个,它们来自于下边这个包:

    spring-tx.jar

    该包其实在前边配置mybatis引入依赖时,已自动引入,就是下边这个:

     <!-- Spring Boot Mybatis 依赖 -->
    <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.2.0</version>
    </dependency> 


    所以只要上边的依赖引入进来,那事务就不需要再引入包了, 
    2.首先,找到你的service实现类,加上@Transactional 注解,如果你加在类上,那该类所有的方法都会被事务管理,如果你加在方法上,那仅仅该方法符合具体的事务。当然我们一般都是加在方法上。因为只有增、删、改才会需要事务。 
    比如下边的一个插入数据的方法添加事务:

    @Override
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public Integer add(Cbf_jtcy t) {
        return cbf_jtcyMapper.insert(t);
    } 


    如果不知道里边都是什么东西,可以查看这篇文章,spring,mybatis事务管理配置与@Transactional注解使用

    3.配置完后,spring boot启动类必须要开启事务,而开启事务用的注解就是@EnableTransactionManagement ,如下:

    @SpringBootApplication
    @EnableTransactionManagement 
    @MapperScan("microservice.qssj.mapper")//必须加这个,不加报错,如果不加,也可以在每个mapper上添加@Mapper注释,并且这里还要多填一个注释,那个我忘了,我一直用这个注解
    public class QssjServiceApplication {
        public static void main(String[] args) {
            SpringApplication.run(QssjServiceApplication.class, args);
        }
    } 


    这样就完成了事务的配置。
    --------------------- 
    作者:JAVA码上飘  
    原文:https://blog.csdn.net/wohaqiyi/article/details/72895983  

     

     三、Redis的事务功能详解

    MULTI、EXEC、DISCARD和WATCH命令是Redis事务功能的基础。Redis事务允许在一次单独的步骤中执行一组命令,并且可以保证如下两个重要事项:

    >Redis会将一个事务中的所有命令序列化,然后按顺序执行。Redis不可能在一个Redis事务的执行过程中插入执行另一个客户端发出的请求。这样便能保证Redis将这些命令作为一个单独的隔离操作执行。 > 在一个Redis事务中,Redis要么执行其中的所有命令,要么什么都不执行。因此,Redis事务能够保证原子性。EXEC命令会触发执行事务中的所有命令。因此,当某个客户端正在执行一次事务时,如果它在调用MULTI命令之前就从Redis服务端断开连接,那么就不会执行事务中的任何操作;相反,如果它在调用EXEC命令之后才从Redis服务端断开连接,那么就会执行事务中的所有操作。当Redis使用只增文件(AOF:Append-only File)时,Redis能够确保使用一个单独的write(2)系统调用,这样便能将事务写入磁盘。然而,如果Redis服务器宕机,或者系统管理员以某种方式停止Redis服务进程的运行,那么Redis很有可能只执行了事务中的一部分操作。Redis将会在重新启动时检查上述状态,然后退出运行,并且输出报错信息。使用redis-check-aof工具可以修复上述的只增文件,这个工具将会从上述文件中删除执行不完全的事务,这样Redis服务器才能再次启动。

    从2.2版本开始,除了上述两项保证之外,Redis还能够以乐观锁的形式提供更多的保证,这种形式非常类似于“检查再设置”(CAS:Check And Set)操作。本文稍后会对Redis的乐观锁进行描述。

    (一)相关命令

    1. MULTI

    用于标记事务块的开始。Redis会将后续的命令逐个放入队列中,然后才能使用EXEC命令原子化地执行这个命令序列。

    这个命令的运行格式如下所示:

    MULTI

    这个命令的返回值是一个简单的字符串,总是OK。

    2. EXEC

    在一个事务中执行所有先前放入队列的命令,然后恢复正常的连接状态。

    当使用WATCH命令时,只有当受监控的键没有被修改时,EXEC命令才会执行事务中的命令,这种方式利用了检查再设置(CAS)的机制。

    这个命令的运行格式如下所示:

    EXEC

    这个命令的返回值是一个数组,其中的每个元素分别是原子化事务中的每个命令的返回值。 当使用WATCH命令时,如果事务执行中止,那么EXEC命令就会返回一个Null值。

    3. DISCARD

    清除所有先前在一个事务中放入队列的命令,然后恢复正常的连接状态。

    如果使用了WATCH命令,那么DISCARD命令就会将当前连接监控的所有键取消监控。

    这个命令的运行格式如下所示:

    DISCARD
    

    这个命令的返回值是一个简单的字符串,总是OK。

    4. WATCH

    当某个事务需要按条件执行时,就要使用这个命令将给定的键设置为受监控的。

    这个命令的运行格式如下所示:

    WATCH key [key ...]
    

    这个命令的返回值是一个简单的字符串,总是OK。

    对于每个键来说,时间复杂度总是O(1)。

    5. UNWATCH

    清除所有先前为一个事务监控的键。

    如果你调用了EXEC或DISCARD命令,那么就不需要手动调用UNWATCH命令。

    这个命令的运行格式如下所示:

    UNWATCH
    

    这个命令的返回值是一个简单的字符串,总是OK。

    时间复杂度总是O(1)。

    (二)使用方法

    使用MULTI命令便可以进入一个Redis事务。这个命令的返回值总是OK。此时,用户可以发出多个Redis命令。Redis会将这些命令放入队列,而不是执行这些命令。一旦调用EXEC命令,那么Redis就会执行事务中的所有命令。

    相反,调用DISCARD命令将会清除事务队列,然后退出事务。

    以下示例会原子化地递增foo键和bar键的值:

     

    <img>

     

    正如从上面的会话所看到的一样,EXEC命令的返回值是一个数组,其中的每个元素都分别是事务中的每个命令的返回值,返回值的顺序和命令的发出顺序是相同的。

    当一个Redis连接正处于MULTI请求的上下文中时,通过这个连接发出的所有命令的返回值都是QUEUE字符串(从Redis协议的角度来看,返回值是作为状态回复(Status Reply)来发送的)。当调用EXEC命令时,Redis会简单地调度执行事务队列中的命令。

    (三)事务内部的错误

    在一个事务的运行期间,可能会遇到两种类型的命令错误:

    一个命令可能会在被放入队列时失败。因此,事务有可能在调用EXEC命令之前就发生错误。例如,这个命令可能会有语法错误(参数的数量错误、命令名称错误,等等),或者可能会有某些临界条件(例如:如果使用maxmemory指令,为Redis服务器配置内存限制,那么就可能会有内存溢出条件)。 
    在调用EXEC命令之后,事务中的某个命令可能会执行失败。例如,我们对某个键执行了错误类型的操作(例如,对一个字符串(String)类型的键执行列表(List)类型的操作)。

    可以使用Redis客户端检测第一种类型的错误,在调用EXEC命令之前,这些客户端可以检查被放入队列的命令的返回值:如果命令的返回值是QUEUE字符串,那么就表示已经正确地将这个命令放入队列;否则,Redis将返回一个错误。如果将某个命令放入队列时发生错误,那么大多数客户端将会中止事务,并且丢弃这个事务。

    然而,从Redis 2.6.5版本开始,服务器会记住事务积累命令期间发生的错误。然后,Redis会拒绝执行这个事务,在运行EXEC命令之后,便会返回一个错误消息。最后,Redis会自动丢弃这个事务。

    在Redis 2.6.5版本之前,如果发生了上述的错误,那么在客户端调用了EXEC命令之后,Redis还是会运行这个出错的事务,执行已经成功放入事务队列的命令,而不会关心先前发生的错误。从2.6.5版本开始,Redis在遭遇上述错误时,会采用先前描述的新行为,这样便能轻松地混合使用事务和管道。在这种情况下,客户端可以一次性地将整个事务发送至Redis服务器,稍后再一次性地读取所有的返回值。

    相反,在调用EXEC命令之后发生的事务错误,Redis不会进行任何特殊处理:在事务运行期间,即使某个命令运行失败,所有其他的命令也将会继续执行。

    这种行为在协议层面上更加清晰。在以下示例中,当事务正在运行时,有一条命令将会执行失败,即使这条命令的语法是正确的:

     

    <img>

     

    上述示例的EXEC命令的返回值是批量的字符串,包含两个元素,一个是OK代码,另一个是-ERR错误消息。客户端会根据自身的程序库,选择一种合适的方式,将错误信息提供给用户

    需要注意的是,即使某个命令执行失败,事务队列中的所有其他命令仍然会执行 —— Redis不会停止执行事务中的命令。

    再看另一个示例,再次使用telnet通信协议,观察命令的语法错误是如何尽快报告给用户的:

     

    <img>

     

    这一次,由于INCR命令的语法错误,Redis根本就没有将这个命令放入事务队列。

    (四)为什么Redis不支持回滚?

    如果你具备关系型数据库的知识背景,你就会发现一个事实:在事务运行期间,虽然Redis命令可能会执行失败,但是Redis仍然会执行事务中余下的其他命令,而不会执行回滚操作,你可能会觉得这种行为很奇怪。

    然而,这种行为也有其合理之处:

    只有当被调用的Redis命令有语法错误时,这条命令才会执行失败(在将这个命令放入事务队列期间,Redis能够发现此类问题),或者对某个键执行不符合其数据类型的操作:实际上,这就意味着只有程序错误才会导致Redis命令执行失败,这种错误很有可能在程序开发期间发现,一般很少在生产环境发现。 
    Redis已经在系统内部进行功能简化,这样可以确保更快的运行速度,因为Redis不需要事务回滚的能力。

    对于Redis事务的这种行为,有一个普遍的反对观点,那就是程序有可能会有缺陷(bug)。但是,你应当注意到:事务回滚并不能解决任何程序错误。例如,如果某个查询会将一个键的值递增2,而不是1,或者递增错误的键,那么事务回滚机制是没有办法解决这些程序问题的。请注意,没有人能解决程序员自己的错误,这种错误可能会导致Redis命令执行失败。正因为这些程序错误不大可能会进入生产环境,所以我们在开发Redis时选用更加简单和快速的方法,没有实现错误回滚的功能。

    (五)丢弃命令队列

    DISCARD命令可以用来中止事务运行。在这种情况下,不会执行事务中的任何命令,并且会将Redis连接恢复为正常状态。示例如下所示:

     

    <img>

     

    (六)通过CAS操作实现乐观锁

    Redis使用WATCH命令实现事务的“检查再设置”(CAS)行为。

    作为WATCH命令的参数的键会受到Redis的监控,Redis能够检测到它们的变化。在执行EXEC命令之前,如果Redis检测到至少有一个键被修改了,那么整个事务便会中止运行,然后EXEC命令会返回一个Null值,提醒用户事务运行失败。

    例如,设想我们需要将某个键的值自动递增1(假设Redis没有INCR命令)。

    首次尝试的伪码可能如下所示:

    val = GET mykey
    val = val + 1
    SET mykey $val
    

    如果我们只有一个Redis客户端在一段指定的时间之内执行上述伪码的操作,那么这段伪码将能够可靠的工作。如果有多个客户端大约在同一时间尝试递增这个键的值,那么将会产生竞争状态。例如,客户端-A和客户端-B都会读取这个键的旧值(例如:10)。这两个客户端都会将这个键的值递增至11,最后使用SET命令将这个键的新值设置为11。因此,这个键的最终值是11,而不是12。

    现在,我们可以使用WATCH命令完美地解决上述的问题,伪码如下所示:

    WATCH mykey
    val = GET mykey
    val = val + 1
    MULTI
    SET mykey $val
    EXEC
    

    由上述伪码可知,如果存在竞争状态,并且有另一个客户端在我们调用WATCH命令和EXEC命令之间的时间内修改了val变量的结果,那么事务将会运行失败。

    我们只需要重复执行上述伪码的操作,希望此次运行不会再出现竞争状态。这种形式的锁就被称为乐观锁,它是一种非常强大的锁。在许多用例中,多个客户端可能会访问不同的键,因此不太可能发生冲突 —— 也就是说,通常没有必要重复执行上述伪码的操作。

    (七)WATCH命令详解

    那么WATCH命令实际做了些什么呢?这个命令会使得EXEC命令在满足某些条件时才会运行事务:我们要求Redis只有在所有受监控的键都没有被修改时,才会执行事务。(但是,相同的客户端可能会在事务内部修改这些键,此时这个事务不会中止运行。)否则,Redis根本就不会进入事务。(注意,如果你使用WATCH命令监控一个易失性的键,然后在你监控这个键之后,Redis再使这个键过期,那么EXEC命令仍然可以正常工作。)

    WATCH命令可以被调用多次。简单说来,所有的WATCH命令都会在被调用之时立刻对相应的键进行监控,直到EXEC命令被调用之时为止。你可以在单条的WATCH命令之中,使用任意数量的键作为命令参数。

    当调用EXEC命令时,所有的键都会变为未受监控的状态,Redis不会管事务是否被中止。当一个客户单连接被关闭时,所有的键也都会变为未受监控的状态。

    你还可以使用UNWATCH命令(不需要任何参数),这样便能清除所有的受监控键。当我们对某些键施加乐观锁之后,这个命令有时会非常有用。因为,我们可能需要运行一个用来修改这些键的事务,但是在读取这些键的当前内容之后,我们可能不打算继续进行操作,此时便可以使用UNWATCH命令,清除所有受监控的键。在运行UNWATCH命令之后,Redis连接便可以再次自由地用于运行新事务。

    如何使用WATCH命令实现ZPOP操作呢?

    本文将通过一个示例,说明如何使用WATCH命令创建一个新的原子化操作(Redis并不原生支持这个原子化操作),此处会以实现ZPOP操作为例。这个命令会以一种原子化的方式,从一个有序集合中弹出分数最低的元素。以下源码是最简单的实现方式:

    WATCH zset
    element = ZRANGE zset 0 0
    MULTI
    ZREM zset element
    EXEC
    

    如果伪码中的EXEC命令执行失败(例如,返回Null值),那么我们只需要重复运行这个操作即可。

    (八)Redis脚本和事务

    根据定义,Redis脚本也是事务型的。因此,你可以通过Redis事务实现的功能,同样也可以通过Redis脚本来实现,而且通常脚本更简单、更快速。

    由于Redis从2.6版本才开始引入脚本特性,而事务特性是很久以前就已经存在的,所以目前的版本才有两个看起来重复的特性。但是,我们不太可能在短时间内移除对事务特性的支持。因为,即使不用求助于Redis脚本,用户仍然能够规避竞争状态,这从语义上来看是适宜的。还有另一个更重要的原因,Redis事务特性的实现复杂度是最小的。

    但是,在相当长的一段时间之内,我们不大可能看到整个用户群体都只使用Redis脚本。如果发生这种情况,那么我们可能会废弃,甚至最终移除Redis事务。

    原文:https://www.cnblogs.com/kyrin/p/5967620.html

     

    四、Mysql事务处理详解

    (一)Mysql事务概念

     MySQL 事务主要用于处理操作量大,复杂度高的数据。由一步或几步数据库操作序列组成逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。事务用来管理 insert,update,delete 语句。

    (二)读取数据概念

      1.脏读(Dirty Reads):所谓脏读就是对脏数据的读取,而脏数据所指的就是未提交的数据。一个事务正在对一条记录做修改,在这个事务完成并提交之前,这条数据是处于待定状态的(可能提交也可能回滚),这时,第二个事务来读取这条没有提交的数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被称为脏读。

      2.不可重复读(Non-Repeatable Reads):一个事务先后读取同一条记录,但两次读取的数据不同,我们称之为不可重复读。也就是说,这个事务在两次读取之间该数据被其它事务所修改。

      3.幻读(Phantom Reads):一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。

    (三)事务隔离级别

      修改事务隔离级别语法:
      SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}

      1、Read Uncommitted(未授权读取、读未提交):这是最低的隔离等级,允许其他事务看到没有提交的数据。这种等级会导致脏读。如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。避免了更新丢失,却可能出现脏读。也就是说事务B读取到了事务A未提交的数据。SELECT语句以非锁定方式被执行,所以有可能读到脏数据,隔离级别最低。

    ?

    1

    2

    3

    4

    5

    SET session transaction isolation level read uncommitted ;

    SET global transaction isolation level read uncommitted;/*全局建议不用*/

    SELECT @@global.tx_isolation;

    SELECT @@session.tx_isolation;

    SELECT @@tx_isolation;

      新建一个简单的student表,设置id和name,num字段,开启事务1对表新增通过存储过程,事务不提交,查看当前数据库事务状态,可以看到一条数据事务,事务级别为READ UNCOMMITTED:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    drop table if exists student;

    create table student(

    id int primary key auto_increment comment 'id',

    name varchar(100) comment '名称',

    num int

    );

    drop procedure if exists proc_on_sw;

    delimiter ;;

    create procedure proc_on_sw()

    begin

    start transaction;

    insert into student(name,num) value('aaa',1);

    select * from information_schema.INNODB_TRX;

    end

    ;;

    delimiter ;;

    call proc_on_sw();

      新建事务2,查询student表,我们在READ UNCOMMITTED级别下,可以看到其他事务未提交的数据:再去查看数据库事务状态,我们会看到状态正常。

    1

    2

    3

    4

    start transaction ;

    select * from student;

    commit;

    select * from information_schema.INNODB_TRX;

      2.Read Committed(授权读取、读提交):读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。该隔离级别避免了脏读,但是却可能出现不可重复读。事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    SET session transaction isolation level read committed ;

    SET global transaction isolation level read committed; /*全局建议不用*/

     

    drop procedure if exists proc_on_up;

    delimiter ;;

    create procedure proc_on_up()

    begin

    set autocommit=0;

    update student set name='cc' where id=1;

    commit;

    set autocommit=1;

    end

    ;;

    delimiter ;;

    call proc_on_up();

    select * from student;


      3.repeatable read(可重复读取):就是在开始读取数据(事务开启)时,不再允许修改操作,事务开启,不允许其他事务的UPDATE修改操作,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。避免了不可重复读取和脏读,但是有时可能出现幻读。这可以通过“共享读锁”和“排他写锁”实现。

    set session transaction isolation level repeatable read;

      4.串行化、序列化:提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。

    set session transaction isolation level serializable;

          隔离等级   脏读   不可重复读   幻读
          读未提交   YES   YES      YES
          读已提交   NO    YES         YES
          可重复读   NO    NO        YES
          串行化       NO    NO        NO

    五、完整例子包括提交和回滚完整例子

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    drop procedure if exists pro_new;

    delimiter;;

    create procedure pro_new(out rtn int)

    begin

    declare err INT default 0;

    -- 如果出现异常,会自动处理并rollback

    declare exit handler for sqlexception ROLLBACK ;

    -- 启动事务

    set autocommit=0;

    start transaction;

    insert into student(name,num) values(NULL,2.3);

    -- set err = @@IDENTITY; -- =  获取上一次插入的自增ID;

    set err =last_insert_id(); -- 获取上一次插入的自增ID

    insert into student(name,num) VALUEs('ccc',err);

    -- 运行没有异常,提交事务

    commit;

    -- 设置返回值为1

    set rtn=1;

    set autocommit=1;

    end

    ;;

    delimiter ;;

    set @n=1;

    call pro_new(@n);

    select @n;

    原文:https://www.jb51.net/article/121153.htm

     

    展开全文
  • 事务用来管理 insert,update,delete 语句。 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。 1、查看事务状态select @@autocommit ;查看事务是否开启自动,默认是自动开启的 2、set autocommit=0...
  • MySQL事务管理及存储引擎

    千次阅读 2020-09-11 22:39:04
    MySQL事务管理MySQL事务概念事务的ACID特点事务控制语句MySQL数据库存储引擎概述关于MyISAM存储引擎MyISAM概述MyISAM的适用场景InnoDB存储引擎InnoDB的概述InnoDB的适用场景企业选择存储引擎的依据相关操作查看引擎...
  • mysql事务? 系统中到底谁的事务是在保证数据的一致性,两个事务有什么关系? spring事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的; Spring...
  • MySQL——事务(Transaction)详解

    万次阅读 多人点赞 2018-03-23 13:05:50
    该博客详解MySQL中的事务 一、事务定义 Transaction 事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元) 一个完整的业务需要批量的DML...
  • Mysql事务及索引

    2018-12-15 13:21:04
    一、数据库索引概述; 二、数据库索引分类; 三、Mysql数据库管理索引; 四、数据库事务概述; 五、数据库事务特性; 六、Mysqk数据库管理事务
  • mysql 事务原理详解

    千次阅读 多人点赞 2022-07-23 09:14:40
    mysql 事务原理详解
  • 0.1)本文部分文字描述转自“MySQL 必知必会”,旨在review“MySQL事务管理+安全管理+MySQL数据类型” 的基础知识; 【1】管理事务处理 【1.1】事务处理 1)并非所有引擎都支持事务管理,MyISAM 不支持,而...
  • spring的@transactional与mysql事务管理

    千次阅读 2017-02-08 11:41:48
    在使用@transactional注解时,需要数据库引擎要支持事务
  • mysql事务mysql事务回滚;MySQL事务死锁;如何解除死锁;资金出入账:最近使用golang做资金账户,目前涉及到这两个问题:资金入账时,可能存在提现【出账】; 资金提现时,可能存在资金入账。因而,为了保证资金的...
  • mysql数据库开机报错: InnoDB: The log sequence number in ibdata files does not match InnoDB: the log sequence number in the ib_logfiles! 100224 12:24:20 InnoDB: Database was not shut down normally! ...
  • QT 5.5之后的Mysql事务处理

    千次阅读 2017-09-07 15:32:47
    QSqlQuery query query.exec(“START TRANSACTION”) query.exec(“COMMIT”); query.exec(“ROLLBACK”); 此方法可以为插入数据库节省大量的时间,提高代码的运行效率!
  • MySQL事务问题

    千次阅读 多人点赞 2022-03-19 08:18:27
    事务MySQL事务及其特征事务的概念事务的特性事务的演示事务的细节说明事务的并发问题脏读(Dirty read)不可重复读幻读事务的隔离级别1.详细介绍+演示2.设置隔离级别3.隔离级别的作用范围4、查看隔离级别 MySQL事务...
  • MySQL事务实现原理详解

    千次阅读 2022-04-03 18:19:51
    MySQL事务的实现原理
  • 就在昨天有个关于支付宝转账的业务不得不使用MySQL事务来完成,别人说了很多,还是不明白MySQL事务到底是个啥,于是就开始了新一轮的补课,出来混,欠下的知识账总是要还的。 先简单说一下我昨天遇到的那个业务,我...
  • 本文实例讲述了Mysql数据库高级用法之视图、事务、索引、自连接、用户管理。分享给大家供大家参考,具体如下: 视图 视图是对若干张基本表的引用,一张虚表,只查询语句执行结果的字段类型和约束,不存储具体的数据...
  • JDBC使用MySQL处理大数据+事务控制管理.txt
  • MySQL事务原理

    千次阅读 2022-03-26 20:36:02
    实际上,我们研究事务的原理,就是研究MySQL的InnoDB引擎是如何保证事务的四大特性的。 而对于这四大特性,实际上分为两个部分。 其中的原子性、一致性、持久化,实际上是由InnoDB中的两份日志来保证的,一份是...
  • mysql事务(详解)

    千次阅读 2022-06-12 16:25:31
    1、事务定义 - 事务事务是一个最小的不可在分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务是一个最小的工作单元) 2、事务有四个特性:一致性、持久性、原子性、隔离性...
  • MySQL事务和锁

    千次阅读 2022-05-03 22:13:04
    MySQL事务和锁:事务四大特性、事务并发的三个问题,InnoDB锁

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 246,585
精华内容 98,634
关键字:

mysql事务管理

mysql 订阅