高性能Mysql(一)

大家好我是孙嵓,从今天起带大家走进高性能Mysql的世界,让你清晰的认识Mysql以及如何最大限度的去优化Mysql,提高我们数据的查询速度,保证我们的业务顺利的进行。

Mysql服务器逻辑架构

图片: https://uploader.shimo.im/f/ARJx4CkGtQfvRIbF.png!thumbnail?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NDg2MTAyMzksImciOiI1cms5ZGxZNDQ3VVA3eXF4IiwiaWF0IjoxNjQ4NjA5OTM5LCJ1c2VySWQiOjY3MjM3Njk0fQ.UbcTsP4x9ETeMAHIHadpDppiqRV275O9-Sa_hUJ4Jxw

图片: https://uploader.shimo.im/f/ELZyp5rfZj2PEfVx.png!thumbnail?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NDg2MTAyMzksImciOiI1cms5ZGxZNDQ3VVA3eXF4IiwiaWF0IjoxNjQ4NjA5OTM5LCJ1c2VySWQiOjY3MjM3Njk0fQ.UbcTsP4x9ETeMAHIHadpDppiqRV275O9-Sa_hUJ4Jxw


读写锁

读锁(read lock)和写锁(write lock)也被称为共享锁(shared lock)和排他(exclusive lock)锁

读锁是共享的互不干扰的,多个客户在同一时刻可读取同一资源,互不打扰。

写锁则是排他的,一个写锁会阻塞其他的写锁和读锁,确保在给定的时间,只有一个用户能执行写入,防止其他用户读取正在写入的资源。


锁粒度

顾名思义锁的粒度大小,这里表示锁的数据范围锁的是部分还是整体。任何时候在给定的资源,锁定的数据量越少,则并发的程度越高,只要不发生冲突即可,这句话很精辟。
但是加锁会消耗资源。包括获取锁、检查锁是否解除以及释放锁,都会增加系统开销。
Mysql的各种存储引擎都可以实现自己的锁策略和锁粒度。
锁策略就是在锁的开销和数据的安全性之间寻求平衡,大部分都是在表上加行级锁,然后再以各种复杂的方式来实现。

表锁(table lock)

表锁是开销最小的锁策略,它对整张表进行加锁一用户对表进行写操作时(插入、删除、更新等),需要先获得锁,阻塞其他用户对表的所有读写操作。只有没有写锁时其他用户才能获取读锁。

写锁比读锁有更高的优先级,因此一个写锁请求可能会被插入到读锁队列前面(写锁可以插入读锁前面,读不能插入到写锁前面)

场景:ALTER TABLE之类的语句会使用表锁,忽略了存储引擎的锁机制。


行锁(row lock)

行级锁可以最大程度的支持并发处理(开销大)。在InnoDB和XtraDB,以及其他一些存储引擎中实现了行级锁。


事务

**ACID(Atomicity Consistency Isolation Durability)**相信大家不陌生吧,很经典的面试题啊。
在这里我通过一个例子带大家领略一下ACID四大特性。
假设:银行数据库现在有两张库表:支票表和储蓄表。现在要从用户孙嵓支票账户转移200rmb到他的储蓄账户,那么至少需要三个步骤:

  1. 检查支票的账户余额是否高于200rmb
  2. 从支票账户余额减去200rmb
  3. 储蓄账户中余额增加200rmb

这三个操作打包在一个事务中,任何一个步骤失败,则必须回滚所有的步骤,保证数据。
图片: https://uploader.shimo.im/f/TG5zd5Lg69NMxVly.png!thumbnail?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NDg2MTAyMzksImciOiI1cms5ZGxZNDQ3VVA3eXF4IiwiaWF0IjoxNjQ4NjA5OTM5LCJ1c2VySWQiOjY3MjM3Njk0fQ.UbcTsP4x9ETeMAHIHadpDppiqRV275O9-Sa_hUJ4Jxw

原子性(Atomicity)

整个事务的操作要么全部成功,要么全部失败

一致性(Consistency)

我的钱从那个账户转到另一个账户,总量是没变的,只不过从一个账户到了另一个账户;即使上述3,4语句崩溃了,事务会回滚200rmb还是再支票账户里。

隔离性(Isolation)

通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。比如我执行完第三句时,第四句还没开始时,此时有另外一个账户汇总程序开始运行,这个时候查到的余额没有被减去200rmb。这个跟后面讲到的隔离级别有关联。

持久性(Durability)

一旦事务提交了,所做的修改就会永久保存到数据库中。

