myisam为什么比innodb查询快_那些还不会MySQL锁的程序员们,求你快看看这篇文章吧...

MySQL锁概述

锁是数据库系统区分与文件系统的一个关键特性。锁机制用于管理对共享资源的并发访问。

MySQL锁级别

9af2b7e3247f15c3efdcee96f8230870.png

MyISAM 表锁

表锁介绍

表锁是MySql中最基本的锁策略,并且是开销最小的策略,表锁将整张表加锁。

表锁模式:表共享读锁和表独占写锁

表锁兼容性

66f301529e6fb7327ed1ae83c3f594b9.png

1. 当一个进程获得了表的读锁,不会阻塞其他进程对同一表的读请求,但会阻塞其他进程对表的写请求。

12146ccf6f02e604c32797e072051060.png


2. 当一个进程获取表的写锁,会阻塞其他进程获得表的读请求和写请求。

70255c9359095f6e9e307de576216cc3.png

MyISAM并发插入

在一定条件下,MyISAM表页支持查询和插入的并发操作。MyISAM存储引擎有一个系统变量concurrent_insert,用以控制其并发插入的行为,取值0、1或2。

  • 当concurrent_insert = 0时,不允许并发插入;
  • 当concurrent_insert = 1时,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。这也是MySQL的默认设置。
  • 当concurrent_insert = 2时,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录。

MyISAM锁调度

mysql认为写请求一般比读请求重要。当一个进程请求表的读锁,同时另一个进程请求同一个表的写锁,写进程将优先获得锁。即使是读请求先到锁等待队列,写请求后到,写锁也会优先获取锁。这也正是MyISAM表不太适合有大量更新操作和查询操作的应用的原因,大量的更新操作会造成查询操作很难获得锁。

可以通过以下方式调节MyISAM锁调度行为

  • 通过指定启动参数low-priority-updates,使MyISAM引擎默认给予读请求以优先的权利。
  • 通过执行命令SET LOW_PRIORITY_UPDATES=1,使该连接发出的更新请求优先级降低。
  • 通过指定INSERT、UPDATE、DELETE语句的LOW_PRIORITY属性,降低该语句的优先级。
  • MySQL也提供了一种折中的办法来调节读写冲突,即给系统参数max_write_lock_count设置一个合适的值,当一个表的读锁达到这个值后,MySQL就暂时将写请求的优先级降低,给读进程一定获得锁的机会。

MyISAM优化建议

缩短锁定时间、分离并行的操作、合理利用读写优先级、读写分离

InnoDB 行锁

锁的类型

InnoDB实现了一下两种标准的行级锁:

  • 共享锁(S):锁粒度是行或者元组(多行)。一个事务获得了共享锁之后,就可以对锁定范围内的数据进行读操作。
  • 排他锁(X):锁粒度是行或者元组(多行)。一个事务获得排他锁之后,就可以对锁定范围内的数据执行insert/delete/update操作。

另外,为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),
这两种意向锁都是表锁。

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

InnoDB锁的兼容性

53290fa022a18a2bc4f23100bf90b38a.png

行锁的算法

  • 单个行记录上的锁(Record Lock):单个单索引记录上的锁。
  • 间隙锁(Gap Lock):锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况。
  • 锁定一个范围,并且锁定记录本身 (Next-Key Lock = Gap Lock + Record Lock):
    Next-Key Lock结合了Gap Lock + Record Lock的一种锁定算法。锁定一个范围,并且锁定记录本身。在MySQL默认的事务隔离级别(REPEATABLE READ)下,InnoDB通过这种机制来防止出现幻读的情况。

死锁

死锁是指两个或两个以上的事务在执行的过程中,因争夺锁资源而造成相互等待的现象。若无外力的作用,事务将无法推进下去。死锁出现的概率是非常低的。

解决死锁问题最简单的一种方式是超时,即当两个事务相互等待时,当一个等待时间超过某个值时,其中一个事务进行回滚,另一个等待事务就能继续进行。InnoDB可通过参数innodb_lock_wait_timeout来设置超时的时间。

除了超时机制,当前数据库较多采用wait-for graph(等待图)方式来进行死锁检测,这是一种更为主动的检测方式。
innodb内置有死锁检查机制。当出现死锁时会自动回滚占用undo资源少的事务。死锁的检测除了超时还有wait-for graph,如果图中出现环形回路则表明存在死锁。wait-for graph要求数据库保存锁的信息链表和事务等待链表表两种信息,通过链表可以构造一张图,而在这个图中若存在回路就代表存在死锁,因此资源间相互发生等待。每个事务在请求锁并发生等待是都会判断是否存在回路,若存在则有死锁,通常InnoDB会选择回滚undo量最小的事务。

最后

感谢大家看到最后,如文章有不足,欢迎大家在评论区支持,给予意见。如果觉得我的文章对你有帮助,那就给我一个赞同吧。

每天都会分享java相关技术文章或行业资讯。欢迎大家关注和转发文章。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值