MySQL的事务隔离级别
MySQL事务的隔离级别
一、事务并发带来的问题
1.1 第一类丢失更新
两个事务同时更新一行数据,第一个事务正常更新,第二个事务中途退出回滚数据到初始状态,导致第一个事务更新失效。
如:银行卡存储了用户甲的余额4000,此时事务A和B同时开始更新余额,事务A将余额更新到5000后正常退出,事务B执行出错导致更新失败,然后回滚余额到开始的状态4000。于是就产生了第一类丢失更新。
两个事务同时更新一行数据,第一个事务正常更新,第二个事务中途退出回滚数据到初始状态,导致第一个事务更新失效。
如:银行卡存储了用户甲的余额4000,此时事务A和B同时开始更新余额,事务A将余额更新到5000后正常退出,事务B执行出错导致更新失败,然后回滚余额到开始的状态4000。于是就产生了第一类丢失更新。
事务是一组SQL语句构成的语句集合,它保证所有的SQL都能全部执行或者全部不执行。
事务必须满足四个条件(ACID):Atomicity 原子性 Consistency 一致性 Isolation 隔离性`Durability 持久性`
工作流程为:

MySQL对事务的支持与引擎有关:
执行事务的方法很简单,只要在需要执行的SQL语句前后分别加上BEGIN和COMMIT即可,即:
BEGIN;
SQL 1;
SQL 2;
...
COMMIT;默认情况下,SQL语句都是默认提交的,即每次执行SQL语句后都会自动加上提交动作。使用set autocommit = 0命令可将语句设置成不自动提交。mysql> create table test(
-> id int primary key auto_increment,
-> name varchar(20) not null default "",
-> age tinyint unsigned not null
-> );
Query OK, 0 rows affected (0.22 sec)在不使用事务的情况下插入一行数据:
mysql> insert into test values(1, "maqian", 21);
Query OK, 1 row affected (0.07 sec)
mysql> select * from test;
+----+--------+-----+
| id | name | age |
+----+--------+-----+
| 1 | maqian | 21 |
+----+--------+-----+
1 row in set (0.00 sec)-- 开始事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
-- 插入数据
mysql> insert into test values(2, "xiaoming", 20);
Query OK, 1 row affected (0.00 sec)
-- 查看当前数据
mysql> select * from test;
+----+----------+-----+
| id | name | age |
+----+----------+-----+
| 1 | maqian | 21 |
| 2 | xiaoming | 20 |
+----+----------+-----+
2 rows in set (0.00 sec)
-- 提交
mysql> commit;
Query OK, 0 rows affected (0.03 sec)
-- 数据仍然存在
mysql> select * from test;
+----+----------+-----+
| id | name | age |
+----+----------+-----+
| 1 | maqian | 21 |
| 2 | xiaoming | 20 |
+----+----------+-----+
2 rows in set (0.00 sec)mysql> insert into test values(3, "xiaohua", 1);
Query OK, 1 row affected (0.00 sec)
-- 插入了一行数据
mysql> select * from test;
+----+----------+-----+
| id | name | age |
+----+----------+-----+
| 1 | maqian | 21 |
| 2 | xiaoming | 20 |
| 3 | xiaohua | 1 |
+----+----------+-----+
3 rows in set (0.00 sec)
-- 回滚
mysql> rollback;
Query OK, 0 rows affected (0.02 sec)
-- 被插入的行被回滚了,数据库回到插入前的状态
mysql> select * from test;
+----+----------+-----+
| id | name | age |
+----+----------+-----+
| 1 | maqian | 21 |
| 2 | xiaoming | 20 |
+----+----------+-----+
2 rows in set (0.00 sec) 计算机网络体系结构有三种:OSI分层(7层)、五层协议(5层)和TCP/IP分层(4层)。
三者之间的分层示意图:

