mysql锁部分

用锁机制区分:

排他锁,共享锁

用粒度区分:

record lock(行锁)
next-key lock(间隙锁–页面锁)
table lock(表锁)

MyISAM 主要采用表锁:

加锁快,不死锁.(因为表锁始终一次获得 SQL 语句所需要的全部锁),但表锁也不适合大量查询和修改

InnoDB锁模式:

InnoDB 实现了以下两种类型的行锁:

共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。
为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB 还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁:

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

InnoDB 行锁实现方式:

InnoDB 行锁是通过给索引上的索引项加锁来实现的,这一点 MySQL 与 Oracle 不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB 这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB 才使用行级锁,否则,InnoDB 将使用表锁!
不论是使用主键索引、唯一索引或普通索引,InnoDB 都会使用行锁来对数据加锁。
只有执行计划真正使用了索引,才能使用行锁:即便在条件中使用了索引字段,但是否使用索引来检索数据是由 MySQL 通过判断不同执行计划的代价来决定的,如果 MySQL 认为全表扫描效率更高,比如对一些很小的表,它就不会使用索引,这种情况下 InnoDB 将使用表锁,而不是行锁。因此,在分析锁冲突时,
别忘了检查 SQL 的执行计划(可以通过 explain 检查 SQL 的执行计划),以确认是否真正使用了索引。(更多阅读:MySQL索引总结)
由于 MySQL 的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然多个session是访问不同行的记录, 但是如果是使用相同的索引键, 是会出现锁冲突的(后使用这些索引的session需要等待先使用索引的session释放锁后,才能获取锁)。 应用设计的时候要注意这一点。

InnoDB的间隙锁:

当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时(例如insert into XXX select …),InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next-Key锁)。

很显然,在使用范围条件检索并锁定记录时,InnoDB这种加锁机制会阻塞符合条件范围内键值的并发插入,这往往会造成严重的锁等待。因此,在实际应用开发中,尤其是并发插入比较多的应用,我们要尽量优化业务逻辑,尽量使用相等条件来访问更新数据,避免使用范围条件。

InnoDB在Read Committed和Repeatable Read下的MVCC

问题:
1、脏读:事务A读到bai了事务B未提交的数据。
2、不可重复读:事务A第一次查询得到一行记录row1,事务B提交修改后,事务A第二次查询得到row1,但列内容发生了变化。

3、幻读:事务A第一次查询得到一行记录row1,事务B提交修改后,事务A第二次查询得到两行记录row1和row2。

Read Committed因为只能读取已经提交的数据,所以可以避免脏读,但是不保证事务重新读的时候能读到相同的数据,因为在每次数据读完之后其他事务可以修改刚才读到的数据,所以不能避免不可重复读和幻读现象.

MySQL 中的提交读和可重复读两个隔离级别是使用多版本并发控制 MVCC 来实现的,而不是通过添加读写锁来实现的,如果通过读写锁来实现隔离级别的话,只有读读可以并发,读写,写读,写写都不能并发,这样数据库的并发度太低了,所以一般不通过加读写锁来实现隔离级别。而如果使用 MVCC 来实现 提交读和可重复读两个隔离级别的话则可以在读的时候不加锁,读写和写读可以同时进行,只有写写需要阻塞,这样就极大地提高了并发度。

MVCC 机制会记录每行数据的历史版本,通过可见性算法、undo 日志以及 read view 控制每个读操作所读取的行数据历史版本,

Repeatable Read 在事务发生第一次读的时候选定所要读取的数据行的版本,整个事务都读取这一个版本的数据行,所以可以重复读,每次读取的数据都一致。

Read Committed 在事务中每次读操作都是读取最新的行数据版本,而这最新的数据行版本很可能是某个事务进行了修改操作后提交的,所以可能会发生多次读取同一行数据,但是前后读取的数据不一致的情况。这就是不可重复读现象,所以提交读不能避免不可重复度现象。

参考文档:
https://zhuanlan.zhihu.com/p/29150809/
https://www.cnblogs.com/hi3254014978/p/12721152.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值