0x318 - 0x318
type: channel
link: https://blog.0x318.com/author/1/
description: 0x318
items: 区块链交易入门
items: 打造炫酷的终端
items: 记录一下自己买的币
items: 挖掘以太坊
items: 加密货币交易
items: QQ聊天机器人搭建
items: 简单实现图片去重
items: Go协程
items: Mysql索引
items: Mysql事务和MVCC

区块链交易入门
type: item
date: 2022-06-16T03:07:27+00:00
description: 区块链交易入门远离区块链骗局,与其亏钱伤心,不如打钱给我, 至少我还会说一声谢谢交易所1. 中心化交易所交易所 a. 币安 (交易人数最多的交易所) b. okx (目前可以直接入金的交易所) c. coinbase (美国人玩的交易所) d. ftx (手续费最低的交易所) 2. 去中心化交易所 a. uniswap(以太链) b. pancakeswap(币安链) Gas1. Gas(汽油费) Gas最初是在以太坊区块链上实现的，用于衡量消息消耗的计算和存储资源。也就是钱包与钱包交互时产生的计算费用 2. 用户可以用更多的Gas来让自己的交易可以更快的被矿工打包 3. 由此可以使用出三明治攻击的玩法, 即在链上的交易对中监控大单以比大单更高的Gas提前完成交易, 之后再卖出来赚取差价 入金入金是将法币在中心化交易所转换为链上资产的行为 入金方法分为线上和线下两种 1. 中心化交易所入金 a. KYC (中国大陆清退政策) b. 提币手续费 (按链划分 以太链最贵) 2. 线下入金 (不安全)目前可以直接入金的交易所只有OKX (支持支付宝, 微信,银行卡 )ERC-201. 支付的手续费种类为ETH 2. ERC-USDT与其他以太坊上的Token一样，存储在以太坊地址上，因此每次转账的时候，需要支付的手续费种类为ETH。地址示例：0xdac17f958d2ee523a2206206994597c13d831ec7 (ERC-20合约) 3. Gas费用高,当消息出现拥堵的时候Gas费用会水涨船高 BSC1.BEP-20是ERC-20的扩展，ERC-20是以太坊区块链上最流行的令牌标准。 同样，BEP-20是Binance平台智能链上的令牌标准。 2. Gas费用低 TRC-201. TRC-20是用于TRON区块链上的智能合约的技术标准，用于使用TRON虚拟机实施代币。 它与 ERC-20完全兼容。 2. 在波场上转账USDT是不收手续费的，但在交易所提现TRC-USDT还是会收提现手续费的(由交易所收取)。地址示例：TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t (TRC-20合约) 如何避免交易所高昂提币手续费方法1:1. 确认FTX交易所是否有你想提现的交易对(没有的话就放弃吧) 2. OKX交易所入金USDT 3. 将USDT提币到 FTX 交易所 4. 在FTX交易所将USDT兑换为你想要的币种 5. 提币到钱包 方法2:1. 交易所入金 2. 提币到FTX交易所 3. 在交易所将USDT兑换为ETH 4. 提币到钱包 5. 在Uniswap上去兑换你想要的币 注意GAS费用

