MySql教程

mysql 性能优化(七)锁机制

本文主要是介绍mysql 性能优化(七)锁机制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1、锁介绍

解决因资源共享,而造成的并发问题。
例如:例如:电商A,B两人同时购买最后一件商品
A:仅快0.0001秒抢到的->加锁->处理业务逻辑->释放锁
B:在B获取到商品时,商品已加锁,等待所释放,商品状态已发生改变,已售空。

  • 分类:
    • 操作类型:
      • 读锁(共享锁):对同一个数据,可以同时进行多个读操作,互不干扰
      • 写锁(互斥锁): 如果当前写操作没有完成(未释放锁),则无法进行其他的读操作和写操作
    • 操作范围:
      • 行锁:一次性对一行加锁,如InnoDB存储引擎,开销大,加锁慢,容易出现死锁,锁的范围较小,不容易发生锁冲突,并发度高(很少发生,脏读、幻读、不可重复读、丢失更新)
      • 表锁:一次性对一个表加锁,如MyISAM存储引擎,开销小,加锁快,无死锁,容易生锁冲突,并发度低
      • 页锁(基本不用)

1.1、MyISAM表锁

  • 查看锁

    1代表加了锁
    show open tables;

  • 增加锁

    locak table 表1 read/write ,表2 read/write…可以加多个

  • 释放锁

    unlocak tables;
    也可以通过事物解锁,ROLLBACK / COMMIT

  • 查看表状态

    SHOW STATUS LIKE ‘table%’;

    • Table_locks_immediate:可以获取到的表锁数
    • Table_locks_waited:需要等待的表锁数,值越大说明锁竞争越大
    • Table_open_cache_hits:表缓存命中的次数
    • Table_open_cache_misses:高速缓存大小
    • Table_open_cache_overflows:超过了table_open_cache的设置,则会进行淘汰,淘汰的值记录到Table_open_cache_overflows

一般建议:Table_locks_immediate / Table_locks_waited > 5000采用InnoDb,否则采用MyISAM

1.1.1、加读锁

例如:会话0给A表增加了读锁

  • 当前会话
    • 如果给A表加了读操作,则当前会话只能对A表进行读操作
  • 其他会话
    • 可以对其他表进行读写操作
    • 可以对A表进行读操作,写操作需要等待会话0释放锁后才会执行

1.1.2、加写锁

例如:会话0给A表增加了写锁

  • 当前会话
    • 可以对当前表进行任何操作;
    • 不能操作其他表
  • 其他会话
    • 需要等待会话0释放锁后,才能进行增删改查操作

mysql表级锁的锁模式

MyISAM

  • 执行查询语句(select)前,会自动给涉及的所有表加读锁。
  • 执行更新操作(DML)前,会自动给涉及的表加写锁。

所以对MyISAM表操作会有一下几种情况

  • 对MyISAM表的读操作(加读锁)
    • 不会阻塞其他进程读(会话)对同一个表的读操作
    • 会阻塞对同一个表的写操作,只有读锁释放后才会执行其他会话写操作。
  • 对MyISAM表的写操作(加写锁)
    • 会阻塞其他进程(会话)对同一个表读写操作,写锁释放后才会执行其他会话读写操作。

2.1、行锁(InnoDB)

如果会话X对某条数据a进行DML操作

  • 其他会话需要等待会话A结束事物后,才能对a数据 进行操作
  • 行锁是通过事物来解锁的
  • 行锁一次锁一行数据,操作不同行数据互不干扰

注意

  • 如果没有索引或索引失效,则行锁转为表锁

2.1.1、间隙锁

行锁的一种特殊情况:值在范围内,但却不存在

例如:一个表a中,ID有1、2、3、4、6、7,这些条数据,但是没有id等于5的

update a set name =‘name’ where id >1 and id< 7

在where中没有id等于5的数据,所以 id =5的数据称之为间隙

mysql会自动给间隙加锁 所以示例中会自动给id=5的数据加间隙锁(行锁)

如果有where 则加锁的范围就是where后面的范围,不是实际的值

  • 总结:
    InnoDB默认采用行锁;
    缺点:比表锁性能损耗大
    有点:并发能力强,效率高
    建议:高并发采用InnoDB,否则采用MyISAM
  • 分析

    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:等待锁的总时长,从系统启动到现在一共等待的次数

2.1.2、查询数据加锁

set autocommit=0;

set transaction;

begin;

学习时可以关闭自动提交后进行测试;

查询数据时是否可以加锁?

  • 查询语句后增加for update

select * from tableName where id =1 for update;

这篇关于mysql 性能优化(七)锁机制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!