MySQL事务学习

四大特性

  1. 原子性

    原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败
    
  2. 一致性

    事务按照预期生效,数据的状态是预期的状态。
    
  3. 隔离性

    事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,  不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
    
  4. 持久性

    持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,  接下来即使数据库发生故障也不应该对其有任何影响。
    

俩个操作

  1. 提交

    将事务执行结果写入数据库
    
  2. 回滚

    回滚所有已执行的语句,返回修改之前的数据
    

锁机制

按照颗粒度划分

  • 行锁
  • 页锁
  • 表锁

按照使用方式划分

  • 共享锁
  • 排它锁

按照思想划分

  • 悲观锁
  • 乐观锁

减少死锁的方式

  • 自动死锁检测,优先回滚小事务
  • 超时参数设置(innodb*lock*wait_timeout
  • 尽量提交事务,小事务不容易产生死锁
  • 加 for update、lock in share mode 读锁时,最好降低事务隔离级别,比如 rc 级别,降低死锁发生概率
  • 事务中涉及多个表,或者涉及多行记录时,每个事务的操作顺序都要保持一致,降低死锁概率,最好用存储过程
  • 通过索引等方式优化 sql 效率,降低死锁概率(目的是减少扫描 / 锁范围,降低概率)

并发读写带来的问题

  1. 脏读(Drity Read)
    某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
    
  2. 不可重复读(Non-repeatable read)
    在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
    
  3. 幻读(Phantom Read)
    在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就有几列数据是未查询出来的,如果此时插入和另外一个事务插入的数据,就会报错。
    

四种隔离级别

  • 读未提交

    在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。读取未提交的数据,也被称之为脏读(Dirty Read)。可能会导致脏读、不可重复读以及幻读。
    
  • 读已提交

    事务A在读取数据时,事务B只能读取数据,不能修改,当事务A读取到数据后,事务B才能修改,这种
    隔离级别可以避免脏读,但依然存在不可重复度以及幻读的问题。
    
  • 可重复度

    这是MySQL的默认事务隔离级别。事务A在没有结束事务时,事务B只能读取数据,不能修改,当事务A结束,事务B才能修改。它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
    
  • 可串行化

    这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
    

Q.E.D.


一个热爱生活的95后精神小伙