这种事务极大的保证了数据的安全性,但是像我们锁一样额外增加了系统的开销,要对这些额外的开销做优化正是Mysql存储引擎的架构之处,用户可根据业务是否需要事务处理去选择合适的引擎,即使不支持事务的引擎可通过LOCK TABLES来提供一定程度的保护。


隔离级别

Sql标注定义了四种隔离级别,Mysql默认的隔离级别REPEATEABLE READ(可重复读)

READ UNCOMMITED(未提交读)

事务中的修改,对其他事务都是可见的即事务可以读取为提交的数据称为脏读(Drity Read),例如上述隔离性的例子,他是可以看到账户已经减掉200rmb了。

READ COMMITED(提交读)

一个事务只能看到已经提交的事务所做的修改 (解决了脏读)。但是当一个A事务开始查询X数据之后另一个B事务提交对X数据的修改,A事务再次查询发现数据被修改了这种场景也被称为不可重复读(nonrepeatable read)

REPEATEABLE READ(可重复读)

一个事务中保证多次读取同样记录的结果是一致的(解决了不可重复读)。但是会导致幻读(Phantom Read)指的是A事务读取某个范围的的记录,B事务在该范围内插入了一条新纪录,A事务再次读取的此范围的时候会产生幻行(Phantom Row)。InnoDB和XtraDB存储引擎通过**多版本并发控制(MVCC,Multiversion Concurrency Contral)**解决了幻读问题。

SERIALIZABLE(可串行化)

最高的隔离级别,强制事务串行化,避免了所有问题。简单来书会在读取的每一行数据上都加锁,所以会导致大量的超时和锁争用的问题。只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑使用

放一张隔离级别的对比图:
图片: https://uploader.shimo.im/f/Vu6n6mbqFmB6D7us.png!thumbnail?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NDg2MTAyMzksImciOiI1cms5ZGxZNDQ3VVA3eXF4IiwiaWF0IjoxNjQ4NjA5OTM5LCJ1c2VySWQiOjY3MjM3Njk0fQ.UbcTsP4x9ETeMAHIHadpDppiqRV275O9-Sa_hUJ4Jxw


死锁

两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,导致恶性循环的现象。多个事务试图以不同的顺序锁定资源时,就可能会产生死锁。多个事务同时锁定同一个资源时,也会产生死锁。
提供一个场景:
图片: https://uploader.shimo.im/f/lFfdjQzfBdlCjivH.png!thumbnail?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NDg2MTAyMzksImciOiI1cms5ZGxZNDQ3VVA3eXF4IiwiaWF0IjoxNjQ4NjA5OTM5LCJ1c2VySWQiOjY3MjM3Njk0fQ.UbcTsP4x9ETeMAHIHadpDppiqRV275O9-Sa_hUJ4Jxw

如果凑巧两个事务都执行了第一条语句,更新了一行数据,同时也锁定了该行数据,接着事务都尝试去执行第二条update,却发现该行被对方锁定,两个事务都在等待对方释放锁,同时又持有对方需要的锁,则陷入了死循环。除非有外部因素介入才能解除死锁。
图片: https://uploader.shimo.im/f/TjhgA3Xr1qveZSMG.png!thumbnail?accessToken=eyJhbGciOiJIUzI1NiIsImtpZCI6ImRlZmF1bHQiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJhY2Nlc3NfcmVzb3VyY2UiLCJleHAiOjE2NDg2MTAyMzksImciOiI1cms5ZGxZNDQ3VVA3eXF4IiwiaWF0IjoxNjQ4NjA5OTM5LCJ1c2VySWQiOjY3MjM3Njk0fQ.UbcTsP4x9ETeMAHIHadpDppiqRV275O9-Sa_hUJ4Jxw

死锁发生后,只有部分或者完全回滚其中一个事务,才能打破死锁
事务日志


事务日志

可以帮助提高事务的效率。简单来说使用事务日志,存储引擎在修改表数据时只需要修改其内存拷贝,再将该行为持久在硬盘上的事务日志中,而不用每次将修改的数据本身持久到磁盘。事务日志采用追加的方式,写日志操作磁盘一小块区域顺序I/O,而不像随机I/O需要在磁盘多地方移动磁头。事务日志持久后,内存中修改的数据在后台可慢慢刷新回到磁盘即预写式日志(Write-Ahead Loggin),修改数据需要写两次磁盘。


以上就是本文的全部内容了,能力有限,理性对待

如果感觉还不错的话,欢迎点赞和关注🦋

分享经验,贴近项目,crud永不为奴!!!


欢迎大家关注我的公众号,公众号也会实时发布Java项目相关的文章!!!

在这里插入图片描述


在这里插入图片描述
1.一文搭建本地git服务器

2.Java实现短信验证码

3. 搭建本地git服务


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙嵓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值