• InnoDB支持事务,MyISAM不支持事务
  • 长事务查询:information_schema库的innodb_trx表
  • update:当前读

    事务开启方式

  • 显示启动事务语句。begin或start transaction;提交:commit;回滚:rollback

  • begin/start transaction 并不是一个事务的起点,在他们之后的第一个操作innoDB 的语句才会真正启动事务。如果要马上启动事务,可以使用start transaction with consistent snapshot;
  • set autocommit=0.这个命令会关闭这个线程的自动提交;commit、rollback、或者连接断开

    Atomicity-原子性

    Consistency-一致性

    Isolation-隔离性

    问题

  • 脏读

  • 幻读
    • 一个事务(同一个read view)在前后两次查询同一范围的时候,后一次查询看到了前一次查询没有看到的行
  • 不可重复读

    隔离级别

  • 读未提交(read uncommitted)

  • 读已提交(read committed)
  • 可重复读(repeatable read)
  • 串行化(serializable)
  • 查看当前的隔离级别:show variables like ‘transaction_isolation’

    实现原理—MVCC(多版本并发控制)

  • 在MySQL的InnoDB引擎的就是指在read committed(读已提交)、repeatable read(可重复读)两种隔离级别下的事务,对select操作会访问版本链(即ReadView)中的记录的过程

  • 提升并发性能
  • 原理

    • InnoDB数据表字段:
      • DB_TRX_ID:最后一次修改本行记录的事务id,6个字节大小
      • DB_ROLL_PRT:回滚指针
        • 指向改行回滚段的指针
        • 通过这个指针找到之前的版本
        • 所有旧版本,在undo log中通过链表形式组织
      • DB_ROW_ID
    • ReadView
      • 根据可见性算法做可见性判断
      • 存储当前活跃的事务
      • RR:第一次创建后,之后使用同一个read view
      • RC:每次调用快照读都会创建一个新的read view
    • undo log:image.png
      • 当有修改记录时候,会把旧版本写入到undo log链表中,保存roll_point指针,指向上一个版本

        示例

  • 一致性读、当前读

    1. mysql> CREATE TABLE `t` (
    2. `id` int(11) NOT NULL,
    3. `k` int(11) DEFAULT NULL,
    4. PRIMARY KEY (`id`)
    5. ) ENGINE=InnoDB;
    6. insert into t(id, k) values(1,1),(2,2);

    | 事务A | 事务B | 事务C | | —- | —- | —- | | start transaction with
    consistent snapshot; | | | | | start transaction with
    consistent snapshot; | | | | | update t set k=k+1 where id =1; | | | update t set k=k+1 where id =1;
    select k from t where id=1; | | | select k from t where id=1;
    commit; | | | | | commit; | |

    • 事务B查询到的k=3,事务A查询到的k=1
    • begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个操作InnoDB表 的语句,事务才真正启动
    • start transaction with consistent snapshot ;可以马上启动一个事务
    • 事务在启动的时候会基于整个库“拍下快照”,即read view
      • 事务开始时候,InnoDB会给事务分配一个transaction id(按照申请顺序递增)
      • 一行记录会有多个版本,每个版本有一个row_trx_id保存创建该版本的事务id
      • InnoDB为每个事务构造了一个数组,保存启动时候,当前活跃的事务transaction id
      • image.png
        • 对于repeatable read隔离级别
          • 绿色部分,是已提交的可以读
          • 红色的是未提交的不可读
          • 若某行数据的row_trx_id在换色范围内,在数组中,则表示事务未提交,不可见,否则可见
      • 一致性读:根据上述规则,读取数据,即使之后数据被修改,此事务读取到的都是一致的
      • 当前读:update都是先读后写,这个读,只能读取最新的数据
        • select若要当前读,加上lock in share mode 或 for update

          Durability-持久性

          事务启动方式

  • 显式启动事务语句, begin 或 start transaction。配套的提交语句是commit,回滚语句是 rollback。

  • set autocommit=0,这个命令会将这个线程的自动提交关掉
    • 意味着如果你只执行一个 select语句,这个事务就启动了,而且并不会自动提交
    • 这个事务持续存在直到你主动执行 commit 或 rollback 语句,或者断开连接
  • 查询超过60秒的事务
    • select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60
  • 杀掉连接:Percona的pt-kill这个工具