草庐IT

高性能MySQL(第4版) 第一章 MySQL架构 读书笔记

fairjm 2023-03-28 原文

这本书去年11月出的,今年中文版也出了,并且直接上了微信读书,之后有空就读一读,分享下读书笔记~

原文内容比较充实,建议有时间可以读一下原文.
第一章主要是个概览.

MySQL的逻辑架构

默认情况下,每个客户端连接都会在服务器进程中拥有一个线程,该连接的查询只会在这个单独的线程中执行,该线程驻留在一个内核或者CPU上.
线程池

优化器会向存储引擎询问它的一些功能、某个具体操作的成本,以及表数据的统计信息.

query cache 5.7.20弃用 8.0移除
考虑应用自己在redis中缓存

并发控制

只要有多个查询需要同时修改数据,就会产生并发控制问题

读写锁

处理并发读/写访问的系统通常实现一个由两种锁类型组成的锁系统
这两种锁通常被称为共享锁(shared lock)和排他锁(exclusive lock),也叫读锁(read lock)和写锁(write lock)

锁的粒度

通过降低锁的粒度提高共享资源并发性
只锁定包含需要修改的部分数据

表锁

table lock
最基本 开销最小的锁策略(锁本身的开销 不是指查询/修改性能)

行级锁

row lock
最大程度支持并发处理 最大的锁开销
行级锁是在存储引擎中实现

事务

事务就是一组SQL语句,作为一个工作单元以原子方式进行处理
要么全部执行成功 要么全部执行失败

ACID

隔离级别

这里谈的是ANSI SQL中的定义

  • READ UNCOMMITTED: 未提交读
    在事务中可以查看其他事务中还没有提交的修改
    脏读(dirty read): 读取未提交的数据

  • READ COMMITTED: 已提交读
    大多数数据库系统的默认级别
    但MySQL不是
    一个事务可以看到其他事务在它开始之后提交的修改,但在该事务提交之前,其所做的任何修改对其他事务都是不可见的.
    允许不可重复读(nonrepeatable read) 同一个事务中两次执行相同语句 可能看到不同结果

  • REPEATABLE READ: 可重复读
    解决了不可重复读
    无法解决幻读(phantom read) 读取范围数据时 如果另一个事务在该范围插入了新的 再次读取会产生换行(phantom row)
    InnoDB和XtraDB通过MVCC解决
    这也是MySQL默认的隔离级别

  • SERIALIZABLE: 可串行化
    该级别通过强制事务按序执行,使不同事务之间不可能产生冲突,从而解决了前面说的幻读问题.
    会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题.
    使用场景较少 除非需要严格确保数据安全 并且接收并发性能下降

死锁

两个或多个事务相互持有和请求相同资源上的锁,产生了循环依赖.
当多个事务试图以不同的顺序锁定资源时会导致死锁.

数据库系统实现了各种是说检测和锁超时机制
InnoDB目前处理死锁的方式是将持有最少行级排他锁的事务回滚
锁的行为和顺序和存储引擎相关

console1:
start transaction ;
update user set user_name='cc11' where user_id=1;
update user set user_name='cc22' where user_id=2;
commit ;
console2:
start transaction ;
update user set user_name='cc222' where user_id=2;
update user set user_name='cc111' where user_id=1;
commit ;

单步执行

[40001][1213] Deadlock found when trying to get lock; try restarting transaction

事务日志

事务日志有助于提高事务的效率.存储引擎只需要更改内存中的数据副本,而不用每次修改磁盘中的表,这会非常快.

事务日志只追加 顺序I/O
WAL write-ahead logging 预写日志 修改数据最终要两次磁盘写入

MySQL中的事务

描述的是InnoDB引擎中的事务

理解AUTOCOMMIT

默认开启 单个语句也是包裹在事务中 自动提交
可以通过set autocommit=0/1进行开关
用begin或者start transaction来开启事务
用commit提交 rollback回滚

有一些命令,当在活动的事务中发出时,会导致MySQL在事务的所有语句执行完毕前提交当前事务
比如一些DDL命令 alter table等

可以通过SET TRANSACTION ISOLATION LEVEL改变隔离级别 下一个事务开始时生效

在事务中混合使用存储引擎

MySQL的事务由下层存储引擎实现
在同一个事务中,混合使用多种存储引擎是不可靠的.

隐式锁定和显式锁定

InnoDB使用两阶段锁定协议(two-phase locking protocol).
事务执行期间,随时都可以获取锁,但锁只有在提交或回滚后才会释放,并且所有的锁会同时释放.
前面描述的锁定机制都是隐式的.InnoDB会根据隔离级别自动处理锁.

显式的(不属于SQL规范)

SELECT … FOR SHARE
SELECT … FOR UPDATE

MySQL还支持LOCK TABLES和UNLOCK TABLES
这两个命令在服务器级别实现
因为InnoDB支持行级锁 没必要使用

