vlambda博客
学习文章列表

走进高性能Mysql(一)


大家好我是孙嵓,从今天起带大家阅读高性能的Mysql,让你清晰的认识Mysql以及如何最大限度的去优化Mysql,提高我们数据的查询速度,保证我们的业务顺利的进行,本文内容均来自《高性能Mysql》一书。


| Mysql服务器逻辑架构


走进高性能Mysql(一)


| 读写锁


读锁(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

这三个操作打包在一个事务中,任何一个步骤失败,则必须回滚所有的步骤,保证数据。

走进高性能Mysql(一)


原子性(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(可串行化)


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

 

放一张隔离级别的对比图:

走进高性能Mysql(一)


| 死锁


两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,导致恶性循环的现象。多个事务试图以不同的顺序锁定资源时,就可能会产生死锁。多个事务同时锁定同一个资源时,也会产生死锁。

提供一个场景:

走进高性能Mysql(一)

如果凑巧两个事务都执行了第一条语句,更新了一行数据,同时也锁定了该行数据,接着事务都尝试去执行第二条update,却发现该行被对方锁定,两个事务都在等待对方释放锁,同时又持有对方需要的锁,则陷入了死循环。除非有外部因素介入才能解除死锁。

走进高性能Mysql(一)

 

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


| 事务日志


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


走进高性能Mysql(一)
走进高性能Mysql(一)

走进高性能Mysql(一)

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

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

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

走进高性能Mysql(一)

推荐阅读






点个在看你最好看