• Mysq事务


    1. 概述

    数据库一般都会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能
    就会导致我们说的脏写、脏读、不可重复读、幻读这些问题。

    为了解决多事务并发问题,数据库设计了事务隔离机制、锁机制、MVCC多版本并发控制隔离机制,用一整套机制来解决多事务并发问题

    2. 事务属性ACID

    • 原子性(Atomicity) :事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行
    • 一致性(Consistent) :事务开始和完成时,数据都必须保持一致状态 (数据的完整性)
    • 隔离性(Isolation) :数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的独立环境执行
    • 持久性(Durable) :事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持

    并发事务处理带来的问题

    • 更新丢失(Lost Update)或脏写
      • 当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题 (最后的更新覆盖了由其他事务所做的更新
    • 脏读(Dirty Reads)
      • ​ 一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致的状态 ;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此作进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象的叫做“脏读”
      • 事务A读取到了事务B已经修改但尚未提交的数据
    • 不可重读(Non-Repeatable Reads)
      • 一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改
        变、或某些记录已经被删除了!
      • 事务A内部的相同查询语句在不同时刻读出的结果不一致,不符合隔离性
    • 幻读(Phantom Reads)
      • 一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数
        据,这种现象就称为“幻读”
      • 事务A读取到了事务B提交的新增数据,不符合隔离性

    3. 事务隔离级别

    数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上“串行化”进行,这显然与“并发”是矛盾的

    常看当前数据库的事务隔离级别: show variables like 'tx_isolation';
    设置事务隔离级别:set tx_isolation='REPEATABLE-READ';
    Mysql默认的事务隔离级别是可重复读,用Spring开发程序时,如果不设置隔离级别默认用Mysql设置的隔离级别,如果Spring设置了就用已经设置的隔离级别

    4. 锁

    锁是计算机协调多个进程或线程并发访问某一资源的机制。

    锁分类

    • 从性能上分为乐观锁(用版本对比来实现)和悲观锁
    • 从性能上分为乐观锁(用版本对比来实现)和悲观锁
      • 读锁(共享锁,S锁(Shared)):针对同一份数据,多个读操作可以同时进行而不会互相影响
      • 读锁(共享锁,S锁(Shared)):针对同一份数据,多个读操作可以同时进行而不会互相影响
    • 从对数据操作的粒度分,分为表锁和行锁
      • 表锁
        • 每次操作锁住整张表。开销小,加锁快;不会出现死锁
        • 锁定粒度大,发生锁冲突的概率最高 ,并发度最低
        • 一般用在整表数据迁移的场景
        • 手动增加表锁 :lock table 表名称 read(write),表名称2 read(write);
        • 查看表上加过的锁 :show open tables;
        • 删除表锁 :unlock tables;
      • 行锁:
        • 开销大,加锁慢
        • 会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高
        • InnoDB与MYISAM的最大不同有两点:
          InnoDB支持事务(TRANSACTION)
          InnoDB支持行级锁
    • 间隙锁
      • 间隙锁,锁的就是两个值之间的空隙
      • 间隙锁是在可重复读隔离级别下才会生
    • 临键锁
      • 行锁与间隙锁的组合

    注意

    ​ 锁主要是加在索引上,如果对非索引字段更新,行锁可能会变表锁

    5.案例分析

    读未提交(读到未提交的数据)

    set tx_isolation='read-uncommitted';

    读已提交
    set tx_isolation='read-committed';

    可重复读

    set tx_isolation='repeatable-read';

    可串行化

    set tx_isolation='repeatable-read';

    **行锁分析 **

    show status like 'innodb_row_lock%';

    Innodb_row_lock_current_waits: 当前正在等待锁定的数量
    Innodb_row_lock_time: 从系统启动到现在锁定总时间长度
    Innodb_row_lock_time_avg: 每次等待所花平均时间
    Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花时间
    Innodb_row_lock_waits:系统启动后到现在总共等待的次数

    查看INFORMATION_SCHEMA系统库锁相关数据表

    ‐‐ 查看事务
    select * from INFORMATION_SCHEMA.INNODB_TRX;
    ‐‐ 查看锁
    select * from INFORMATION_SCHEMA.INNODB_LOCKS;
    ‐‐ 查看锁等待
    select * from INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
    ‐‐ 释放锁,trx_mysql_thread_id可以从INNODB_TRX表里查看到
    kill trx_mysql_thread_id
    ‐‐ 查看锁等待详细信息
    show engine innodb status\G;
    

    锁优化建议
    尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
    合理设计索引,尽量缩小锁的范围
    尽可能减少检索条件范围,避免间隙锁
    尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行
    尽可能低级别事务隔离

  • 相关阅读:
    如何选择机器学习算法 转
    机器学习经典算法详解及Python实现--基于SMO的SVM分类器
    机器学习(Machine Learning)&深度学习(Deep Learning)资料
    计算智能在设备状态维护中的应用
    LaTeX 在编译时出现 File ended while scanning use of @writefile错误
    LaTeX 中插入图片使其紧跟插入的文字之后
    LaTeX 制作表格
    LaTeX 中换段落
    LaTeX 中使用三级标题
    使用 WinEdt 来写中文文章or 建模论文
  • 原文地址:https://www.cnblogs.com/steven158/p/15526541.html
Copyright © 2020-2023  润新知