MySQL-事务


  • 事务

事务

  • ACID
    • 原子性(Atomicity) :事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行
    • 一致性(Consistent) :在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性
    • 隔离性(Isolation) :数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的,反之亦然
    • 持久性(Durable) :事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持
  • 并发事务处理带来的问题
    • 更新丢失(Lost Update)或脏写:最后的更新覆盖了由其他事务所做的更新
    • 脏读(Dirty Reads):事务A读取到了事务B已经修改但尚未提交的数据
    • 不可重读(Non-Repeatable Reads) :事务A内部的相同查询语句在不同时刻读出的结果不一致,不符合隔离性
    • 幻读(Phantom Reads):事务A读取到了事务B提交的新增数据,不符合隔离性
  • 事务隔离级别:事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上“串行化”进行,这显然与“并发”是矛盾的
    • 不同的应用对读一致性和事务隔离程度的要求也是不同的
    • 当前数据库的事务隔离级别: show variables like 'tx_isolation';
    • 设置事务隔离级别:set tx_isolation='REPEATABLE-READ';
    • Mysql默认的事务隔离级别是可重复读
  • 4 种事务隔离级别
    • 读未提交:set tx_isolation='read-uncommitted';
    • 读已提交:set tx_isolation='read-committed';
    • 可重复读:set tx_isolation='repeatable-read';
      • 使用了MVCC(multi-version concurrency control)机制
        • select操作不会更新版本号,是快照读(历史版本)
        • insert、update和delete会更新版本号,是当前读(当前版本)
      • 使用了间隙锁
    • 串行化:set tx_isolation='serializable';
      • 这种隔离级别并发性极低,开发中很少会用到
      • 读操作会获得共享锁,写操作会获得排他锁
      • 使用了间隙锁


  • 锁分类
    • 乐观锁:version
    • 悲观锁:读锁(共享锁,S锁(Shared))和写锁(排它锁,X锁(eXclusive))
      • 读锁会阻塞写,但是不会阻塞读
      • 写锁则会把读和写都阻塞
    • 从对数据操作的粒度分:表锁和行锁
      • 无索引行锁会升级为表锁:InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁
  • 表锁
    • lock table 表名称 read(write)
    • show open tables; 查看表上加过的锁
    • unlock tables;
  • 行锁:InnoDB支持事务(TRANSACTION)和行级锁
    • MyISAM在执行查询语句SELECT前,会自动给涉及的所有表加读锁,在执行update、insert、delete操作会自 动给涉及的表加写锁
    • InnoDB在执行查询语句SELECT时(非串行隔离级别),不会加锁。但是update、insert、delete操作会加行锁
    • 锁定某一行还可以用 lock in share mode(共享锁) 和 for update(排它锁)
    • 通过检查InnoDB_row_lock状态变量来分析系统上的行锁的争夺情况
      • Innodb_row_lock_time_avg (等待平均时长)
      • Innodb_row_lock_waits (等待总次数)
      • Innodb_row_lock_time(等待总时长)
  • 间隙锁:就是两个值之间的空隙,在某些情况下可以解决幻读问题
    • 这个范围所包含的所有行记录(包括间隙行记录)以及行记录所在的间隙里
    • 临键锁(Next-key Locks):是行锁与间隙锁的组合
  • 查看INFORMATION_SCHEMA系统库锁相关数据表
    • INFORMATION_SCHEMA.INNODB_TRX 查看事务
    • INFORMATION_SCHEMA.INNODB_LOCKS 查看锁
    • INFORMATION_SCHEMA.INNODB_LOCK_WAITS 查看锁等待
    • kill trx_mysql_thread_id 释放锁,trx_mysql_thread_id 可以从 INNODB_TRX 表里查看到
    • show engine innodb status 查看锁等待详细信息
  • 死锁 show engine innodb status
    • 大多数情况mysql可以自动检测死锁并回滚产生死锁的那个事务
  • 锁优化
    • 尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
    • 合理设计索引,尽量缩小锁的范围
    • 尽可能减少检索条件范围,避免间隙锁
    • 尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行
    • 尽可能低级别事务隔离

文章作者: 钱不寒
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 钱不寒 !
  目录