打造炫酷的终端
type: item
date: 2022-01-05T09:14:00+00:00
description: iTerm2+omz+p10k打造炫酷的终端前言代码可以写的烂, 工具必须要好看!!效果图准备工作iTerm2 Mac上最强的终端工具 官网oh my zsh 用于管理Zsh配置的框架 官网powerlevel10k 是Zsh的一款主题 官网开始1.下载iTerm2 前往官网下载2. 安装Oh my zsh 通过官网给 curl 或 wget 下载安装sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"sh -c "$(wget https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"3. 安装powerlevel10k克隆项目到omz的外置主题目录下git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k在 ~/.zshrc 中设置主题ZSH_THEME="powerlevel10k/powerlevel10k" 4. 安装语法高亮插件和自动补全插件语法高亮插件git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting自动补全插件git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions在 ~/.zshrc 中添加插件plugins=( [plugins...] 其他插件 zsh-syntax-highlighting zsh-syntax-highlighting )4.使配置生效 source ~/.zshrc5. 安装字体git clone https://hub.fastgit.org/possible318/p10k-font.git6. 设置iTerm2的字体7. 运行p10k configure 按照提示选择想要的效果enjoy !!!

记录一下自己买的币
type: item
date: 2021-10-21T03:55:00+00:00
description: 远离区块链骗局时间价值2021-11-302021-11-292021-11-282021-11-272021-11-262021-11-252021-11-242021-11-232021-11-212021-11-202021-11-192021-11-182021-11-172021-11-162021-11-152021-11-142021-11-132021-11-122021-11-112021-11-102021-11-092021-11-082021-11-072021-11-052021-11-042021-11-032021-11-022021-10-012021-10-312021-10-302021-10-292021-10-282021-10-272021-10-262021-10-252021-10-222021-10-212021-10-202021-10-192021-10-18

挖掘以太坊
type: item
date: 2021-10-21T02:59:00+00:00
description: 挖掘以太坊Ethereum(中文名 以太坊, 缩写 ETH)使用 Ethash 算法来挖掘, 这种算法是一种内存密集型算法, 内存吞吐量越高计算越快. 显卡所用的显存比需要通过数据总线来传输数据的主板内存快得多, 因此以太坊主要使用显卡来挖掘, CPU 挖掘的速度低至忽略不计.Ethash 算法会把已有的区块的加密信息放在显存中继而计算下一区块. 由于以太坊支持 uncle block, 因此这些数据甚至不是链而是有向无环图(DAG). 这个 DAG 会以每年大约 520MiB 的速度增大, 在目前(2021 年 3 月)已经达到了 4.2GiB, 如果你的显卡显存没有超过 4.2GiB 将挖不了以太坊.DAG 占用的内存每年逐渐增大, 因此 ASIC 矿机挖掘以太坊的效益并不是那么高. 通常 ASIC 的内存都不是那么快(相比显卡所用的 DDR6), 并且没有那么大, 所以矿老板并不是非常乐意挖以太坊, 这也就意味着业余加密货币爱好者用自己的显卡挖以太坊也可以有相对比较好的收益(相较于比特币).有不少 ETH 挖矿程序并不开源, 无法得知其内部是否有恶意代码窃取用户电脑上的数据, 业余加密货币爱好者一般不会有多台高性能电脑, 挖矿用的电脑就是平时所用的电脑, 因此使用一款安全的挖矿程序格外重要. 甚至有很多闭源程序或补丁会标榜自己能够 "优化" 算法, 使相同的硬件运行得到更高的 HashRate, 实际上 Ethash 核心算法是开源的, 而且早已优化到不能再优化, 那些程序只不过是给使用者的显存超频而已. 显存超频之后会提高硬件出错率, 加速元件老化, 也会导致原本风道设计合理的机箱变得无法及时散热进一步损害其他硬件的健康(矿老板正是因为超频挖矿所以矿卡故障率很高).对于业余加密货币爱好者来说, 为了体验挖矿的乐趣而损害计算机健康得不偿失.挖矿程序挖掘以太坊推荐使用 ethminer 挖矿程序 https://github.com/ethereum-mining/ethminer在 release 页面下载适合自己所用的操作系统的最新版程序, 例如 "ethminer-0.19.0-alpha.0-cuda-9-linux-x86_64.tar.gz" 表示适用于 Linux 操作系统的用 CUDA9 编译的 0.19.0 版本.下载完挖矿程序之后, 还需要安装对应版本的 CUDA. 不过安装显卡驱动时可能已经自带了 CUDA, 使用以下命令来查看显卡和显卡驱动器状态nvidia-smi如果显示已经安装了 CUDA 就不需要另外安装了. 值得一提的是, 软件是面向旧版本 CUDA 编译的, 因为作者称新版本 CUDA 的挖矿效率没有那么高, 但是安装了新版本 CUDA(例如 CUDA11) 也是能运行软件(CUDA 9/10)的, 如果追求最高的性能可以删除安装驱动时自动安装的 CUDA 再手动安装旧版本.Windows 系统也是用这个命令来查看, 但是通过 Windows 更新安装的驱动有可能没有这个命令, 可以先尝试运行一下挖矿程序, 运行报错则再手动安装 CUDA.如果安装驱动时没有自动安装 CUDA, 请到 NVIDIA 官网下载 https://developer.nvidia.com/zh-cn/cuda-downloads以太坊钱包在开始挖掘之前要先拥有一个自己的以太坊钱包.以太坊钱包软件有很多, 与其他加密货币钱包一样, 不开源===送钱给别人. 在这个页面可以找到可靠的钱包软件 https://ethereum.org/en/wallets/find-wallet/ 挑选其中一款你觉得好看的钱包软件就可以开始了. 或者直接使用交易所提供的充值地址(那是交易所为用户自动生成的钱包), 这样就不需要额外使用钱包软件, 挖矿所得也可以直接在交易所卖出, 十分方便. 注册交易所详见另一篇文章 加密货币交易.选择矿池以太坊矿池也有很多, 在一些矿池列表网站上可以找到它们 https://investoon.com/mining_pools/eth目前第一名的矿池(按算力排序)是 SparkPool, 这个矿池的网站很多页面不登录不给看, 对于想要匿名挖矿的用户请直接跳过这一矿池. 第二名的矿池是 Ethermine, 与其他国外矿池一样, 它支持匿名挖矿, 并不需要任何个人资料也不需要任何形式的注册, 这是本文推荐的矿池.如果你已经注册了加密货币交易所, 并且交易所自己开设了矿池, 可以直接用交易所的矿池, 比如币安矿池. 交易所提供的矿池一般没有最小提现额度限制, 挖出多少就可以立即在市场上交易多少.Ethermine打开矿池的网站查看矿池提供的服务器 https://ethermine.org/start然后…

加密货币交易
type: item
date: 2021-10-21T02:46:00+00:00
description: 加密货币交易致命警告: 加密货币有风险, 与其亏钱不如直接送我很多业余加密货币爱好者接触加密货币并不是出于对区块链技术的兴趣, 而是想通过加密货币交易来赚钱, 俗称炒币.选择交易所加密货币交易除了面对面交易, 主要发生在加密货币交易所(Cryptocurrency Exchange), 这些交易所提供了交易平台, 让用户可以在平台托管自己的数字资产, 并与他人进行交易. 选择一个靠谱的交易所也就成为了交(亏)易(钱)的第一步.直接在 Google 搜索 world's biggest bitcoin exchange 可以找到很多交易所排名网站, 例如 statista 或者 coinmarketcap 在绝大多数榜单上, Binance 都是世界第一交易所, 这也是本文推荐的交易所.很多国内用户会被人推荐火币交易所, 但是本文并不推荐使用火币, 主要原因有几个:首先, 火币是中国人创办的交易所, 创办比特币交易网站在国内是非法的 , 而且未来政策可能会进一步缩紧. 虽然目前火币网站不在国内(大部分交易所都在塞舌尔或者马耳他), 但是火币的老板和大部分员工都在中国, 不排除未来政策改变后因为某些众所周知的原因 无 了.其次, 火币的交易手续费高达 0.2% , 而主流交易所例如币安只有 0.1% (BNB 手续费燃烧, 邀请人返利, 高等级 VIP 还会有进一步交易手续费折扣, 最低可达 0.012%).再次, 火币的数字资产提现手续费非常高昂(提现到自己的钱包或者其他交易所), 以比特币为例, 火币的比特币提现费用高达 0.001 , 而币安仅有 0.0005 . 这意味着想把资产从火币转移出去比其他交易所更困难.获得 USDT开始炒币的第一步是首先获得计价币种, 计价币种是价值长期稳定的加密货币, 最常用的是 USDT(泰达币), 每个 USDT 等于一美元. 交易的关键就是在价值波动大的加密货币例如比特币(BTC)涨到高点时卖出得到 USDT, 通过 USDT 这样的价值稳定的加密货币维持自己的数字资产价值, 继而在比特币跌到低谷时用 USDT 换取更多的 BTC, 循环往复从而赚钱.获得 USDT 主要有两个方式, 一是从其他交易所或者 USDT 钱包转入币安为用户提供的托管账户内. 在交易所的充值页面可以充值各种加密货币, 每一种加密货币的充值页面上给出的钱包地址是交易所为每个用户自动生成的托管式的钱包. 这个钱包的密钥用户无法取得, 把资产转入这一钱包地址就可以在交易所进行交易. 由于托管式钱包的安全性完全依赖于交易所会不会突然 无 了, 因此选择靠谱的交易所尤为重要. 对于其他数字资产也是同样的操作过程, 转到交易所提供的对应种类的加密货币的充值地址就可以开始交易了.二是通过 C2C(customer to customer) 交易获得. C2C 交易就是从别人手里购买数字资产(不仅限于 USDT), 交易所会提供广告位挂出用法币买/卖数字资产的其他用户. 目前各大交易所在进行 C2C 交易之前都要求用户实名认证(人脸, 身份证), 来确保交易双方互相可信. 如果你不想透露个人信息给交易所, 请通过第一种方式来获得可供交易的数字资产.由于 USDT 的价值保持长期稳定, 所以 C2C 交易中的买家和卖家给出的 USDT 价格接近美元真实汇率, 而其他数字资产的 C2C 交易价格都与实际价值偏差较大.现货交易现货交易就是最简单的一手交钱一手交货, 双方在某一转换率交换了两种加密货币(比如用 USDT 买 BTC), 通过高抛低吸操作继而赚钱.交易对是指买卖双方交换的数字资产种类, 例如 BTC/USDT 或者缩写为 BTCUSDT 的意思是买家用 USDT 买入 BTC 而卖家卖出 BTC 获得 USDT. 买入消耗的币种为 USDT 是最简单的交易对, 可以很直观的反映 BTC 的价格波动不需要换算. 其他的交易对例如 BTC/ETH 是用 ETH 买 BTC, 由于 ETH 本身价值也在大幅度波动, 这样的交易对的价格(转换率)十分大脑升级, 不建议新手尝试. 在最简单的情况下, 只交易以 USDT 做计价的交易对.现货交易常用概念在现货交易中会碰到一些基本概念委托委托就是已经挂在市场上的订单. 在深度图中可以看到买卖双方的委托价格和资金容量.限价委托限价委托是以固定价格发出的委托, 这是最普通的委托订单. 这些订单会写明以什么价格买入或卖出货物(加密货币). 如果有买家/卖家挂出更好价格的对应的买/卖委托, 这两份委托就会互相成交.市价现货交易的市价就是最新价格, 最新价格是当前市场上最新一份被成交的委托的价格, 如果有人以比正常价格高的多/低得多的价格买/卖, 市价就会猛烈波动. 如果一直没有任何委托被成交…

QQ聊天机器人搭建
type: item
date: 2021-09-26T09:58:00+00:00
description: HoshionBot搭建QQ群 机器人搭建项目go-cqhttp基于 Mirai 以及 MiraiGo 的 OneBot Golang 原生实现机器人框架HoshinoBotHoshinoBot: 基于 nonebot 框架，开源、无公害、非转基因的QQ机器人。部署环境Python3Golang部署 go-cqhttp官方文档git clone 项目目录结构 . ├── go-cqhttp 运行脚本 ├── config.yml 配置文件(主要修改的文件) ├── device.json 设备信息 ├── logs 日志 │ └── xx-xx-xx.log └── data 数据 ├── images │ └── xxxx.image └── db修改配置使用的反向代理端口是 universal: 'ws://127.0.0.1:8900/ws/'执行 go build 构建可执行文件执行 ./go-cqhttp 启动出现下面输出标识启动成功[2021-09-26 16:55:44] [INFO]: 当前版本:(devel) [2021-09-26 16:55:44] [INFO]: 用户交流群: 721829413 [2021-09-26 16:55:44] [INFO]: 将使用 device.json 内的设备信息运行Bot. [2021-09-26 16:55:44] [INFO]: Bot将在5秒后登录并开始信息处理, 按 Ctrl+C 取消. [2021-09-26 16:55:49] [INFO]: 开始尝试登录并同步消息... [2021-09-26 16:55:49] [INFO]: 使用协议: iPad [2021-09-26 16:55:49] [INFO]: Protocol -> connect to server: 61.181.203.156:8080 [2021-09-26 16:55:51] [INFO]: 登录成功 欢迎使用: 菜狗2号机 [2021-09-26 16:55:51] [INFO]: 开始加载好友列表... [2021-09-26 16:55:51] [INFO]: 共加载 2 个好友. [2021-09-26 16:55:51] [INFO]: 开始加载群列表... [2021-09-26 16:55:51] [INFO]: 共加载 1 个群. [2021-09-26 16:55:51] [INFO]: 信息数据库初始化完成. [2021-09-26 16:55:51] [INFO]: 资源初始化完成, 开始处理信息. [2021-09-26 16:55:51] [INFO]: CQ WebSocket 服务器已启动: 127.0.0.1:6700 [2021-09-26 16:55:51] [INFO]: アトリは、高性能ですから! [2021-09-26 16:55:51] [INFO]: 开始尝试连接到反向WebSocket Universal服务器: ws://127.0.0.1:8900/ws/ [2021-09-26 16:55:51] [INFO]: 正在检查更新.配置文件go-cqhttp配置文件account: # 账号相关 uin: 123456789 # 账号 password: '123456789' # 密码为空时使用扫码登录 encrypt: false # 是否开启密码加密 status: 0 # 在线状态 请参考 https:#github.com/Mrs4s/go-cqhttp/blob/dev/docs/config.md#在线状态 relogin: # 重连设置 disabled: false delay: 3 # 重连延迟, 单位秒 interval: 0 # 重连间隔 max-times: 0 # 最大重连次数, 0为无限制 use-sso-address: true heartbeat: disabled: false # 是否开启心跳事件上报 interval: 5 message: post-format: string ignore-invalid-cqcode: false force-fragment: false fix-url: false proxy-rewrite: '' report-self-message: false remove-reply-at: false extra-reply-data: false output: log-level: info # 日志等级 trace,debug,info,warn,error debug: false # 开启调试模式 # 默认中间件锚点 default-…

简单实现图片去重
type: item
date: 2020-04-13T06:20:54+00:00
description: 将图片转为灰阶 计算汉明距离 判断是否相似from os import listdir from PIL import Image, ImageFile import pymysql ImageFile.LOAD_TRUNCATED_IMAGES = True conn = pymysql.connect( host='127.0.0.1', user='root', password='xxxxxx', database='media' ) class Pic: @classmethod def get_client(cls): return conn.cursor() # 计算汉明距离 @classmethod def hamming(cls, diff1=None, diff2=None): if diff2 is None: diff2 = [] if diff1 is None: diff1 = [] hamming_distance = 0 for i in range(len(diff1)): if diff1[i] != diff2[i]: hamming_distance += 1 return hamming_distance # 计算图片灰阶 @classmethod def dhash(cls, image, hash_size=8): # 调整为灰阶 image = image.convert('L').resize( (hash_size + 1, hash_size), Image.ANTIALIAS, ) pixels = list(image.getdata()) # 比较相邻像素。 difference = [] for row in range(hash_size): for col in range(hash_size): pixel_left = image.getpixel((col, row)) pixel_right = image.getpixel((col + 1, row)) difference.append(pixel_left > pixel_right) # 转换 decimal_value = 0 hex_string = [] for index, value in enumerate(difference): if value: decimal_value += 2 ** (index % 8) if (index % 8) == 7: hex_string.append(hex(decimal_value)[2:].rjust(2, '0')) decimal_value = 0 return ''.join(hex_string) if __name__ == '__main__': pic = Pic() dirName = "/media/" # 相册路径 allDiff = [] dirList = listdir(dirName) num = 0 for i in dirList: if i == ".DS_Store": continue try: im = Image.open(dirName + i) hash = pic.dhash(im) allDiff.append((i, hash)) num += 1 except: continue same_map = {} for i in range(len(allDiff)): for j in range(i + 1, len(allDiff)): if i != j: ans = pic.hamming(allDiff[i][1], allDiff[j][1]) if ans <= 5: # 判别的汉明距离 same_map[allDiff[i][0]] = allDiff[j][0] print(allDiff[i][0] + " => " + allDiff[j][0]) client = pic.get_client() same_list = [] for k, item in same_map.items(): same = [k, item] same_list.append(same) # 查询 sql = """insert into same(a,b) values(%s,%s);""" client.executemany(sql, same_list) conn.commit()

Go协程
type: item
date: 2020-03-25T10:20:00+00:00
description: Go goroutine理解Go语言最大的特色就是从语言层面支持并发（Goroutine），Goroutine是Go中最基本的执行单元。事实上每一个Go程序至少有一个Goroutine：主Goroutine。当程序启动时，它会自动创建。为了更好理解Goroutine，先讲一下线程和协程的概念线程（Thread）：有时被称为轻量级进程(Lightweight Process，LWP），是程序执行流的最小单元。一个标准的线程由线程ID，当前指令指针(PC），寄存器集合和堆栈组成。另外，线程是进程中的一个实体，是被系统独立调度和分派的基本单位，线程自己不拥有系统资源，只拥有一点儿在运行中必不可少的资源，但它可与同属一个进程的其它线程共享进程所拥有的全部资源。线程拥有自己独立的栈和共享的堆，共享堆，不共享栈，线程的切换一般也由操作系统调度。协程（coroutine）：又称微线程与子例程（或者称为函数）一样，协程（coroutine）也是一种程序组件。相对子例程而言，协程更为一般和灵活，但在实践中使用没有子例程那样广泛。和线程类似，共享堆，不共享栈，协程的切换一般由程序员在代码中显式控制。它避免了上下文切换的额外耗费，兼顾了多线程的优点，简化了高并发程序的复杂。Goroutine和其他语言的协程（coroutine）在使用方式上类似，但从字面意义上来看不同（一个是Goroutine，一个是coroutine），再就是协程是一种协作任务控制机制，在最简单的意义上，协程不是并发的，而Goroutine支持并发的。因此Goroutine可以理解为一种Go语言的协程。同时它可以运行在一个或多个线程上。先给个简单实例func loop() { for i := 0; i < 10; i++ { fmt.Printf("%d ", i) } } func main() { go loop() // 启动一个goroutine loop() }GO并发的实现原理一、Go并发模型Go实现了两种并发形式。第一种是大家普遍认知的：多线程共享内存。其实就是Java或者C++等语言中的多线程开发。另外一种是Go语言特有的，也是Go语言推荐的：CSP（communicating sequential processes）并发模型。CSP并发模型是在1970年左右提出的概念，属于比较新的概念，不同于传统的多线程通过共享内存来通信，CSP讲究的是“以通信的方式来共享内存”。请记住下面这句话：DO NOT COMMUNICATE BY SHARING MEMORY; INSTEAD, SHARE MEMORY BY COMMUNICATING.“不要以共享内存的方式来通信，相反，要通过通信来共享内存。”普通的线程并发模型，就是像Java、C++、或者Python，他们线程间通信都是通过共享内存的方式来进行的。非常典型的方式就是，在访问共享数据（例如数组、Map、或者某个结构体或对象）的时候，通过锁来访问，因此，在很多时候，衍生出一种方便操作的数据结构，叫做“线程安全的数据结构”。例如Java提供的包”java.util.concurrent”中的数据结构。Go中也实现了传统的线程并发模型。Go的CSP并发模型，是通过goroutine和channel来实现的。goroutine 是Go语言中并发的执行单位。有点抽象，其实就是和传统概念上的”线程“类似，可以理解为”线程“。channel是Go语言中各个并发结构体(goroutine)之前的通信机制。 通俗的讲，就是各个goroutine之间通信的”管道“，有点类似于Linux中的管道。生成一个goroutine的方式非常的简单：Go一下，就生成了。go f();通信机制channel也很方便，传数据用channel <- data，取数据用<-channel。在通信过程中，传数据channel <- data和取数据<-channel必然会成对出现，因为这边传，那边取，两个goroutine之间才会实现通信。而且不管传还是取，必阻塞，直到另外的goroutine传或者取为止。示例如下：package main import "fmt" func main() { messages := make(chan string) go func() { messages <- "ping" }() msg := <-messages fmt.Println(msg) }注意 main()本身也是运行了一个goroutine。messages:= make(chan int) 这样就声明了一个阻塞式的无缓冲的通道chan 是关键字 代表我要创建一个通道GO并发模型的实现原理我们先从线程讲起，无论语言层面何种并发模型，到了操作系统…

Mysql索引
type: item
date: 2020-03-18T12:10:00+00:00
description: B+ Tree 原理1. 数据结构B Tree 指的是平衡树。平衡树是一颗查找树，并且所有叶子节点位于同一层。B+ Tree 是基于 B Tree 和叶子节点顺序访问指针进行实现，它具有 B Tree 的平衡性，并且通过顺序访问指针来提高区间查询的性能。在 B+ Tree 中，一个节点中的 key 从左到右非递减排列，如果某个指针的左右相邻 key 分别是 key$_i$ 和 key$_{i+1}$，且不为 null，则该指针指向节点的所有 key 大于等于 key$_i$ 且小于等于 key$_{i+1}$。2. 操作进行查找操作时，首先在根节点进行二分查找，找到一个 key 所在的指针，然后递归地在指针所指向的节点进行查找。直到查找到叶子节点，然后在叶子节点上进行二分查找，找出 key 所对应的 data。插入删除操作会破坏平衡树的平衡性，因此在进行插入删除操作之后，需要对树进行分裂、合并、旋转等操作来维护平衡性。3. 为什么使用B+树做索引文件系统及数据库系统普遍采用 B+ Tree 作为索引结构，这是因为使用 B+ 树访问磁盘数据有更高的性能。（一）B+ 树有更低的树高（二）磁盘访问原理1). 操作系统一般将内存和磁盘分割成固定大小的块，每一块称为一页，内存与磁盘以页为单位交换数据。数据库系统将索引的一个节点的大小设置为页的大小，使得一次 I/O 就能完全载入一个节点。2). 如果数据不在同一个磁盘块上，那么通常需要移动制动手臂进行寻道，而制动手臂因为其物理结构导致了移动效率低下，从而增加磁盘数据读取时间。B+ 树相对于红黑树有更低的树高，进行寻道的次数与树高成正比，在同一个磁盘块上进行访问只需要很短的磁盘旋转时间，所以 B+ 树更适合磁盘数据的读取。（三）磁盘预读特性为了减少磁盘 I/O 操作，磁盘往往不是严格按需读取，而是每次都会预读。预读过程中，磁盘进行顺序读取，顺序读取不需要进行磁盘寻道，并且只需要很短的磁盘旋转时间，速度会非常快。并且可以利用预读特性，相邻的节点也能够被预先载入。MySQL 索引索引是在存储引擎层实现的，而不是在服务器层实现的，所以不同存储引擎具有不同的索引类型和实现。1. B+Tree 索引是大多数 MySQL 存储引擎的默认索引类型。因为不再需要进行全表扫描，只需要对树进行搜索即可，所以查找速度快很多。因为 B+ Tree 的有序性，所以除了用于查找，还可以用于排序和分组。可以指定多个列作为索引列，多个索引列共同组成键。适用于全键值、键值范围和键前缀查找，其中键前缀查找只适用于最左前缀查找。如果不是按照索引列的顺序进行查找，则无法使用索引。InnoDB 的 B+Tree 索引分为主索引和辅助索引。主索引的叶子节点 data 域记录着完整的数据记录，这种索引方式被称为聚簇索引。因为无法把数据行存放在两个不同的地方，所以一个表只能有一个聚簇索引。辅助索引的叶子节点的 data 域记录着主键的值，因此在使用辅助索引进行查找时，需要先查找到主键值，然后再到主索引中进行查找。2. 哈希索引哈希索引能以 O(1) 时间进行查找，但是失去了有序性：无法用于排序与分组；只支持精确查找，无法用于部分查找和范围查找。InnoDB 存储引擎有一个特殊的功能叫“自适应哈希索引”，当某个索引值被使用的非常频繁时，会在 B+Tree 索引之上再创建一个哈希索引，这样就让 B+Tree 索引具有哈希索引的一些优点，比如快速的哈希查找。索引优化1. 独立的列在进行查询时，索引列不能是表达式的一部分，也不能是函数的参数，否则无法使用索引。例如下面的查询不能使用 actor_id 列的索引：select a_id from test WHERE a_id + 1 = 5;2. 联合索引在需要使用多个列作为条件进行查询时，使用多列索引比使用多个单列索引性能更好。例如下面的语句中，最好把 actor_id 和 film_id 设置为多列索引。select a_id, b_id from test where a_id = 1 and b_id = 1;3. 索引列的顺序让选择性最强的索引列放在前面。索引的选择性是指：不重复的索引值和记录总数的比值。最大值为 1，此时每个记录都有唯一的索引与其对应。选择性越高，每个记录的区分度越高，查询效率也越高。例如下面显示的结果中 customer_id 的选择性比 staff_id 更高，因此最好把 customer_id 列放在多列索引的前面。select count(distinct a_id)/count(*) as a_id_t, count(distinct b_id)/count(*) as b_id_t, count(*) as c from test;a_id_t : 0.0…

Mysql事务和MVCC
type: item
date: 2020-03-02T11:23:00+00:00
description: Mysql事务和MVCC谈到MySQL事务，必然离不开InnoDB和MVCC机制，同时，MVCC也是数据库面试中的杀手问题，写这篇总结的目的，就是为了让自己加深映像，这样面试就不会忘记了。在搜索时发现关于MVCC的文章真的是参差不齐(老子真的是零零散散看了三个月都迷迷糊糊)，所以这里集合了各家所言之后进行了自我总结，苦苦研究了许久，才得到的比较清晰的认知，这可能也是我目前最有深度的一篇博客了把，希望对我和看到的人都有所帮助，哈哈。MVCC: Multiversion Concurrency Control,翻译为多版本并发控制，其目标就是为了提高数据库在高并发场景下的性能。MVCC最大的优势：读不加锁，读写不冲突。在读多写少的场景下极大的增加了系统的并发性能在讲解MVCC之前我们需要先了解MySQL的基本架构，如下图所示：MySQL事务MySQL的事务是在存储引擎层实现的，在MySQL中，我们最常用的就是InnoDB和MyISAM，我们都知道，MYISAM并不支持事务，所以InnoDB实现了MVCC的事务并发处理机制，也是我们这篇文章的主要研究内容。可能我们都看到过，MVCC只在RC和RR下，为了分析这个问题，我们先回顾一下SQL标准事务隔离级别read uncommitted 读未提交： 一个事务还没提交时，它做的变更就能被别的事务看到。read committed 读提交：一个事务提交之后，它做的变更才会被其他事务看到。>repeatable read 可重复读：一个事务执行过程中看到的数据，总是跟这个事务在启动时看到的数据是一致的。在可重复读隔离级别下，未提交变更对其他事务也是不可见的。serializable 串行化 ：对于同一行记录，“写”会加“写锁”，“读”会加“读锁”。我们通过两个事务提交流程来说明事务隔离级别的具体效果:我们假设有一个表，仅有一个字段field:DROP TABLE IF EXISTS `mvcc_test`; CREATE TABLE `mvcc_test`( `field` INT)ENGINE=InnoDB; INSERT INTO `mvcc_test` VALUES(1); -- 插入一条数据如下的操作流程：根据事务隔离级别的定义，我们可以来推测，事务A提交前后，事务B的两次读取3和4分别读取的值：若事务B的隔离级别为 read uncommitted，事务B的两次读取都读取到了20，即修改后的值若事务B的隔离级别是read committed，那么，事务B的操作3读取到的值为1，而4读取到的值为20，因为4时事务A已经完成了提交若事务B的隔离级别是repeatable read或serializable，那么操作3和4读取的值都是1。MVCC的必要性MySQL中MYISAM并不支持事务，同样的， MVCC也就和他没有半毛钱关系了，InnoDB相比与MYISAM的提升就是对于行级锁的支持和对事务的支持，而应对高并发事务, MVCC 比单纯的加行锁更有效, 开销更小。但是单纯的并发也会带来十分严重的问题：Lost Update 更新丢失: 多个事务对同一行数据进行读取初值更新时，由于每个事务对其他事务都未感知，会造成最后的更新覆盖了其他事务所做的更新。dirty read 脏读: 事务一个正在对一条记录进行修改，在完成并提交前事务二也来读取该条记录，事务二读取了事务一修改但未提交的数据，如果事务一回滚，那么事务二读取到的数据就成了“脏”数据。non-repeatable read 不可重复读: 个事务在读取某些数据后的某个时间再次读取之前读取过的数据，发现读出的数据已经发生了改变或者删除，这种现象称为“不可重复读”phantom read 幻读: 个事务按相同的查询条件重新读取以前检索过的数据，发现其他事务插入了满足查询条件的新数据，这种现象称为“幻读”不可重复读与幻读的现象是比较接近的，也有人直接就说幻读就是不可重复读，我比较倾向与他两就是他两个： 不可重复读针对的是值的不同，幻读指的是数据条数的不同。同样的对于幻读，单纯的MVCC机制并不能解决幻读问题，InnoDB也是通过加间隙锁来防止幻读。从本质上来说，事务隔离级别就是系统并发能力和数据安全性间的妥协，我们在刚开始学习数据库时就在说: 隔离性越高，数据库的性能就越差，就是这个结果，只是我们当时只知其然罢了。解决并发带来的问题，最通常的就是加锁，但锁对于性能也是腰斩性的，所以MVCC就显得十分重要了。抄大佬的一句话： 在不同的隔离级别下，数据库通过 MVCC 和隔离级别，让事务之间并行操作遵循了某种规则，来保证单个事务内前后数据的一致性。InnoDB 下的 MVCC 实现原理在InnoDB中MVCC的实现通过两个重要的字段进行连接：…