redo_log 和 binlog

一、redo log

InnoDB 存储引擎,当事务提交时,必须先将该事务的所有日志写入到 redo log 文件中进行持久化,待事务的 commit 操作完成后才算完成。redo log 保证了数据的持久性。redo log 基本上都是顺序写的,并且在数据库运行时不需要对 redo log 的文件进行读取操作。

有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。

只要 redo log 和 binlog 保证持久化到磁盘,就能保证 MySQL 异常重启后,数据可以恢复。

1. redo log 的写入机制

查看更多

undo log

一、undo log

redo log 记录了事务的行为,但是事务有时还需要进行 “回滚” 操作,就需要使用 undo log。如果用户执行的事务或语句由于某种原因失败了,又或者用户用一条 ROLLBACK 语句请求回滚,就可以利用这些 undo log 信息将数据回滚到修改之前的样子

undo log 存放在数据库内部的一个特殊段(segment)中,这个段被称为 undo 段。undo 段位于共享表空间内。undo log 是逻辑日志,因此只是将数据库逻辑地恢复到原来的样子。所有修改都被逻辑的取消了,但是数据结构和页本身在回滚之后可能大不相同。这是因为在多用户并发系统中,可能会有多个并发事务。数据库的主要任务就是协调对数据记录的并发访问。比如,一个事物在修改当前一个页中某几条记录,同时还有别的事务对同一个页中另外几条记录进行修改。因此,不能将一个页回滚到事务开始的样子,因为这样会影响其他事务正在进行的工作。

因此,当 InnoDB 存储引起回滚时,实际上做的是与先前相反的工作。对于 INSERT,会完成一个 DELETE;对于 DELETE,会完成 INSERT;对于 UPDATE 操作,会执行一个相反的 UPDATE,将修改前的行放回去。

undo log 的另一个作用是实现 InnoDB 存储引擎中的 MVCC 功能。当用户读取一行记录时,若该功能已经被其他事务占用,当前事务可以通过 undo log 来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过 undo log 读取之前的行版本信息,以次实现非锁定读取。

注意:undo log 也会产生 redo log,也就是 undo log 的产生会伴随着 redo log 的产生,这是因为 undo log 也需要持久性的保护。

查看更多

文件

本文介绍 MySQL 和 InnoDB 存储引擎中的各种类型文件。

  • 参数文件:MySQL 实例启动时,需要的配置文件
  • 日志文件:用于记录MySQL 实例对某种条件做出响应时写入的文件,如错误日志文件、二进制日志文件、慢查询日志文件、查询日志文件等
  • socket文件:当用 UNIX 域套接字方式进行连接时需要的文件
查看更多

刷脏页的策略

当内存数据页和磁盘数据页的内容不一致时,那么这个内存页就是 “脏页”。

平时执行很快的更新操作,只是在写内存和 redo log。而偶尔的那一条执行很慢的更新操作,可能就是在刷脏页。

什么情况会引起刷脏页的过程呢?

  • InnoDB 的 redo log 写满了,这是系统会停止所有更新操作,把 redo log 的 checkpoint 往前推进。其中 checkpoint 是当前要擦除的位置,也是往前推移并且循环的,擦除记录前要把记录更新到数据文件。当改动 checkpoint 之后,redo log 就可以留出空间继续写数据。
查看更多

mysql 修改 root 密码

一、默认账户密码

当我们在 ubuntu 上使用 sudo apt install mysql-server 指令安装 mysql 后。一般情况下,会自动为我们设置账户密码,并且放在 /etc/mysql/debian.cnf 文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
# sudo cat /etc/mysql/debian.cnf
[sudo] password for zhangyi83:
# Automatically generated for Debian scripts. DO NOT TOUCH!
[client]
host = localhost
user = debian-sys-maint
password = 4RypQP1XBTOTJpwC
socket = /var/run/mysqld/mysqld.sock
[mysql_upgrade]
host = localhost
user = debian-sys-maint
password = 4RypQP1XBTOTJpwC
socket = /var/run/mysqld/mysqld.sock

如上图中显示就是默认的账户和密码。我们可以使用这组账号和密码进行登录。

二、绕过密码登陆

我们可以设置绕过密码登陆。修改 mysql 的配置文件: /etc/mysql/mysql.conf.d/mysqld.cnf

查看更多

利用 gdb 实现 pstack

利用 gdb 实现 pstack

使用 gdb 的 attach 实现获取所有线程的 堆栈,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/bin/bash

if test $# -ne 1; then
echo "Usage: `basename $0 .sh` <process-id>" 1>&2
exit 1
fi

if test ! -r /proc/$1; then
echo "Process $1 not found." 1>&2
exit 1
fi

# GDB doesn't allow "thread apply all bt" when the process isn't
# threaded; need to peek at the process to determine if that or the
# simpler "bt" should be used.

backtrace="bt"
if test -d /proc/$1/task ; then
# Newer kernel; has a task/ directory.
if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then
backtrace="thread apply all bt"
fi
elif test -f /proc/$1/maps ; then
# Older kernel; go by it loading libpthread.
if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
backtrace="thread apply all bt"
fi
fi

GDB=${GDB:-/usr/bin/gdb}

if $GDB -nx --quiet --batch --readnever > /dev/null 2>&1; then
readnever=--readnever
else
readnever=
fi

# Run GDB, strip out unwanted noise.
$GDB --quiet $readnever -nx /proc/$1/exe $1 <<EOF 2>&1 |
$backtrace
EOF
/bin/sed -n \
-e 's/^(gdb) //' \
-e '/^#/p' \
-e '/^Thread/p'

mem-profiler 工具说明

一、概述

此工具可以分析内存是被那些函数使用了。原理是每分配一定内存就去采样内存分配调用处的堆栈。最后按照堆栈的函数调用关系汇总成我们想要的结果图。

实际依赖 jemalloc、libunwind 来获取函数调用的堆栈,通过共享内存作为媒介来实现不同进程之间的通信,也即使用 jemalloc 的进程为我们测试进程,mem-profiler 进程可以操作共享内存,修改数据,以达到与测试进程之间交互的目的;最终实现实时的控制启动、停止内存详细信息的收集处理任务。

二、使用

1. 配置待测试进程

使用 jemalloc 作为我们的内存分配管理库,并且使用我们改写优化后的 jemalloc 。库地址:https://console.cloud.baidu-int.com/devops/icode/repos/baidu/adu-3rd/jemalloc/blob/mem_profiler_x86_64_ubuntu18_gcc750_v5.2.1/README.md

请查看分支名,获取不同 cpu 架构、不同 gcc 版本编译的 libjemalloc 库。其中带 mem_profiler 前缀的即为所需的库。

为了工具的可插拔性,我们一般推荐使用 LD_PRELOAD 的方式加载 libjemalloc.so。比如 AVP-ANP2 项目中的添加方式,查看 start_all_modules.bash 文件中的 use_jemalloc 函数的实现。链接:https://console.cloud.baidu-int.com/devops/icode/repos/baidu/asd/AVP-ANP2/blob/dev_pangu/onboard/bin/start_all_modules.bash

查看更多