每一层的作用如下:
各层包含的协议:
在计算机网络中,我们通常使用的是5层表示法。因此数据链路层也被称为二层,网络层被称为三层。
Redis官网地址:redis官网,官网可能会打不开,可以在github的发布页中下载:Release-redis。
当前最新版6.0-rc1,下载redis:
https://github.com/antirez/redis/archive/6.0-rc1.tar.gz编译redis6.0需要GCC5以上版本,低版本会报错,如果GCC版本低于5,只能使用redis5.x版本。
解压源码文件编译:
tar -zxvf 6.0-rc1.tar.gz && mv 6.0-rc1 redis-6.0-rc1
cd redis-6.0-rc1
make MALLOC=libc注意make的时候要添加MALLOC=libc参数,否则可能出现以下报错:
zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory
#include <jemalloc/jemalloc.h>
^
compilation terminated.
make[1]: *** [adlist.o] Error 1
make[1]: Leaving directory `/usr/local/redis-5.0.5/src'
make: *** [all] Error 2这个参数的用处是指定redis使用的malloc函数为libc中的,默认情况下redis使用的是jmalloc,大部分系统默认没有安装,会报错。
编译完成后,安装redis到/usr/local/redis-6.0-rc1:
sudo make PREFIX=/usr/local/redis-6.0-rc1 install给安装目录创建软链接并添加到PATH路径下:
sudo ln -s /usr/local/redis-6.0-rc1/ /usr/local/redis
# 添加路径到PATH环境变量中
REDIS_HOME=/usr/local/redis
export PATH=$PATH:$REDIS_HOME/bin执行完成后,直接运行redis-server 就能启动redis了,可以加上--port 参数指定运行端口。

默认的配置文件在安装目录下:redis.conf ,复制到/etc/redis/ 目录下:
mkdir /etc/redis
cp redis.conf /etc/redis/6379.conf6379是redis的默认监听端口,根据不同端口来命名配置文件可以使主机同时运行多个redis实例,方便管理。
配置文件中的一些参数说明:
port 6379 # 默认的端口
dir ./ # 持久化文件存放路径
daemonize no # 是否以守护进程启动
pidfile /var/run/redis_6379.pid # pid文件路径
logfile "" # 日志文件路径添加redis用户:
useradd -M -s /sbin/nologin redis设置目录权限:
chown redis.redis -R /usr/local/redis安装目录下的utils 默认有一个redis_init_script 脚本,复制到/etc/ini.d 目录下:
cp utils/redis_init_script /etc/init.d/redis_6379 # 6379是redis监听的端口号里面需要修改的内容:
REDISPORT=6379 # 默认监听端口6379
EXEC=/usr/local/redis/bin/redis-server # 服务端程序路径
CLIEXEC=/usr/local/redis/bin/redis-cli # 客户端程序路径
PIDFILE=/var/run/redis_${REDISPORT}.pid # pid文件路径
CONF="/etc/redis/${REDISPORT}.conf" # 配置文件路径启动和关闭redis:
/etc/init.d/redis_6379 start # 启动
/etc/init.d/redis_6379 stop # 关闭使用systemd服务时,注意redis不能以守护进程启动:
daemonize no复制以下内容到/etc/systemd/system/redis_6379.service:
[Unit]
Description=The redis-server Process Manager
After=syslog.target network.target
[Service]
Type=simple
PIDFile=/var/run/redis_6379.pid
ExecStart=/usr/local/redis/redis-server /etc/redis/redis_6379.conf
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/bin/kill -SIGINT $MAINPID
User=redis
Group=redis
[Install]
WantedBy=multi-user.target然后执行systemctl start redis_6379即可启动服务。
luanchd服务是mac系统下的后台管理程序,把以下配置保存到文件homebrew.mxcl.redis.plist,然后放到~/Library/LaunchAgents/路径下(注意修改程序和日志文件路径):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
<key>Label</key>
<string>homebrew.mxcl.redis</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/redis/bin/redis-server</string>
<string>/etc/redis/redis.conf</string>
</array>
<key>RunAtLoad</key>
<false/>
<key>WorkingDirectory</key>
<string>/usr/local/redis</string>
<key>StandardErrorPath</key>
<string>/appdata/redis/redis.log</string>
<key>StandardOutPath</key>
<string>/appdata/redis/redis.log</string>
</dict>
</plist>编辑完成后,载入redis服务:
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.redis.plist
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.redis.plist启动和关闭redis:
launchctl start ~/Library/LaunchAgents/homebrew.mxcl.redis.plist
launchctl stop ~/Library/LaunchAgents/homebrew.mxcl.redis.plist上面的配置中没有设置开机自启,如果希望开机自启,要把18行的<false/>改成<true>。
使用GCC4编译redis-6.0,会报错:

cd src && make all
make[1]: 进入目录“/data/software/redis-6.0-rc1/src”
CC server.o
In file included from server.c:30:0:
server.h:1022:5: 错误:expected specifier-qualifier-list before ‘_Atomic’
_Atomic unsigned int lruclock; /* Clock for LRU eviction */
^
server.c: 在函数‘serverLogRaw’中:
server.c:1020:31: 错误:‘struct redisServer’没有名为‘logfile’的成员
int log_to_stdout = server.logfile[0] == '\0';问题原因:
In old gcc version like 4.7/8, there is a bug that miss the macro like [STDC_NO_ATOMICS]
低版本的GCC例如4.7和4.8,有一个缺少类似[STDC_NO_ATOMICS]宏定义的BUG。
可参考fix: old gcc without atomic support compile failed
解决方案是升级GCC5或以上
+
1 row in set (0.00 sec)
几乎所有的数据包都是通过以太网来传输,所以使用wireshark抓取以太网数据包非常容易,这里我们以DNS数据包为例。
打开wireshark,在筛选栏输入dns,点击开始抓包,然后打开命令提示符,输入ping www.baidu.com ,此时wireshark将会抓到以下数据:
wordpress默认用户登录做了错误次数限制,但是没有对xmlrpc.php 这个文件接口限制,导致此文件被黑客利用进行暴力破解,此时可以利用Login Security Solution 插件来对这个文件接口进行限制。
设置界面:

xmlrpc.php 是wordpress默认就有的一个离线发布模块,我们可以使用诸如windows live writer 之类的软件进行离线发布,在发布的过程中会验证wordpress帐号的密码,不管帐号密码正确失败,都会给予相应的回复。对于攻击者来说,这就是一个漏洞,因为他们知道每一次尝试登陆的结果,于是就可以无限制利用这个文件进行暴力密码破解,直到得到一次正确的返回——即尝试到了一个正确的账户密码。
yum -y install expect