1. 什么是事务

事务是一个序列操作,其中的操作要么都执行,要么都不执行

2. 事务的特性

  • atomicity(原子性):原子性是指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生。
  • consistency(一致性):一致性是指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏
  • isolation(隔离性):多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果
  • durability(持续性):事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚
  • 3. 看看事务是如何工作的

    本地环境模拟,准备两张表:

    CREATE TABLE `user_log` (  
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
      `user_id` int(11) unsigned NOT NULL COMMENT '用户ID',
      `scores` int(11) NOT NULL COMMENT '积分',
      `token` varchar(255) NOT NULL COMMENT '唯一性token',
      `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
      `update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
      `is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除标识',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uniq_token` (`token`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户记录表'
    
    CREATE TABLE `user_account` (  
      `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
      `scores` int(11) NOT NULL COMMENT '积分',
      `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
      `update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
      `is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除标识',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户账户表'
    

    客户端1和客户端2同时打开数据库,开启事务。测试一下几种场景:

  • 步骤1.两个客户端分别写入不同的数据并提交事务
  • 步骤2.客户端1写入A,B两条记录,不提交事务;客户端2写入B记录

    查看进行中的事务:SELECT * FROM information_schema.INNODB_TRX;

    查看锁定等待的请求:select * from INNODB_LOCK_WAITS;

  • 步骤3.客户端1进行rollback操作,看看客户端2的数据情况

    数据记录id发生了什么变化

    客户端2的记录提交成功了么

  • 步骤4.继续在客户端1添加新数据C、D,不提交,查看客户端2的数据情况
  • 步骤5.在客户端2添加新数据E,提交事务,查看客户端1的数据情况
  • 步骤6.在客户端1中添加新数据E,结果是什么
  • 步骤7.在客户端2中查看数据库查询列表,找到客户端1连接的ID,并杀掉客户端1的连接,看看发生什么情况
  • 4. 思考

  • 数据库事务作为一个最小单元,只能全部成功或者全部失败。失败后数据库操作会回滚,但并不意味着毫无痕迹(比如自增主键的ID变化)。

  • 数据库回滚本质上是undo log,把事务过程中的语句对等的保留了undo log,回滚时反向操作把数据恢复原样。但是,如果数据库事务中有其他不能回滚的操作(比如第三方接口调用),那就会发生业务不一致的问题。

  • 数据库的隔离性保证了多个事务在并发执行时不相互影响,但并不是说完全感知不到其他事务的存在(比如主键冲突检查,多个事务有数据可能发生冲突时会有等待的过程INNODB_LOCK_WAITS)。

  • 事务一旦提交后,数据就持久化了,即便再进行回滚也不会影响事务的数据。在开发过程中,要尽量避免commit事件后的逻辑抛异常,否则catch住异常进行回滚就会发生事务不匹配的问题(transaction not match)


  • 参考文档: