将epub文件转换为md文件

这是后续记录,好几个月前处理的,因此步骤可能有漏,尽量回忆

下载epub格式书籍#

https://zh.z-lib.fm/ ,网址时不时失效,需要到https://yinghezhinan.com/site/z-library/找到最新网址。注册后下载软件默认是不需要钱的,但是非会员一天只能下载10本(可以多注册几个号,只要求邮箱注册即可),正常情况下够用我这里用《吕氏春秋》这本书举例

epub编辑器#

我这里用的calibre便捷版7.19,具体谷哥一搜便有,不详细讲了(主要是太久了,怕有些细节忘了,不如不说)

编辑目录#

处理前需要先把epub文件备份一下,这里会修改源文件。

编辑书籍#

编辑处理#

一开始的目录长这样

我习惯把前面几章和后面几章都各自归为一章(下面的处理逻辑,会把每一章处理成单独的一个md文件)
随便找一个,右键编辑目录即可
然后在第一个前新建一个书名-版权-前言-目录,之后把其他二三次五级目录都删掉即可,如图:

小技巧:先全选,然后同时按住ctrl+大标题(依次取消大标题选择,然后全部删除小标题)

完毕后点击确定,然后ctrl+s保存,关闭编辑窗口

epub拆分#

现在需要把epub文件进行拆分

注意这几个地方,现在先看一下目前目录结构,点击书籍文件,然后查看他的上级目录,目前只有一本

回到calibre软件,选中书籍,点击Epub拆分功能,ctrl+a全选章节,然后点击每个章节一本书,这里就会多出27本
现在我们再查看刚才的D:\software\calibre\Calibre Portable\Calibre Library\Lu Jiu目录除了一本书原书,其他都是新拆分出来的

拆分后的epub转换成txtZ格式#

选中拆分后的27个文件

转换书籍–>输出格式txtZ(其他设置默认)
随便点一本书的文件夹进去看,会发现多了一个txtZ文件
可以复制一份.txtZ文件,之后改成.zip,会发现就是txt文件+image图片的文件堆了(为了不影响脚本功能,记得删除这里的.zip文件)

shell-批量将txtZ转换成md#

我写了个shell脚本处理epub转md文件,由于个人使用,没有太过讲究,所以有一些限制,建议在linux环境下运行,当然,我是在windows10+cmder下运行该脚本的。脚本内容如下:

脚本#

n=$#
if [ $n -ne 2 ] ; then
   echo -e "Please set the dir(source)(book目录) dir(dest)(md目录). "
   exit 0
fi

#待处理的txtz文件目录
bookDir=$1;
dirMd=$2; 

initDirMd(){
fileName="$1/_index.md" 
cat >> $fileName <<-_EOF_
---
bookCollapseSection: true
title:
---
_EOF_
# echo "创建$fileName成功"
}
initContentMd(){
fileName="$1/index.md"
time=`date '+%Y-%m-%dT%H:%M:%S%:z'`
cat >> $fileName <<-_EOF_
---
title: 
description: 
categories:
  - 学习
tags: 
  - MySQL
  - MySQL是怎样运行的
cssAttach: 
  - book01
cssclasses: 
  - book01
date: $time
lastmod: $time
---
_EOF_
# echo "创建$fileName成功"
}

#遍历books目录并在相应位置创建目录
iterateBooks(){

	local dirBook=$1;
	local dirMd=$2;
	local files=$(ls "$dirBook")
	#echo "$files"
	#临时修改SHELL中的分隔符
	oldIFS=$IFS
	IFS=$'\n'
	initDirMd "$dirMd"
	for file in $files; do
		local fullPathFile="$dirBook/$file";
		if [[ -d $fullPathFile ]]; then
			# echo $file 
			#如果是目录则在目录创建对应的目录
			mkdir -p "$dirMd/$file" 
			initContentMd "$dirMd/$file" 
			#处理目录下文件
			handleDir "$fullPathFile" "$dirMd/$file"
		fi
	done
	IFS=$oldIFS
}

