Skip to content

Daily Study

更新: 5/29/2025 字数: 0 字 时长: 0 分钟

Daily Plan

#todo

  • [ ]

Mysql锁相关

SELECT语句的锁

普通的Select在不同事务隔离级别下表现不同:

  • 读未提交:不加锁
  • 读已提交和可重复读:采用MVCC,不加锁读取行的一个快照版本
  • 串行化:隐式转换为 SELECT ...LOCK IN SHARE MODE,添加共享锁,如果涉及到幻读可能需要间隙锁

锁定读:

  • SELECT ... FOR UPDATESELECT ... FOR NO KEY UPDATE:对读取的行记录加X锁,如果包含索引,会锁定相应的索引记录,如果不包含索引则会锁整个表。在 REPEATABLE READSERIALIZABLE 隔离级别下,还会使用间隙锁 (Gap Locks)临键锁 (Next-Key Locks) 来防止幻读,即锁定一定范围,阻止其他事务在这个范围内插入新数据。
  • SELECT ... LOCK IN SHARE MODE (或 MySQL 8.0+ 的 SELECT ... FOR SHARE):对读取的行记录加S锁。在 REPEATABLE READSERIALIZABLE 隔离级别下和上面类似

UPDATE语句的锁

  • 在执行时,会对修改的行记录加X锁
  • 锁的粒度通常是行级锁
  • REPEATABLE READSERIALIZABLE 隔离级别下,UPDATE 语句为了防止幻读,通常会使用临键锁 (Next-Key Locks),这会锁定匹配到的索引记录以及它们之间的间隙。
  • 如果 UPDATEWHERE 条件没有使用索引或者索引区分度不高,可能会导致大范围的锁定,甚至锁表。
  • 锁会一直持有到事务提交或者回滚为止。
  • 具体的加锁方式根据索引类型(唯一/普通)和等值查询/范围查询来区分
    • 唯一索引等值查询且命中:通常只对命中的那一行加记录锁 (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 UPDATESELECT ... 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 地址 和虚拟机/宿主机是同等层次的,通过为容器提供 MACIP 地址,让容器在物理网络上成为"一等公民"。因为无须端口映射或者额外桥接,可以直接通过主机接口(或者子接口)访问容器接口。

但是,Macvlan的缺点是需要将主机网卡(NC)设置为混杂模式。(Promiscuous Mode),这在大部分公有云平台上是不允许的。所以 Macvlan 对于公司内部的数据中心网络来说很棒(假设公司网络组能接受 NIC 设置为混杂模式),但是 Macvlan 在公有云上并不可行。

Macvlan 本身是 linux kernel 模块,其功能是允许在同一个物理网卡上配置多个 MAC 地址,即多个interface。每个interface可以配置自己的IPMacvlan本质上是一种网卡虚拟化技术。

yaml
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

菜就多练

本站访客数 人次 本站总访问量