编程我只用CPP 发布的文章

一、什么是事务

事务是一组SQL语句构成的语句集合,它保证所有的SQL都能全部执行或者全部不执行。

事务必须满足四个条件(ACID):Atomicity 原子性 Consistency 一致性 Isolation 隔离性`Durability 持久性`

  • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

工作流程为:

MySQL对事务的支持与引擎有关:

  • MyISAM:不支持事务,用于只读程序提高性能。
  • InnoDB:支持ACID事务、行级锁、并发。

二、使用方法

执行事务的方法很简单,只要在需要执行的SQL语句前后分别加上BEGINCOMMIT即可,即:

BEGIN;
SQL 1;
SQL 2;
...
COMMIT;
默认情况下,SQL语句都是默认提交的,即每次执行SQL语句后都会自动加上提交动作。使用set autocommit = 0命令可将语句设置成不自动提交。

三、示例

1.创建一张测试表

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)

2.使用事务插入一行数据

-- 开始事务
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)

3.回滚事务

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层)。

三者之间的分层示意图:

每一层的作用如下:

  • 物理层:通过媒介传输比特,确定机械及电气规范(比特Bit)
  • 数据链路层:将比特组装成帧和点到点的传递(帧Frame)
  • 网络层:负责数据包从源到宿的传递和网际互连(包PackeT)
  • 传输层:提供端到端的可靠报文传递和错误恢复(段Segment)
  • 会话层:建立、管理和终止会话(会话协议数据单元SPDU)
  • 表示层:对数据进行翻译、加密和压缩(表示协议数据单元PPDU)
  • 应用层:允许访问OSI环境的手段(应用协议数据单元APDU)

各层包含的协议:

  • 物理层:RJ45、CLOCK、IEEE802.3
  • 数据链路:PPP、FR、HDLC、VLAN、MAC
  • 网络层:IP、ICMP、ARP、RARP、OSPF、IPX、RIP、IGRP
  • 传输层:TCP、UDP、SPX
  • 会话层:NFS、SQL、NETBIOS、RPC
  • 表示层:JPEG、MPEG、ASII
  • 应用层:FTP、DNS、Telnet、SMTP、HTTP、WWW、NFS
在计算机网络中,我们通常使用的是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.conf
6379是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

三、添加服务

3.1 services服务

安装目录下的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  # 关闭

3.2 systemd服务

使用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即可启动服务。

3.2 luanchd服务

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>

四、其他

4.1 低版本GCC编译redis-6.x报错问题

使用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或以上

一、概述

几乎所有的数据包都是通过以太网来传输,所以使用wireshark抓取以太网数据包非常容易,这里我们以DNS数据包为例。

二、抓包

1. 准备数据

打开wireshark,在筛选栏输入dns,点击开始抓包,然后打开命令提示符,输入ping www.baidu.com ,此时wireshark将会抓到以下数据:

- 阅读剩余部分 -

一、概述

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

- 阅读剩余部分 -

# 未定义的参数标记
Hello
World


要注意的一些点是:

- 短标记和长标记后可以跟空格和等号再接参数,短标记也可以省略这两个符号直接加参数
- 不管长标记短标记后面都不能跟多个值

![](https://i.maqian.xin/2017/11/args.png)