#处理目录下的文件
handleDir(){ 
	local dirBook=$1;
	local dirMd=$2;
	local files=$(ls "$dirBook")
	#echo "$files"
	#临时修改SHELL中的分隔符
	oldIFS=$IFS
	IFS=$'\n'
	for file in $files; do
		#如果是.txtz结尾
		if [[ $(expr "$file" : ".\+\.txtz$") > 0 ]]; then
			local fullPathFile="$dirBook/$file";
			cp -r "$fullPathFile" "$fullPathFile.zip"
		    echo "$fullPathFile"
			unzip -qo  "$fullPathFile" -d $dirBook
			rm "$fullPathFile.zip"

			#处理解压后的文件
			#sed -Ei "s/^##(.*?\s)/\1/g" index.txt 
			# sed不支持PCRE
			# \\\\\[用来取 \[ 
			#sed -Ei "s/\\\\\[([0-9]+)\\\\\]/[\1]/g"  index.txt 

			#替换图片地址
			# 这里-i -pe 一个不能去掉,且顺序不能改。且p去掉没效果,不知道原因
			# perl命令行加上"-e"选项,就能在perl命令行中直接写perl表达式
			# -i:对输入的每一行执行一次代码,并进行原地编辑(覆盖原文件)
			# -p:对输入的每一行执行一次Perl代码,并打印输出结果。 
			# g是全局,p:保存匹配的字符串到${^PREMATCH} ${^MATCH} ${^POSTMATCH}中,它们在结果上对应$` $& $'
			perl -i -pe 's/(\!\[.*?\])\(images/$1\(img/gp' "$dirBook/index.txt"
			#perl中$&表示整个字符串
			# perl -i -pe 's/(\!\[.*?\])\(img.*?\)/$&  \n/gp' "$dirBook/index.txt"
			#替换\(\) \[\]之类的默认转义(不需要)
			perl -i -pe 's/\\\[(.*?)\\\]/\[$1\]/gp' "$dirBook/index.txt"
			perl -i -pe 's/\\\((.*?)\\\)/\($1\)/gp' "$dirBook/index.txt"
			# 反引号`,星号*,下划线_
			perl -i -pe 's/\\`/`/gp' "$dirBook/index.txt"
			perl -i -pe 's/\\\*/\*/gp' "$dirBook/index.txt"
			perl -i -pe 's/\\_/_/gp' "$dirBook/index.txt"
			#标题降1级(#\s+)\*{2}(.*?)\*{4}
			perl -i -pe 's/^#(.*?\s)/$1/gp' "$dirBook/index.txt" 

			#去除#号后面4个星号(#\s+)(.*?)\s*\n\*{4}\s*\n\*{2}(.*)
			#perl -i -0 -pe 's/(#\s+)\*{2}(.*?)\*{4}.*\n\*{4}.*\n\*{2}(.*)\n.*\n/$1$2 $3/gp' "$dirBook/index.txt" 
			


			#去除#后面连续的4个星号
			#perl -i -pe 's/^(#.*?\s)\*{4}/$1/gp' "$dirBook/index.txt" 
			#去除#号后面4个星号(#\s+)\*{2}(.*?)\*{4}
			#perl -i -pe 's/(#\s+)\*{2}(.*?)\*{4}/$1$2/gp' "$dirBook/index.txt"
			#处理img图片
			# sed -Ei "s/(\!\[\.*?\])\(images/\1\(img/g"  "$dirBook/index.txt"
			#替换\(\) \[\]之类的默认转义(不需要)
			# sed -Ei "s/\\\\\[/[/g"  "$dirBook/index.txt"
			# sed -Ei "s/\\\\\]/]/g"  "$dirBook/index.txt"
			# sed -Ei "s/\\\\\(/(/g"  "$dirBook/index.txt"
			# sed -Ei "s/\\\\\)/)/g"  "$dirBook/index.txt"			
			#去除#后面连续的4个星号
			# sed -Ei "s/\*{4}//g"  "$dirBook/index.txt"
			# sed -Ei "s/\\\\\[(.*?)\\\\\]/[\1]/g"  "$dirBook/index.txt"
			# sed -Ei "s/\\\\\((.*?)\\\\\)/(\1)/g"  "$dirBook/index.txt"			
			#标题降1级
			# sed -Ei  "s/^#(.*?\s)/\1/g"  "$dirBook/index.txt"
			mkdir -p "$dirMd/img" 
			cp -r "$dirBook"/images/* "$dirMd/img"
			rm -rf "$dirBook"/images
			echo -ne "\n" >>  "$dirMd/index.md"
			# echo "23" >>  "$dirMd/index.md"
			cat "$dirBook/index.txt" >>  "$dirMd/index.md"
			rm -rf "$dirBook"/index.txt
		fi
	done
	IFS=$oldIFS

}
iterateBooks "$bookDir" "$dirMd"
# handleDir "$bookDir" "$dirMd"

将脚本放在某个目录下(随意)

01-04设置cpp

WelcomeToCpp#

  • 使用c++可以控制CPU应该执行的每条指令
  • C++的代码编译后可以在任何平台运行,前提是有一个为对应平台生成机器代码的编译器
  • 与C++不同,C#或JAVA,他们在虚拟机中运行,运行时将代码从“中间语言”转换为机器代码
  • 学习新事物的关键就是对事物进行实验
  • 将讨论如何利用C++库
  • C++实际上如何工作
  • 关于内存和指针:内存区域,智能指针,移动语义,模板
  • 宏,以及为多个平台编程
  • 编写自己的数据结构,学习如何使他们比C++标准库中的结构更快
  • 低级优化,与编译器和汇编相关

设置C++#

windows平台#

  1. 需要文本编辑器,将C++代码编写为文本文件,传递给编译器以生成某种可执行二进制文件,以便可以运行

  2. 或者跳过1,直接用IDE,即有一套帮助你编写和调试代码的工具。(Visual Studio,视频用的2017,我这里下载的 Visual Studio Community 2022)

  3. 安装勾选:

  4. 新建项目

    不要勾选 Place solution and project in the same directory

    解决方案,solution,是一组相互关联的项目,他们有各种项目类型,解决方案就像工作台,每个项目本质上是一组文件,会编译成目标二进制文件(无论是库还是实际的可执行文件)

  5. 添加新项

  6. 代码文件(Main.cpp)

#include <iostream>
int main() {
	std::cout << "hello world!" << std::endl;
	std::cin.get();
}

配置文件修改#

下载ChernoVS.vssettings文件,并放到下面的位置
C:\Users\ly\AppData\Local\Microsoft\VisualStudio\17.0_f89cedea\Settings

在vs工具栏中-tools-ImportAndExportSettings-

ImportSelectedEnvironmentSettings

选择no,just Import new,选择 ChernoVS.vssetings即可

运行#

  1. 右键,构建(项目)


    文件系统查看:

  2. 双击.exe文件,结果:


    按任意键终止


或者单机本地的Windows调试器来运行它

154【杂项】算竞常用_C++_STL_用法

C++ 标准模板库 (STL, Standard Template Library):包含一些常用数据结构与算法的模板的 C++ 软件库。其包含四个组件——算法 (Algorithms)、容器 (Containers)、仿函数 (Functors)、迭代器 (Iterators).

示例:

  • 算法:sort(a.begin(), a.end())
  • 容器:priority_queue<int> pque
  • 仿函数:greater<int>()
  • 迭代器:vector<int>::iterator it = a.begin()

1 前言#

STL 作为一个封装良好,性能合格的 C++ 标准库,在算法竞赛中运用极其常见。灵活且正确使用 STL 可以节省非常多解题时间,这一点不仅是由于可以直接调用,还是因为它封装良好,可以让代码的可读性变高,解题思路更清晰,调试过程 往往 更顺利。

不过 STL 毕竟使用了很多复杂的结构来实现丰富的功能,它的效率往往是比不上自己手搓针对特定题目的数据结构与算法的。因此,STL 的使用相当于使用更长的运行时间换取更高的编程效率。因此,在实际比赛中要权衡 STL 的利弊,不过这一点就得靠经验了。

接下来,我会分享在算法竞赛中常用的 STL 容器和算法,对于函数和迭代器,就不着重展开讲了。

2 常用容器#

2.1 内容总览#

打勾的是本次将会详细讲解的,加粗的是算法竞赛中有必要学习的。

  • 顺序容器

    • array

    • vector

    • deque

    • forward_list

    • list

  • 关联容器

    • set
    • map
    • multiset
    • multimap
  • 无序关联容器

    • unordered_set
    • unordered_map
    • unordered_multiset
    • unordered_multimap
  • 容器适配器

qt学习

建议版本#

  • Qt 4.8.7 官方推荐的 MinGW 版本为 4.4.x,但是MinGW4.4没法编译,MinGW4.5才行,然后找不到MinGW4.5,这里使用了MinGW4.8。qtCreator配套推荐3.0.1(也可以用3.5.0)

下载(视频所用版本)#

- perl-->  https://strawberryperl.com/download/5.16.3.1/strawberry-perl-5.16.3.1-32bit-portable.zip
- MinGW(4.8.1): https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.8.1/threads-posix/sjlj/i686-4.8.1-release-posix-sjlj-rt_v3-rev2.7z/download (兼容windowsXP)
- (推荐)https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.8.2/threads-posix/dwarf/ (新版win7以上)
=====qt 4.8.7========
- qt库(带MinGW和qtCreator) :https://download.qt.io/new_archive/qt/4.8/4.8.7/qt-opensource-windows-x86-mingw482-4.8.7.exe
- qt库(源码): https://download.qt.io/new_archive/qt/4.8/4.8.7/qt-everywhere-opensource-src-4.8.7.zip
- qtCreator: https://qt.mirror.constant.com/archive/qtcreator/3.0/3.0.1/qt-creator-opensource-windows-x86-3.0.1.exe
===弃用===
- MinGW(4.4): https://www.123912.com/s/u5pSjv-32uAH?提取码:M27Z  
	- 要记得设置环境变量
- qt库: https://download.qt.io/archive/qt/4.7/qt-win-opensource-4.7.0-mingw.exe  
- Qt Creator: https://download.qt.io/archive/qtcreator/2.0/qt-creator-win-opensource-2.0.1.exe  
====使用5.0.2====
qt+mingw--> https://download.qt.io/archive/qt/5.0/5.0.2/qt-windows-opensource-5.0.2-mingw47_32-x86-offline.exe
源码-->  https://download.qt.io/archive/qt/5.0/5.0.2/single/qt-everywhere-opensource-src-5.0.2.zip
=====在线版5.15======
https://mirrors.tuna.tsinghua.edu.cn/qt/official_releases/online_installers/qt-online-installer-windows-x64-online.exe
- .\qt-online-installer-windows-x64-online.exe  --mirror https://mirrors.ustc.edu.cn/qtproject 
- Archive中选择5.15及6.8
- 安装内容:MinGW,Android,QtCharts,QtMultimedia,QtQuich3D,QtShaderTools
=====其他=======
- qt库(带MinGW和qtCreator): https://download.qt.io/new_archive/qt/5.2/5.2.1/qt-opensource-windows-x86-mingw48_opengl-5.2.1.exe

编译静态编译的qmake#

  • 下载源码
  • 路径不能有奇奇怪怪的符号(.-_ 之类)
  • (弃)修改 E:\Qt\qtSrc\qtbase\mkspecs\win32-g++\qmake.conf,修改QMAKE_LFLAGS = -static -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc(仅添加-static)

目录结构#

#mkdir "E:\Qt\qtCustom487\buildQtStatic" #/p
mkdir "E:\Qt\qtCustom\buildQtStatic" #/p
#mkdir "E:\Qt\qtCustom487\qtStatic" #/p
mkdir "E:\Qt\qtCustom\qtStatic" 
#mkdir "E:\Qt\qtCustom487\qtSrc" #/p
mkdir "E:\Qt\qtCustom\qtSrc"  
#E:\Qt\qtCustom下
				- buildQtStatic #(新建的)编译时切换到这个目录
				- qtSrc #源码
				- qtStatic #(新建的)install目录

静态编译#

我用的是视频0087集的办法,也可以用 https://www.cnblogs.com/atggg/p/16878575.html试试

平板安装linuxDeploy的问题简记

关于系统服务#

ly@tabs8:~$ ls -l /etc/systemd/system/sshd.service
lrwxrwxrwx. 1 root root 31 Apr  3 14:16 /etc/systemd/system/sshd.service(用户自定义service存放地址) -> /lib/systemd/system/ssh.service(系统安装软件后的service存放地址)

但是sudo service hello status,chroot容器中查找的只是/etc/init.d/这个路径下的hello(不查找/etc/systemd和lib/systemd中的),但是如果使用systemctl disable hello,则/etc/init.d中的hello服务不会被运行,并且会删除/etc/systemd/system/multi-user.target.wants文件夹下的软连接。如果systemctl enable hello,则会在/etc/systemd/system/multi-user.target.wants文件夹下生成一个软连接。
执行完/etc/init.d/hello就不会再操作其他东西了(hello.service没有用)

建议linuxdeploy的自动化开启Sysv模式,然后在/etc/init.d/里头编写脚本就可以了,如果要开机启动,使用systemctl enable xxx即可。

问题1#

chroot容器中,sudo systemctl enable hello.service后,开机启动时并没有执行。但是如果服务名hello在/etc/init.d/文件中存在对应名的SysV Init 脚本,就会执行,这是为什么呢

在普通 chroot 中,SysV Init 脚本能执行是因为其不依赖 PID 1 管理器,而 systemd 服务需要完整的初始化环境。若需 systemd 功能,应优先使用 systemd-nspawn。

问题2 ★#

chroot容器中,默认情况下,系统启动时会执行/etc/init.d/hello脚本(SysV Init 脚本),但是如果sudo systemctl disable hello.service后,开机启动时就不会执行了,这是为什么呢

 Debian 12(即使使用 systemd)默认保留了 SysV Init 兼容性,通过systemd-sysv-generator 工具动态生成 .service 文件来管理 /etc/init.d/ 中的脚本。当执行 systemctl disable hello.service 时:①删除符号链接:会移除 /etc/systemd/system/<target>.wants/ 中指向自动生成的 hello.service 的符号链接(如 multi-user.target.wants/hello.service)。②禁用服务:即使 /etc/init.d/hello 存在,systemd 也不会在开机时触发其执行,因为兼容层已被禁用。

systemctl enable#

ly@tabs8:~$ sudo systemctl disable ssh
Synchronizing state of ssh.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install disable ssh
Removed "/etc/systemd/system/multi-user.target.wants/ssh.service".
Removed "/etc/systemd/system/sshd.service".
#=================================
ly@tabs8:~$ ls -l /etc/systemd/system/multi-user.target.wants | grep ssh
ly@tabs8:~$ ls -l /etc/systemd/system/ | grep ssh
#================开机自启动========
ly@tabs8:~$ sudo systemctl enable ssh
Synchronizing state of ssh.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable ssh
#创建了两个符号链接
#保证兼容性,十几年前一直是用sshd
Created symlink /etc/systemd/system/sshd.service → /lib/systemd/system/ssh.service.
#multi-user.target.wants下: 开机自启动
Created symlink /etc/systemd/system/multi-user.target.wants/ssh.service → /lib/systemd/system/ssh.service.
#开机自启动其实是直接链接到系统(软件)自己的service
ly@tabs8:~$ ls -l /etc/systemd/system/multi-user.target.wants | grep ssh
lrwxrwxrwx. 1 root root 31 Apr  3 15:05 ssh.service -> /lib/systemd/system/ssh.service
ly@tabs8:~$ ls -l /etc/systemd/system/ | grep ssh
lrwxrwxrwx. 1 root root   31 Apr  3 15:05 sshd.service -> /lib/systemd/system/ssh.service

#====总的来说,我只要在/etc/systemd/system/下创建自己的服务S,然后systemctl enable S即可

service编写(这里没用上)#

vim /etc/systemd/system/vncser

[Unit]
Description=TigerVncService  # 服务描述
After=network.target          # 定义启动顺序(在网络就绪后启动)

[Service]
Type=simple                  # 服务类型(simple/forking/oneshot等)
ExecStart=/usr/local/bin/tigervnc.sh    # 启动命令(绝对路径)
Restart=on-failure           # 失败时自动重启
User=ly                  # 运行用户(可选)
#Group=nogroup                # 运行组(可选)
#WorkingDirectory=/path/to    # 工作目录(可选)

[Install]
WantedBy=multi-user.target   # 定义服务所属的“目标”(开机自启)

一些命令暂记#

#镜像下载 https://mirrors-i.tuna.tsinghua.edu.cn/lxc-images/images/debian/bookworm/arm64/
#发行版 [rootfs.tar]
#源地址 ${EXTERNAL_STORAGE}/linuxdeploy/bookworm.tar.xz

#=====!!!!安装类型[ 目录]会有一些问题,比如ssh提示权限过高,不太懂..=======
#安装路径[ ${ENV_DIR}/rootfs/bookworm ] --> [ /data/data/ru.meefik.linuxdeploy/files/rootfs/bookworm ]----安装类型[ 目录]
#安装路径[ /data/media/0/linuxdeploy/bookworm ]----安装类型[ 目录] 
#建议放镜像
#安装路径{EXTERNAL_STORAGE}/linuxdeploy/bookworm.img----安装类型[ 镜像文件]

#用户名--用户密码--特权用户--本地化--DNS--networktrigger--powertrigger--随便弃用
#(弃用)初始化-启用-run-parts--路径/etc/rc.local--初始用户root
#!!!!初始化我这里使用sysv,通过systemctl enable ssh可以让ssh开机自启动,但是systemctl start ssh不能使用,需要用service ssh start替代
#挂载目录--挂载点--source使用/data/media/0 (data开头的,android14中其他的好像都不行不知道为什么,给ly加了 aid_media_rw  这个组权限) sudo usermod -aG  aid_media_rw username
#其他都不需要

#设置 telnet守护模式打开

挂载目录说明#

为了统一,可以用/mnt/pass_through/0/emulated/0/(内置存储卡) 以及/mnt/pass_through/0/822C-9525/(外置存储卡)

05日志

undolog#

作用#

  1. 恢复某条记录原始状态
  2. 记录修改过程,MVCC的原理,结合事务id知道哪些数据可见 undo log的修改本身会被记录到redo log中。即使undo log未刷盘,崩溃恢复时也可以通过redo log重建undo log。

redolog#

  1. 数据持久性–事务提交后,buffer pool一些脏页没有写入数据库磁盘文件。重启时,利用redolog恢复(表空间、页号、偏移量、数值)的数据(磁盘数据)
  2. 由于redolog有几种策略时机刷入磁盘。另有额外线程每隔1s不断刷入redolog buffer pool数据到redolog磁盘日志文件中,如果事务未提交但是刷入了redolog日志文件也无妨。可以根据一些标识,找到哪个事务是未提交的,然后再用undolog恢复原始状态。
root@db211:/var/lib/mysql# ls
auto.cnf	 ibdata1	     public_key.pem
ca-key.pem	 ib_logfile0 (redolog)	     server-cert.pem
ca.pem		 ib_logfile1 (redolog)		 server-key.pem
client-cert.pem  ibtmp1		     sys
client-key.pem	 mysql		     test
db211-slow.log	 performance_schema  xx
ib_buffer_pool 	 private_key.pem

update语句执行流程#

流程#

  1. 事务开始
    1. 写Undo Log到Undo Log Buffer(记录旧值)
    2. 修改Buffer Pool中的数据页(生成脏页)
    3. 写Redo Log到Redo Log Buffer(记录物理变更) 修改BufferPool后,还会MySQL还会生成对应的Binlog 事件逻辑操作记录),先写入线程的私有内存缓冲区(Binlog Cache
  2. 事务提交
    1. Redo Log 标记为 Prepare
    2. 写Binlog并刷盘
    3. Redo Log Commit阶段(标记提交)

redolog的刷盘策略#

  1. Redo Log Buffer 空间不足:当 Redo Log Buffer 的写入速度超过刷盘速度时,InnoDB 会强制刷盘以释放空间。
  2. 后台线程定期刷盘:InnoDB 的后台线程(如 log_writer 和 log_flusher)会周期性刷盘(默认每秒一次,由 innodb_flush_log_at_timeout 控制)。
  3. 参数配置触发
    1. 0:设置为 0 的时候,表示每次事务提交时不进行刷盘操作。这种方式性能最高,但是也最不安全,因为如果 MySQL 挂了或宕机了,可能会丢失最近 1 秒内的事务。
    2. 1:设置为 1 的时候,表示每次事务提交时都将进行刷盘操作。这种方式性能最低,但是也最安全,因为只要事务提交成功,redo log 记录就一定在磁盘里,不会有任何数据丢失。
    3. 2:设置为 2 的时候,表示每次事务提交时都只把 log buffer 里的 redo log 内容写入 page cache(文件系统缓存)。page cache 是专门用来缓存文件的,这里被缓存的文件就是 redo log 文件。这种方式的性能和安全性都介于前两者中间。

这里其实有个疑问,就是redolog并不是事务提交后才刷盘的,而是很有可能事务提交前就刷盘了。如果提交前刷盘了,之后系统宕机了,那么redolog磁盘文件就多出了一些未提交事务的日志。解决办法:可以通过一些属性,在undolog中找到未提交事务的id,然后通过undolog回滚未提交事务。

04事务

关闭自动提交#

在MySQL命令行的默认设置下,事务都是自动提交的,即执行SQL语句后就会马上执行COMMIT操作。因此开始一个事务,必须使用BEGIN、START TRANSACTION,(显示开启事务)或者执行SET AUTOCOMMIT=0,以禁用当前会话的自动提交。

  1. select语句一般用来输出用户变量,比如select @变量名,用于输出数据源不是表格的数据。
  2. 系统变量在变量名前面有两个@
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)

mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.00 sec)
# 修改变量
set autocommit=0;

本文中autocommit=0,开始事务需要使用begin显式开启

事务并发存在的问题#

没有脏读问题,如果两个事务同时修改一条数据,那么另一个事务的修改操作会被阻塞
【隔离性】脏读(读到了还没有提交的数据)

【隔离性】不可重复读(同一事务中,第1次读的数据和第2次读的数据不一样。读到了事务操作过程中其他事务提交的数据,也不应该,这个没法保证一致性。比如我第一次根据某个事务做了一个操作,第二次想同样的逻辑做一个判断操作,但是数据变了,导致同一个事务中对同一个(其实不是了)数据做的操作居然不一致

【隔离性】虚读、幻读(同一事务中:我第一次读到某一条数据,但是第二次没读到;或者第一次没读到,第二次居然读到了。条数问题)

事务的隔离级别#

READ_UNCOMMITTED 读未提交
READ_COMMITTED 读已提交
REPEATABLE_READ 重复读 SERIALIZABLE 串行化(行锁) 修改事务隔离级别:

set tx_isolation='SERIALIZABLE'; (可以加global,让新开的session也使用该事务隔离级别)

经测试,如果有三个session(mysql客户端),其中一个(a)是SERIALIZABLE,而其他两个(b,c)是READ_UNCOMMITTED,那么客户端b,c之间不会因为锁挂起,而ab或ac会导致(行)锁挂起

REPEATABLE_READ重复读#

REPEATABLE_READ重复读的隔离级别只能在一定程度上防止幻读 如果事务a(插入一条新数据,或者删除一条数据)后提交。那么变动的数据不会在事务b被查出来。但是如果插入的这条数据(在事务b,注意 不是事务a)被修改了,那么之后它会在事务b被查出来

新增后修改#

事务a新增数据后提交,在事务b执行中修改了该数据,则该数据会显示出来(影响了)

#=======事务b=======
mysql> begin;
mysql> select * from user;
+----+-----+
| id | age |
+----+-----+
|  1 |  10 |
|  2 |  20 |
|  3 |  33 |
+----+-----+
#=======事务a=======
mysql> insert into user(age) values(44);
#=======事务b=======
mysql> select * from user;
+----+-----+
| id | age |
+----+-----+
|  1 |  10 |
|  2 |  20 |
|  3 |  33 |
+----+-----+
#=======事务a=======
mysql> update user set age=55 where id = 4;
#=======事务b=======
mysql> select * from user;
+----+-----+
| id | age |
+----+-----+
|  1 |  10 |
|  2 |  20 |
|  3 |  33 |
+----+-----+
#=======事务b=======
mysql> update user set age=55 where id = 4;
mysql> select * from user;
+----+-----+
| id | age |
+----+-----+
|  1 |  10 |
|  2 |  20 |
|  3 |  33 |
|  4 |  55 |
+----+-----+
##此时如果事务a进行 delete from user where id = 4; 那么事务a会阻塞,直到事务b commit

删除后修改#

事务a删除数据后提交,在事务b执行中修改了该数据,该数据也照样存在(不影响)

03存储引擎

表结构、数据、索引

文件目录#

 root@db211:/var/lib/mysql/mysql# ls | tail -16
tables_priv.frm
tables_priv.MYD
tables_priv.MYI
time_zone.frm
time_zone.ibd
time_zone_leap_second.frm
time_zone_leap_second.ibd
time_zone_name.frm
time_zone_name.ibd
time_zone_transition.frm
time_zone_transition.ibd
time_zone_transition_type.frm   #INNODB存储引擎-表结构
time_zone_transition_type.ibd   #INNODB存储引擎-表数据+表索引(包括所有索引)
user.frm   #MyISAM存储引擎-表结构
user.MYD   #MyISAM存储引擎-表数据
user.MYI   #MyISAM存储引擎-表索引

INNODE存储引擎的表主键聚簇索引和数据在同一个文件(所以即使没有设置主键,innodb也会为每一行自动生成一个默认的隐藏主键列,用来形成B+树)

索引#

索引创建#

建表时创建#

create table index1( id int, name varchar(20), index idx_id_name (id,name));

后续添加#

create index idx_name on bank_bill (name);

B树#

m阶B树 ,m个分支(或者说m个区间)
x个元素就会有x+1个区间

B+树和B树区别#

从B树考虑#

log2 2000万≈24.3 log500 2000万≈3 (m阶平衡树) 如果是500阶B树,那么2000万个节点最多只需要3层

从B+树考虑#

MySQL中,一个节点1页,也就是16KB(可以改),而一个节点可以放(主键bigint(8字节)+页号地址 6字节)单元1170个,假设是1000,那两层可以放100 0000万个节点。由于1个节点16KB,如果一条数据用1KB的话,那么最底层每个叶子节点就是放16条数据。那就是3层可以放1600万条数据。这是估算,细算的话应该是2000万左右

其他#

操作系统内存管理按页面4K为单位。MySQL默认使用InnoDB存储引擎,其数据块大小(block size)一般默认为16KB

using index#

mysql> explain select name from student where name = 'liuxiang' \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: student
   partitions: NULL
         type: ref
possible_keys: idx_name
          key: idx_name
      key_len: 152
          ref: const
         rows: 1
     filtered: 100.00
        Extra: Using index (直接在二级索引搜索就结束了)

下面这个还需要回表

02增删改查

分类#

  • DDL 数据定义语言(create,drop,alter)
  • DML 数据操纵语言(insert,delete,update,select)
  • DCL 数据控制语言(grant,revoke)

删除#

mysql> select * from user;
+----+----------+-----+-----+
| id | name     | age | sex |
+----+----------+-----+-----+
|  1 | zhangsan |  20 | M   |
|  2 | wuqi     |  34 | M   |
|  5 | baobaoi  |  45 | W   |
|  6 | lalal    |  44 | W   |
+----+----------+-----+-----+
4 rows in set (0.00 sec)
mysql> delete from user where id = 6
#如果之后重启了mysql(且id最大为5,则再插入的数据id为6),(如果id最大为10,则插入的数据id为11);如果没有重启,则再插入的数据id为7
mysql> nsert into user(name,age,sex) values('hah',35,'W');

新增#

一次新增多条数据和多次新增单条数据区别

搜索#

limit可以优化sql语句,不过要看数据的位置

mysql> select * from t_user  limit 1999999 ,1;
+---------+------------------+------------+
| id      | email            | password   |
+---------+------------------+------------+
| 2000000 | cwng78@yahoo.com | h4HcxZKBNQ |
+---------+------------------+------------+
1 row in set (0.52 sec)
#这条数据在最后一条,所以优化效果不怎么样
mysql> select * from t_user where email='cwng78@yahoo.com';
+---------+------------------+------------+
| id      | email            | password   |
+---------+------------------+------------+
| 2000000 | cwng78@yahoo.com | h4HcxZKBNQ |
+---------+------------------+------------+
1 row in set (0.47 sec)

在第一条或者前面,则优化效果显著

01基础知识

本课程大纲#

部分扩展知识#

MySQL分为服务端和客户端(两进程),SQLite是进程程序,客户端和服务端都在同一个进程操作数据

安装(windows)#

安装目录下包括数据目录(Data/)和配置文件(my.ini)

安装(debian)#

数据目录#

root@db211:/etc/mysql# ls -l /var/lib/mysql | awk '{print $1,$3,$4,$9}'
total   
-rw-r----- mysql mysql auto.cnf
-rw------- mysql mysql ca-key.pem
-rw-r--r-- mysql mysql ca.pem
-rw-r--r-- mysql mysql client-cert.pem
-rw------- mysql mysql client-key.pem
-rw-r----- mysql mysql ib_buffer_pool
-rw-r----- mysql mysql ibdata1
-rw-r----- mysql mysql ib_logfile0
-rw-r----- mysql mysql ib_logfile1
-rw-r----- mysql mysql ibtmp1
drwxr-x--- mysql mysql mysql
drwxr-x--- mysql mysql performance_schema
-rw------- mysql mysql private_key.pem
-rw-r--r-- mysql mysql public_key.pem
-rw-r--r-- mysql mysql server-cert.pem
-rw------- mysql mysql server-key.pem
drwxr-x--- mysql mysql sys
drwxr-x--- mysql mysql xx

配置目录#

root@db211:/etc/mysql# ls -l | awk '{print $1,$9,$10,$11}'
total   
drwxr-xr-x conf.d  
lrwxrwxrwx my.cnf -> /etc/alternatives/my.cnf
-rw-r--r-- my.cnf.fallback  
-rw-r--r-- mysql.cnf  
drwxr-xr-x mysql.conf.d

再进一步查看