BoyChai's Blog - 闲谈 https://blog.boychai.xyz/index.php/category/%E9%97%B2%E8%B0%88/ [MYSQL]SQL优化 https://blog.boychai.xyz/index.php/archives/64/ 2023-09-05T04:51:00+00:00 插入数据批量插入数据推荐使用下面语句INSERT INTO 表名(字段1,字段2,......) VALUES (值1,值2,......),(值1,值2,......),(值1,值2,......);如果数据量过于庞大,数据条数大于1000推荐使用文件导入的方式进行插入,方法如下## 登录mysql的时候需要添加--local-infile参数 mysql --local-infile -u root -p ## 登录之后设置local_infile为1,开启从本地加载文件导入数据的开关 set global local_infile=1; ## 使用load命令导入数据 load data local infile '文件' into table `表名` fields terminated by `文件里面的分隔符` lines terminated by '\n';文件里面的内容格式如下1,a,b,c 2,b,c,dPS:主键顺序插入性能高于乱序插入主键优化数据组织方式在InnoDB存储引擎中,表数据都是根据逐渐顺序组织存放的,这种存储方式的表成为索引组织表(index organized table IOT)页分裂页可以为空 ,也可以填充一半,也可以填充100%。每个页包含了2-N行数据(如果 一行数据多大,会溢出),根据主键排列。页合并当删除一条记录时,实际上记录并没有被物理删除,只是被标记(flaged)为啥暗处并且他的空间变得允许被其他记录声明使用。当页面中删除的记录达到MERGE_THRESHOLD(默认为页的50%),InnoDB会开始寻找最靠近的页(前或后)看看是否可以将两个页合并已优化空间使用。主键设置原则满足业务要求的情况下,尽量降低主键长度。插入数据的时,尽量选择顺序插入,选择使用AUTO_INCREMENT自增主键。尽量不要使用UUID做主键或者是其他自然主键,如身份证。业务操作时,避免对主键的修改。order by优化Using filesort通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sort buffer中完成排序操作,所有不是通过索引直接返回排序结果的排序都叫FileSort排序。Using index通过有序索引顺序扫描直接返回有序数据,这种情况即为using index,不需要额外排序,操作效率更高。优化根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。尽量使用覆盖索引。多字段排序,一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)如果不可避免出现filesort,大数据量排序时,可以适当增大排序缓冲区大小sort_buffer_size(默认256k)。group by优化分组操作时,可以通过索引来提高效率。分组操作时,索引的使用也是满足最左前缀法则的。limit优化一般分页查询时,通过创建 覆盖索引 能够比较好的提高性能,可以通过覆盖索引加子查询形式进行优化。count优化在MyISAM引擎把一个表的总行数存在了磁盘上,因此执行count(*)的时候会直接返回这个数,效率很高。InnoDB引擎就麻烦了,他执行count(*)的时候,需要把数据一行一行的从引擎里面读出来,让后累计计数。count(主键)InnoDB引擎会遍历整张表,把每一行的主键id值都取出来,返回给服务层。服务层拿到主键后,直接按行累加(主键不可能为null)。count(字段)没有not null约束时: InnoDB疫情会便利整张表把每一行的字段值都取出来,返回给服务层,服务层判断是否为null,不为null,计数累加。有not null约束时: InnoDB疫情会便利整张表把每一行的字段值都取出来,返回给服务层们直接按行进行累加。count(1)InnoDB疫情遍历整张表,但不取值。服务层对于返回的每一行,放一个数字“1”进去,直接按行累加。count(*)InnoDB疫情并不会把全部字段取出来,而是专门做了优化,不取值,服务层直接按行进行累加。优化方案可以自己做count,使用缓存数据库做这类工作。按照效率排序的话,count(字段)<count(主键)<count(1)≈count(*),所以尽量使用count(*)。update优化InnoDB的行锁是针对索引加的锁,不是针对记录家的锁,并且该索引不能失效,否则会从行锁升级为表锁。规避这种情况就需要在对应字段创建索引。 [排错笔记]Ingress-Nginx传递用户真实ip问题 https://blog.boychai.xyz/index.php/archives/62/ 2023-08-25T13:53:00+00:00 引入问题我的K8s环境是宿主机的hyper-v虚拟出来的,如果要映射到外面则还需要再我的宿主机上面再做一层反代,我采用的是nginx,当ingress整好之后,我从我从我腾讯云上复制了一段nginx配置放到了我的宿主机,主要配置如下:location /test/ { proxy_pass http://kubernetes.boychai.xyz/test/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }为了防止传入的ip是代理主机的ip我这里设置了Host、X-Real-IP、REMOTE-HOST、X-Forwarded-For。经过测试之后发现使用宿主机配置的代理访问时返回404,在宿主机上直接却没问题。访问问题日志我去查看了宿主机的nginx日志、ingress-nginx-controller日志、应用程序的日志,发现除了宿主机的nginx均没有日志记录,宿主机日志信息如下111.180.204.54 - - [25/Aug/2023:22:12:21 +0800] "GET /test/ HTTP/1.1" 404 548 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"除了这一条之外其他的日志均无404。解决看到日志之后有点懵,因为我的宿主机是可以直接访问ingress暴露出来的服务的,而且没有报错正常访问,我是用反代之后就报错404,我最开始以为这个404就是我宿主机报的,但是宿主机的404默认页面会返回nginx的版本,如下图而我反代返回的404页面则是这样的一想就是我ingress返回的页面,但是我去查看ingress-nginx-controller的日志并无404的报错,日志查看命令如下,访问时并无产生记录[root@kubernetes ~]# kubectl -n ingress-nginx logs -f ingress-nginx-controller-kc5np我这里去尝试修改宿主机的反代配置,配置如下location /test/ { proxy_pass http://kubernetes.boychai.xyz/test/; }发现这样是可以正常访问程序的,这就奇怪了,难不成还能是因为我设置了这几个header的问题?我挨个注释这些header的配置发现问题出在下面这段配置proxy_set_header Host $host;具体原因也没搞清楚但是取消使用这条配置就好了...原因在Kubernetes的Ingress中,Host 头部用于根据不同的域名(或主机名)将请求路由到不同的服务。每个Ingress规则可以基于请求的 Host 头部将流量路由到不同的后端服务。我宿主机代理的域名和Ingress设置的域名不同,所以导致了这个问题,我外部代理的域名是tools.boychai.xyz而我k8s设置Ingress的域名则是kubernetes.boychai.xyz,当我在宿主机的代理设置了proxy_set_header Host $host;这段配置之后,请求发到Ingress之后,Ingress拿到的路由请求域名则是tools.boychai.xyz,而我又没有设置这个资源则就返回了404。IP传递问题日志能够访问之后发现最终的应用拿不到真是访问的ip,这里通过nginx直接返回X-Forwarded-For头信息来查看问题出在什么位置,宿主机Nginx配置如下location /aaa { default_type text/html; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; return 200 "proxy_add_x_forwarded_for:$proxy_add_x_forwarded_for"; } location /test/ { # ingress暴露的地址`http://kubernetes.boychai.xyz/test/` proxy_pass http://kubernetes.boychai.xyz/test/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }后端Nginx配置如下location / { default_type text/html; return 200 "proxy_add_x_forwarded_for:$proxy_add_x_forwarded_for"; }这样访问反代的/aaa就是访问反代主机的ip,访问反代的/test就会返回访问nginx的后端访问的ip,访问结果如下访问/aaa返回proxy_add_x_forwarded_for:111.180.204.54访问/test返回proxy_add_x_forwarded_for:192.16.1.1, 192.16.1.2解决查看访问返回的信息发现直接访问代理的ip是没问题的,那就是Ingress的锅了,这里的1.1和1.2依次是反代的ip和k8s主机的ip,到ingress这层没有把x_forwarded_for头加进来,这里我去官方翻了翻文档发现了三条和x_forwarded_for有关系的配置,如下data: ... compute-full-forwarded-for: "true" # 这一条可以不加也需要知道 # forwarded-for-header: "X-Forwarded-For" use-forwarded-headers: "true" 给ingress的cm加上这两条配置即可解决问题,最终/test返回的内容如下proxy_add_x_forwarded_for:111.180.204.54, 192.16.1.1, 192.16.1.2原因Ingress默认是没有配置传递真实IP功能的,需要配置,这三条配置和官网文档如下:use-forwarded-headers文档位置: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#use-forwarded-headers如果为true,则ingress-nginx会将传入的x-forward-*传递到上游,如果是Ingress上层还有一层ingress则需要配置这一条。如果他直接暴露在公网中或者它基于L3的网络负载后门则不需要管,因为它默认就是false。forwarded-for-header文档位置: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#forwarded-for-header这个用来设置客户端来源的真实IP,默认就是X-Forwarded-For。这里不需要额外配置。compute-full-forwarded-for文档位置: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#compute-full-forwarded-for如果开启了use-forwarded-headers的话,会发现还是没能获取到客户端的真实IP,原因是当前X-Forwaded-Fox变量是从remote_addr获取的,每次都是拿上一层的代理ip,这段配置的作用是将客户端用户访问所经过的代理ip都追加到X-Forwaded-Fox. [折腾]绕过校园网WEB认证解决方案 https://blog.boychai.xyz/index.php/archives/50/ 2023-03-17T04:05:00+00:00 原理分析先说一下原理,连接上校园网设备之后只要不进行认证,大部分的流量只要是经过校园网设备都会拦截之后给客户端重定向到一个认证页面(本文封面),让其进行认证。不进行认证的小部分流量比如说是dhcp、dns都不会进行拦截重定向,dhcp要进行分配ip,刚连接的设备需要通过这个dhcp才可以拿到自己的ip地址,dns是域名解析服务也不会拦截。他们的端口分别是DHCP(UDP/67服务端、UDP/68客户端)、DNS(UDP/53),目前只发现了这两个服务的端口是不被拦截的。我们可以通过这些端口来绕过流量的拦截。例如使用虚拟专用网络、虚拟隧道等技术来实现绕过拦截。干!!!软件介绍本文服务端使用V2ray软件进行绕过,项目地址以及文档地址如下:项目地址:https://github.com/v2fly/v2ray-core文档地址:https://www.v2fly.org/客户端为了方便采用V2rayN和服务端进行链接,项目地址如下:项目地址:https://github.com/2dust/v2rayN部署搭建我们在服务端部署一下v2ray,如何去下载这里不多讲解,部署方式如下# 下载 [root@dj1 work]# wget https://github.com/v2fly/v2ray-core/releases/download/v5.3.0/v2ray-linux-64.zip 100%[==============================================================================================>] 11,706,579 3.22MB/s in 3.5s # 解压 [root@dj1 work]# unzip v2ray-linux-64.zip Archive: v2ray-linux-64.zip inflating: config.json inflating: geosite.dat inflating: geoip-only-cn-private.dat creating: systemd/ creating: systemd/system/ inflating: systemd/system/v2ray.service inflating: systemd/system/v2ray@.service inflating: vpoint_socks_vmess.json inflating: geoip.dat inflating: v2ray inflating: vpoint_vmess_freedom.json # 配置 [root@dj1 work]# mv config.json config.json.bak [root@dj1 work]# vim config.json # 配置如下 { "inbounds": [ { "port": 53, // 服务器监听端口 "protocol": "vmess", "settings": { "clients": [ { "id": "0297a6ed-9152-4ad1-a80a-b248a9c4d3ad" } ] }, "streamSettings": { "network": "mkcp", //此处的 mkcp 也可写成 kcp,两种写法是起同样的效果 "kcpSettings": { "uplinkCapacity": 5, "downlinkCapacity": 100, "congestion": true, "header": { "type": "none" } } } } ], "outbounds": [ { "protocol": "freedom" } ] } # 运行v2ray,这里采用screen工具放在后台运行. [root@dj1 work]# screen -S V2 [root@dj1 work]# ./v2ray run V2Ray 5.3.0 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.20 linux/amd64) A unified platform for anti-censorship. 2023/03/17 13:02:30 Using default config: /root/work/config.json 2023/03/17 13:02:30 [Warning] V2Ray 5.3.0 started # ctrl + a + d [detached from 81853.V2]这里就配置好了,我这里用的是V2ray的VMess协议端口用的是dns的53端口关于VMess的配置文档可以在V2ray的文档中找到这里不多做解释,clients中的id算是链接的token,需要记住,这个id不能随便写,需要通过特殊的算法生成可以直接使用v2rayn来生成 这里也多做讲解。客户端链接下载方式这里不细说了,去github中的版本列表中都有。下载好之后打开软件,在左上角服务器-》添加VMess服务器中配置,配置如下地址填写自己的服务器地址,用户id这里可以直接生成,需要和服务端一样。协议选择kcp即可。配置好之后"右键左下角的v2ray的图标选择路由-》全局"。之后再设置一下代理"右键右下角图标-》系统代理-》自动配置系统代理"。连接上校园网之后就会发现不会再跳转到认证页面。实际上网的速度和服务器的网络规格挂钩。不是用校园网的时候建议关闭代理不然数据会一直走代理会出现限速的现象可以通过"右键右下角图标-》系统代理-》清除系统代理"来解决。