• MySQL学习(四)锁机制


    • 分类
      • 读锁(共享锁):对同一个数据,多个读操作可以同时进行,互不干扰
      • 写锁(互斥锁):如果当前写操作没有完毕,则无法进行其他的读操作、写操作
    • 操作范围
      • 表锁:一次性对一张表整体加锁。如myisam存储使用引擎,开销小,加锁快,无死锁;锁的范围大,容易发生锁冲突,并发低
      • 行锁:一次性对一条数据加锁。如innodb使用行锁,开销大,加锁满,容易死锁;锁的范围小,不易发生锁冲突,并发度高(很小概率,发生高并发问题、不可重复读,丢失更新等问题)
        • 间隙锁(next-key):值在范围内,但却不存在

    此时表中没有id=7的数据
    update linelock set name = 'x' wher id > 1 and id < 9;

    加锁 lock table 表1 read/write,表2 read/write
    查看加锁的表: show open tables;

    1.加读锁

    结论1:一个会话,对A表加了read锁,则该会话可以对A表进行读操作,不能进行写操作;且该会话不能对其他表进行读、写操作。(即如果给A表加了读锁,则当前会话只能对A表进行读操作)

    结论2:会话0对A表加了锁,其他会话的操作:

    • 可以对其他表(A表以外的表)进行读、写操作
    • 对A表可以读,写-需要等待释放锁 unlocal tables;

    2.加写锁

    会话0: lock table tablename write;
    总结1:当前会话可以对加了写锁的表,可以进行任何操作(增删改查);但是不能操作(增删改查)其他表.
    总结2:对会话0加写锁的表,可以进行增删改查的前提是:等会话0释放写锁。

    3.行锁分析

    1. 如果会话x对某条数据a进行DML操作(研究时,关闭了自动commit的情况下),则其他会话必须等待会话x结束事务(commit/rollback)后,才能对数据a进行DML操作
    2. 表锁是通过 unlock tables; ,也可以通过事务解锁,行锁是通过事务解锁。
    3. 如果没有索引/索引失效,则行锁会转为表锁
    4. 行锁:如果有where,则实际加锁的范围就是where后面的范围(不是实际的值 )
      show status like '%innodb_row_lock%';
      image
    • innodb_row_lock_current_waits; 当前正在等待锁的数量
    • innodb_row_lock_time; 等待总时长。从系统启动到现在一共等待的时间
    • innodb_row_lock_time_avg; 平均等待时长

    如果发现锁争用比较严重,如InnoDB_row_lock_waitsInnoDB_row_lock_time_avg的值比较高

    如果仅仅是查询数据,能否加锁?可以 for update:select * from linelock where id = 2 for update;

    4.InnoDB锁问题

    参考博客:https://www.cnblogs.com/jpfss/p/8890250.html
    InnoDB和MyISAM最大不同有两点:一是支持事务;二是采用了行级锁

    • 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
    • 排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。另外,为了允许行锁和表锁共存,实现多粒度锁机制

    InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。

    • 意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
    • 意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
      image

    如果一个事务请求的锁模式与当前的锁兼容,InnoDB就将请求的锁授予该事务;反之,如果两者不兼容,该事务就要等待锁释放。
    意向锁是InnoDB自动加的,不需用户干预。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁;事务可以通过以下语句显示给记录集加共享锁或排他锁。

    • 共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。
    • 排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。

    用SELECT ... IN SHARE MODE获得共享锁,主要用在需要数据依存关系时来确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作。但是如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT... FOR UPDATE方式获得排他锁。

    5.InnoDB行锁实现方式

    :通过索引上的索引项加锁来实现的。这种行锁特定意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁。

  • 相关阅读:
    log4net封装类
    (转)MySQL InnoDB 架构
    备份宽带不足,innobackupex备份导致从库不可写
    从库查询阻塞xtrabackup备份,应该是kill备份还是kill查询的问题
    rabbitmq群集安装
    MySQL索引选择问题(要相信MySQL自己选择索引的能力)
    binlog_format产生的延迟问题
    命令行登录mysql报Segmentation fault故障解决
    MySQL5.7.21启动异常的修复
    大查询对mha切换的影响
  • 原文地址:https://www.cnblogs.com/lhxBlogs/p/15660224.html
Copyright © 2020-2023  润新知