Daily Study
更新: 5/29/2025 字数: 0 字 时长: 0 分钟
Daily Plan
#todo
- [ ]
Mysql锁相关
SELECT语句的锁
普通的Select在不同事务隔离级别下表现不同:
- 读未提交:不加锁
- 读已提交和可重复读:采用MVCC,不加锁读取行的一个快照版本
- 串行化:隐式转换为
SELECT ...LOCK IN SHARE MODE
,添加共享锁,如果涉及到幻读可能需要间隙锁
锁定读:
SELECT ... FOR UPDATE
或SELECT ... FOR NO KEY UPDATE
:对读取的行记录加X锁,如果包含索引,会锁定相应的索引记录,如果不包含索引则会锁整个表。在REPEATABLE READ
和SERIALIZABLE
隔离级别下,还会使用间隙锁 (Gap Locks) 或 临键锁 (Next-Key Locks) 来防止幻读,即锁定一定范围,阻止其他事务在这个范围内插入新数据。SELECT ... LOCK IN SHARE MODE
(或 MySQL 8.0+ 的SELECT ... FOR SHARE
):对读取的行记录加S锁。在REPEATABLE READ
和SERIALIZABLE
隔离级别下和上面类似
UPDATE语句的锁
- 在执行时,会对修改的行记录加X锁
- 锁的粒度通常是行级锁
- 在
REPEATABLE READ
和SERIALIZABLE
隔离级别下,UPDATE
语句为了防止幻读,通常会使用临键锁 (Next-Key Locks),这会锁定匹配到的索引记录以及它们之间的间隙。 - 如果
UPDATE
的WHERE
条件没有使用索引或者索引区分度不高,可能会导致大范围的锁定,甚至锁表。 - 锁会一直持有到事务提交或者回滚为止。
- 具体的加锁方式根据索引类型(唯一/普通)和等值查询/范围查询来区分
- 唯一索引等值查询且命中:通常只对命中的那一行加记录锁 (Record Lock)。
- 唯一索引范围查询或未命中:可能会加间隙锁 (Gap Lock) 或 Next-Key Lock (记录锁 + 间隙锁) 来锁定一个范围,防止幻读(尤其在 RR 级别)。
- 普通索引等值查询且命中:除了对命中的索引记录加锁,通常还会在对应的聚集索引记录上也加锁。如果是RR级别,还可能在索引间隙上加间隙锁或Next-Key Lock。
- 普通索引范围查询:会锁定扫描到的所有符合条件的索引记录及其对应的聚集索引记录,并在相关间隙上加间隙锁或Next-Key Lock (RR级别)。
并发的SELECT和UPDATE
通过不同的事务隔离级别和Select类型来讨论:假设事务A执行 UPDATE
,事务B执行 SELECT
如果事务B是普通的SELECT
:
- 在
READ COMMITTED
级别:事务B会读取事务A提交后的最新数据(如果A已提交),或者读取A操作前的数据(如果A未提交)。通过MVCC,通常不会被A的X锁阻塞。 - 在
REPEATABLE READ
级别:事务B会读取其事务开始时建立的快照版本的数据,即使事务A后续修改并提交了这些行,事务B也看不到这些变更。通过MVCC,通常不会被A的X锁阻塞。 - 在
SERIALIZABLE
级别:普通SELECT
会隐式加 S 锁,因此会被事务A持有的 X 锁阻塞,直到A释放锁。
如果事务B时锁定读,类似SELECT ... FOR UPDATE
或 SELECT ... FOR NO KEY UPDATE
:由于事务A已经持有这些行的X锁,所以事务B会被阻塞
Docker的网络模式
Bridge模式
bridge
模式是docker
中的默认模式- 当
docker
进程启动的时候,会在主机上创建一个名为docker0
的虚拟网桥,此主机启动的Docker
容器会连接到这个docker0
的网桥上,虚拟网桥的工作方式和物理交换机相似,因此虚拟网桥类似工作在数据链路层,这样主机上的所有容器就通过交换机连在了一个二层网络上。 - 从
docker0
子网中分配一个IP给容器使用,并设置docker0
的IP地址为容器的默认网关,在主机上创建一堆虚拟网卡veth-pair
设备,veth-pair
是一种成对出现的特殊网络设备,可以把他们想象成由一根虚拟网线连接起来的一对网卡,网卡的一头(eth0)
在容器中,另一头(vethadb)
挂在网桥docker0上。 - 如果不写
-network
参数,默认就是bridge
模式,通过-p
参数来指定端口映射docker run --name tomcat -d -p 8000:8080 tomcat
Host模式
如果启动容器的时候使用host
模式,那么这个容器将不会获得一个独立的Network Namespace
,而是和宿主机共用一个Network Namespace
。容器将不会虚拟出自己的网卡,配置自己的IP
等,而是使用宿主机的IP
和端口。命令:docker run --name t2 --network=host -d tomcat
容器将直接使用主机的网络栈,与主机共享网络接口和 IP 地址,这意味着容器可以直接访问主机上的所有网络服务,同时也会导致容器与主机网络之间的隔离性降低。
container模式
container模式和host模式很类似,host模式和宿主主机共享network namespace;container模式和指定的容器共享,两者之间除了网络共享(网卡、主机名、IP 地址),其他方面还是隔离的。
隔离性好,只占用一个IP
,会占用容器的端口,性能差,开发网关应用的时候可以考虑。
命令: docker run -d -name tomcat02 --net=container:name/id -p 8000:80 tomcat:latest
None模式
如果dockers容器指定的网络模式为none,该容器没有办法联网,外界也无法访问它,可以用来本次测试。(基本不用)命令:docker run -d -name tomcat02 --net=none -p 8000:80 tomcat:latest
。
自定义模式
参照链接:彻底透彻Docker常用网络模式及应用场景-腾讯云开发者社区-腾讯云
Macvlan:容器占用的 IP
地址 和虚拟机/宿主机是同等层次的,通过为容器提供 MAC
和 IP
地址,让容器在物理网络上成为"一等公民"。因为无须端口映射或者额外桥接,可以直接通过主机接口(或者子接口)访问容器接口。
但是,Macvlan
的缺点是需要将主机网卡(NC)
设置为混杂模式。(Promiscuous Mode)
,这在大部分公有云平台上是不允许的。所以 Macvlan
对于公司内部的数据中心网络来说很棒(假设公司网络组能接受 NIC
设置为混杂模式),但是 Macvlan
在公有云上并不可行。
Macvlan
本身是 linux kernel
模块,其功能是允许在同一个物理网卡上配置多个 MAC
地址,即多个interface
。每个interface
可以配置自己的IP
。Macvlan
本质上是一种网卡虚拟化技术。
docker network create -d macvlan
--subnet=192.168.31.0/24\
--ip-range=192.168.31.0/24\
--gateway=192.168.31.1\
-o parent=ens33\
macvlan31