MySQL锁

Posted by Liao on 2020-05-14

隔离性的底层实现

其中事务的隔离性底层实现的原理是

锁的分类

按照数据操作的类型划分
  • 读锁(共享锁):同一份数据,多个读操作可以同时进行,互不影响
  • 写锁(排它锁):当前写操作还没完成,会阻断其他写锁和读锁

session1 加了读锁,当前session1不能读其他未加锁的表,而且不能插入或更新锁定的表。session2可以读或操作未加锁的表,但如果对加读锁的表进行操作,会一直等待获得锁(阻塞),直到上读锁的表释放锁之后,session2获得锁,操作完成。

按照数据操作的粒度划分
  • 行锁(偏写)

    • 锁定粒度最小,发生冲突率低,并发度也最高

    • 偏向InnoDB存储引擎

    • 锁定一行:在session1select * from table where a = 8 for update,此时锁定后只有session1自己可以继续,其他线程来操作数据会阻塞,直到session1 commit事务

    • 分析系统中行锁争夺情况show status like 'innodb_row_lock%',其中有三个重要状态变量:innodb_row_lock_time_avg平均等待时长/innodb_row_lock_waits等待总次数/innodb_row_lock_time等待总时长

  • 表锁(偏读)

    • 读锁会阻塞写,但不会阻塞读。而写锁会把读和写都阻塞,MyISAM以读为主,故不能作为频繁更新操作,会导致阻塞。

锁的种类

  • 乐观锁:每次取数据的时候都认为别人不会修改数据,所以不会上锁。但在更新时会判断别人有没有更新(版本号机制)
    • 策略:通常在数据表最后加一个字段version。当A,B同时修改一条数据的不同字段(电话号码,微信号),(A比B快修改完提交)修改当A修改完一个事务,版本号+1,然后提交事务。接着B修改完提交的时候,B的版本号还是原来的1,但现在已经变成2了,B提交事务后立即报异常。得去数据库获取最新版本号,才能进行修改,+1后再提交。
    • 用于多读类型,提高吞吐量
  • 悲观锁:每次取数据的时候都会认为别人修改了数据,所以每次拿数据都会上锁。别人想拿到这个数据就会阻塞,直到拿到锁。
    • 共享锁S(行锁)
    • 排它锁X(行锁)
    • 意向共享锁IS(表锁)
    • 意向排它锁IX(表锁)
  • 自增锁
  • 间隙锁:当sql语句中用范围条件而不是相等条件检索数据,并请求共享或排它锁时,InnoDB会给符合条件的已有数据记录的索引项上锁。对于键值在条件范围内,但不存在的记录,成为“间隙”。InnoDB会给这个间隙上锁,称为“间隙锁”(Next-Key锁)