建议: 除了在禁用AUTOCOMMIT的事务中可以使用之外,其他任何时候都不要显式地执行LOCK TABLES,不管使用的是什么存储引擎.

多版本并发控制

MySQL的大多数事务型存储引擎使用的都不是简单的行级锁机制.它们会将行级锁和可以提高并发性能的多版本并发控制(MVCC)技术结合使用.

不同数据库的实现细节不一样

可以认为MVCC是行级锁的一种变种 它在很多情况下避免加锁 因此开销更低

通过数据快照实现

  • InnoDB为每个事务启动时分配一个事务ID
  • 该事务修改记录时 向Undo log写入一条如何恢复回去的undo记录 事务回滚指针指向该记录
  • 当不同会话读取聚簇主键索引记录时 InnoDB会把记录的事务ID和该会话的读取视图比较 如果更改他的事务未提交 则跟踪undo log直到一个符合可见条件的事务ID

大多数读取通过这种方式不需要获取锁(通过读取快照) 缺点是存储引擎会对每一行存储更多数据 做更多工作

MVCC仅适用于REPEATABLE READ和READ COMMITTED隔离级别.
(可以想象对于可重复读 读取的事务id固定为事务进行中第一次读的可见事务id 对于读已提交 读最新的可见事务id
另外两个因为不需要事务版本(一个是脏读 一个是串行化的) 和MVCC不是很适配(当然要看不同引擎的实现)

复制

Replication
一主多从

数据文件结构

在8.0版本中,MySQL将表的元数据重新设计为一种数据字典,包含在表的.ibd文件中
使得表结构上的信息支持事务和原子级数据定义更改

除了以来information_schema检索表定义和元数据
引入了字典对象缓存 LRU的内存缓存
使得服务器访问表的元数据减少了I/O
每个表的.ibd和.frm文件被替换为已经被序列化的字典信息(.sdi).

InnoDB引擎

为处理大量短期事务而设计 这些事务预期通常是正常提交 很少会被回滚

默认情况下,InnoDB将数据存储在一系列的数据文件中,这些文件统被称为表空间(tablespace)

InnoDB使用MVCC来实现高并发性,并实现了所有4个SQL标准隔离级别.
默认为REPEATABLE READ隔离级别,并且通过间隙锁(next-key locking)策略来防止在这个隔离级别上的幻读:
InnoDB不只锁定在查询中涉及的行,还会对索引结构中的间隙进行锁定,以防止幻行被插入

基于聚簇索引构建
但是,因为二级索引(secondary index,非主键索引)需要包含主键列,如果主键较大,则其他索引也会很大.如果表中的索引较多,主键应当尽量小.


微信读书: https://weread.qq.com/web/bookDetail/00a32b70813ab746fg018ec7
博客位置: https://bingowith.me/2022/11/08/high-performance-mysql-4th-ch01-note/

有关高性能MySQL(第4版) 第一章 MySQL架构 读书笔记的更多相关文章

  1. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  2. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  3. ruby-on-rails - CarrierWave - PDF - 只选择第一页 - 2

    我的Rails应用程序中安装了carrierwave。但是,当用户上传多页pdf时,我只希望应用程序获取文档中的第一页并将其转换为jpeg。这可能吗?用什么命令?这是我的uploader。#encoding:utf-8classImageUploader[200,300]##defscale(width,height)##dosomething#end#Createdifferentversionsofyouruploadedfiles:version:thumbdoprocess:resize_to_fill=>[150,210]process:convert=>:jpgdefful

  4. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

    我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

  5. ruby - 如何跳过 CSV 文件的第一行并将第二行作为标题 - 2

    有没有办法跳过CSV文件的第一行,让第二行作为标题?我有一个CSV文件,第一行是日期,第二行是标题,所以我需要能够在遍历它时跳过第一行。我尝试使用slice但它会将CSV转换为数组,我真的很想将其读取为CSV,以便我可以利用header。 最佳答案 根据您的数据,您可以使用另一种方法和skip_lines-option此示例跳过所有以#开头的行require'csv'CSV.parse(DATA.read,:col_sep=>';',:headers=>true,:skip_lines=>/^#/#Markcomments!)do|

  6. Ruby 的数字方法性能 - 2

    我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

  7. ruby - Ruby 性能中的计时器 - 2

    我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

  8. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

  9. ruby - Ruby 和 Ruby on Rails 中的三层架构 - 2

    我是一名决定学习Ruby和RubyonRails的ASP.NETMVC开发人员。我已经有所了解并在RoR上创建了一个网站。在ASP.NETMVC上开发,我一直使用三层架构:数据层、业务层和UI(或表示)层。尝试在RubyonRails应用程序中使用这种方法,我发现没有关于它的信息(或者也许我只是找不到它?)。也许有人可以建议我如何在RubyonRails上创建或使用三层架构?附言我使用ruby​​1.9.3和RubyonRails3.2.3。 最佳答案 我建议在制作RoR应用程序时遵循RubyonRails(RoR)风格。Rails

  10. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

    如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

随机推荐