UDP
无连接
报文格式
- 目标端口,16bit
- 源端口,16bit
- 包长度,16bit
- 校验和,16bit
用于确认IP包是否成功送达目标地址,报告发送过程中IP被废弃的原因和改善网络设置等
查询报文类型
标识符字段会记录由那个引用发送的ICMP包,同时选项数据中会记录发送时间,用于计算RT,说明路程的长短
差错报文类型
3-目标不可达
4-远点抑制,增大IP数据包的传输间隔,缓和网络拥堵
5-重定向或改变路由
11-超时, TTL减为0时,数据包将被丢弃,会向发送方发送一个ICMP消息
Ping命令
IGMPv1一共有两种报文,普查报文和成员报告报文,没有离组报文。
IGMPv1只有一种机制,响应抑制机制,没有离组机制。
IGMPv1没有查询器选举机制,需要PIM的DR来充当IGMPv1的查询器。
IGMPv1没有离组机制,对流量的控制性不好。
MySQL以Page页为单位,默认大小16K,会在Buffer Pool中划分出很多的缓存页,并用描述数据(元数据)记录缓存页所在的表空间 数据页编号、Buffer Pool地址等信息,底层采用链表数据结构管理Page
上图描述了Buffer Pool在innoDB中的位置,通过它所在的位置我们可以大概知道它的工作流程:
所有的更新和读取都是在Buffer Pool中进行。并由异步线程不断刷盘。查询数据时通过hash表快速定位到对应的缓存页
语句 | 锁类别 | 用途 |
---|---|---|
lock tables t read | 表锁,读锁,共享锁 |
表共享锁之间不互斥,读读可以并行 |
lock tables t write | 表锁,写锁,排他锁 |
表排他锁与任何锁都互斥,读写/写写都不可并行 |
意向锁是表级锁,不会和行级锁发生冲突,并且意向锁之间也不会发生冲突。
只会和共享表锁、独占表锁发生冲突
普通的select操作利用MVCC实现一致性读,是【无锁】的
加锁方式 | 规则 | 锁类别 |
---|---|---|
select … lock in shard mode | 先对表加上【意向共享锁】,再对读取的记录加上【排它锁】 | 意向锁,共享锁(S),排他锁 |
select … for update | 先对表加上【意向排他锁】,再对读取的记录加【排它锁】 | 意向锁,排他锁(X) |
执行插入、更新、删除操作前,需要先对表加上【意向共享锁】,再对记录加【排它锁】
表锁和行锁之间满足【读读共享】、【读写互斥】、【写写互斥】
如果没有【意向锁】,那么加【排他表锁】时需要遍历表里的所有记录,查看是否有记录存在【排它锁】,效率会很慢。
有了【意向锁】之后,由于在对记录加排他锁之前,先会加上表级别的【意向排它锁】,那么在对记录加【排他锁时】,直接查看该表是否存在【意向排他锁】即可
锁类型 | 用途 |
---|---|
意向排他锁(IX) | 一个事务想给一个数据行加排他锁之前,必须先获得该表的IX锁 |
意向共享锁(IS) | 一个事务给一个数据行加共享锁之前,必须先获得该表的IS锁 |
当另外事务想给该表加表锁(S锁 或 X锁)时,只需查看该表上的IS锁和IX锁的加锁情况即可,不用再做遍历行锁的行为 |
字段被声明为AUTO_INCREATMENT时,数据库会自动给该字段赋递增的值,通过AUTO-INC锁实现的
在插入数据时,会加上AUTO-INC锁,插入语句执行完成后会释放。事务持有该锁的过程,其他事务的插入将会被阻塞(排它锁)
大量数据插入时会影响性能。
MySQL 5.1.22版本后InnoDB提供了【轻量级】的锁实现自增
innodb_autoinc_lock_mode 变量控制选择AUTO-INC还是轻量级锁
等级 | 锁类型 |
---|---|
innodb_autoinc_lock_mode = 0 | 选用AUTO-INC锁 |
innodb_autoinc_lock_mode = 2 | 选用轻量级锁 |
innodb_autoinc_lock_mode = 1 | (默认值)时混用两种锁 |
锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间(可重复读级别下才会有间隙锁)
当我们用范围条件而不是相等条件索引数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”。
InnoDB也会对这个“间隙”枷锁,这种锁机制就是所谓的间隙锁(Next-Key锁)
间隙锁定之间不存在冲突关系如果一个事务对某个间隙中间加了锁,那么其他事务也可以在这个间隙中加锁,这些操作不冲突。它的存在,仅仅是为了防止其他事务在这个间隙中插入记录。
【前开后开】区间
它是对记录【加锁的基本单位】,更新非唯一索引对应的记录(重点),会加上Next-Key Lock,同时锁住记录本身,以及数据相邻上游范围和相邻下游范围
由【记录锁】和【间隙锁】组合而成
next-key lock 【前开后闭】区间
某些场景下会退化成为【记录锁】或【间隙锁】
场景 | 状态 |
---|---|
唯一索引等值查询 | 记录存在,会退化成为【记录锁】(记录锁,前开后闭区间) |
记录不存在,会退化成为【间隙锁】 | |
唯一索引范围查询 | 会退化为加【记录锁】或【间隙锁】,也可能同时加两个锁 |
非唯一索引等值查询 | 记录存在时会加上next-key lock以及【间隙锁】 |
记录不存在时,会加上多个【间隙锁】 | |
非唯一索引范围查询 | 不会退化,只会加【next-key lock】 |
sql_safe_updates安全模式
当变更表数据未添加Where条件时,会对所有记录加锁(多个Record锁+Gap锁,形成类似表锁的结构)
即使加Where条件,若优化器最终选择全表,则仍全表加锁
开启方法:sql_safe_updates=1
Update语句必须满足如下条件之一才能执行成功
使用where子句,并且where子句中列必须为prefix索引列
使用limit
同时使用where子句和limit(此时where子句中列可以不是索引列)
Delete语句必须满足如下条件之一才能执行成功
锁操作 | 锁处理 |
---|---|
加锁 | 在事务中,随着执行的SQL,按需获取锁。 过程中可能会有阻塞等待或死锁 |
释放锁 | 事务提交时,自动释放本事务中所有的锁 |
死锁的发生:多个事务,每个事务都已持有部分锁,然后进一步去获取对方事务持有的锁,互相等待。
参数 | 作用 |
---|---|
innodb_lock_wait_timeout | 设置锁超时时间,默认50秒 |
innodb_deadlock_detect | 开启死锁检测,在检测到死锁时回滚两条中的某一个事务(默认值on) |
正常情况下采用第二种策略。主动死锁检测在发生死锁的时候,是能够快速发现并进行处理的。
业务研发上,一般以乐观锁为主。
SQL尽量用索引,因为走索引才能用上行锁,更细粒度的锁,减少锁冲突的概率。
减少大事务,用于减少持有锁的时间,进而降低冲突。
https://dev.mysql.com/doc/refman/5.6/en/innodb-locking.html#innodb-intention-locks
MVCC (Multiversion Concurrency Control),多版本并发控制,是Innodb实现事务回滚与并发的重要功能
目的:解决不可重复读,用于支持读已提交(RC)和可重复读(RR)隔离级别的实现
场景 | 是否存在问题 |
---|---|
读读 | 不存在数据安全问题 |
写写 | 有数据安全问题,更新丢失 |
读写 | 有线程安全问题,脏读、幻读、不可重复读(MVCC就是为了解决这种问题而存在的) |
如果是RC隔离级别,那么每次在进行快照读的时候都会生成一个新的readview
如果是RR隔离级别,那么只有在当前事务第一次进行快照读的时候会生成readview,之后的快照读都会沿用当前的readview
RC和RR之间的区别就在于生成readview的时机不同
MVCC主要是用来解决【读-写】冲突的无锁并发控制,可以解决以下问题:
MVCC与锁的组合
一般数据库中都会采用以上MVCC与锁的两种组合来解决并发场景的问题,以此最大限度的提高数据库性能。
通过上述描述,MVCC的作用可以概括为就是为了解决【读写冲突】,提高数据库性能的,而MVCC的实现又依赖【隐式字段】【undo日志】【版本链】【快照读和当前读】【读视图】。