[内容] MariaDB & MySQL 事务

内容一:事务的作用

事务的作用是保护数据的安全性

内容二:MariaDB & MySQL 事务的 4 大特性

2.1 原子性(Atomicity)

一系列操作被看作一个事务,这个事务里面的所有操作要么全部失败,要么全部成功,如果在操作的过程中出现中断,则立刻进行 rollback

2.2 一致性(Consistency)

一系列操作被看作一个事务,在事务开始前和结束后,整个库的完整逻辑约束不能被打破,例如:一个人向另一个人转账,不能出现一个人转账成功另一个人没有收到转账,或者一个人转账失败另一个人收到转账的情况

2.3 隔离性(Isolation)

主要解决并发的情况,避免不同的人,在相同的时间,查看到的数据的不一致性,避免以下情况的发生:
1) 脏读:一个事务读取了另一个事务更新、提交并撤销的数据,导致此事务看到的数据是错误的
2) 不可重复读:一个事务多次读取了另一个事务多次更新并提交的数据,导致此事务看到的数据是来回变化的
3) 幻读:一个事务在批量修改所有数据,但是在修改的过程中另一个事务又往里面插入了数据,导致此事务在修改完成之后,意外发现还有一条数据没有修改

2.4 持久性(Durability)

事务结束后,所有更新都将被保存,不能回滚

内容三:MariaDB & MySQL 事务隔离级别

3.1 MariaDB & MySQL 事务隔离级别的特点

事务隔离级别脏读不可重复读幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

3.2 MariaDB & MySQL 默认的事务隔离级别

可重复读 repeatable-read

3.3 查看目前所使用的事务隔离的方法

MariaDB [(none)]> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.001 sec)

(补充:这里以查看 MariaDB 目前所使用的事务隔离为例)

[内容] MariaDB & MySQL 多表关系

内容一:一对一关系

1.1 通常实现方法

唯一外键

1.2 典型案例

学生表和学生证表

内容二:一对多关系

2.1 通常实现方法

主外键

2.2 典型案例

学生表和班级表

内容三:多对多关系

3.1 通常实现方法

中间表加联合主键

(补充:联合主键是指一张表中有两个主键,这两个主键叫联合主键,每一条数据里的联合主键可以相互之间拼凑成一个新的主键,联合主键可以重复,只要保证这个新的主键唯一即可)

3.2 典型案例

学生和课程

[工具] Shell 自动化部署 LNMP + SSL 平台 (openSUSE Leap 15 版)

介绍

基本信息

作者:朱明宇
名称:自动化部署 LNMP + SSL 平台
作用:自动化安装 LNMP + SSL,即通过 Linux、Nginx、MariaDB、PHP、php-fpm、SSL,实现 HTTPS

使用方法

1. 将网站的网页数据备份、网站的 SSL 公钥、网站的 SSL 私钥、网站的数据库备份和本脚本,5 个文件放在同一目录下
2. 如果没有网站的数据库备份则将网页数据备份、网站的 SSL 公钥、网站的 SSL 私钥和本脚本,4 个文件放在同一目录下
3. 在此脚本的分割线内写入相应的内容
4. 开启系统的 selinux
5. 给此脚本添加执行权限
6. 执行此脚本:./<执行本脚本>

脚本分割线里的变量

1. webdomain=”eternalcenter.com” #网站的域名,注意不要在前面加任何前缀
2. webtar=”eternalcenter-backup-*.tar.gz” #网站的网页数据备份,如果没有这个备份,可以下载一个开源的 WordPress 网页程序
3. webcrt=”eternalcenter.com.crt” #网站 SSL 的公钥,可以自己创建也可以在 FreeSSl 上申请
4. webkey=”eternalcenter.com.key” #网站 SSL 的私钥,可以自己创建也可以在 FreeSSL 上申请
5. sqlbackup=”eternalcenter-backup-*.sql” #网站数据库数据备份,如果没有这个备份(数据库是全量备份),则这里可以为空
6. db=”ec” #网站在数据库中库
7. dbuser=”ec” #网站在数据库中的用户
8. dbuserpw=”eternalcenter” #网站在数据库中的用户密码
9. dbrootpw=”eternalcenter” #数据库的 root 密码

注意

1. 服务器的系统需要是 openSUSE 15 版本
2. 服务器系统要配置好可用的软件源(最好是软件数量最多的官方版本)
3. 服务器要能够连接外网

脚本

#!/bin/bash

####################### Separator ########################
webdomain="eternalcenter.com"
webtar="eternalcenter-backup-*.tar.gz"
webcrt="eternalcenter.com.crt"
webkey="eternalcenter.com.key"
sqlbackup="eternalcenter-backup-*.sql"
db="ec"
dbuser="ec"
dbuserpw="eternalcenter"
dbrootpw="eternalcenter"
####################### Separator ########################

#判断所需文件是否存在
ls $webtar
if [ $? -ne 0 ];then
	echo "没有网页数据备份,无法继续"
	exit 2
fi

ls $webcrt
if [ $? -ne 0 ];then
	echo "没有网站公钥,无法继续"
	exit 2
fi

ls $webkey
if [ $? -ne 0 ];then
	echo "没有网站私钥,无法继续"
	exit 2
fi

#更新系统
zypper ref
zypper -n update

#确保必需软件已经安装
zypper -n in tar
zypper -n in firewalld


#部署 Nginx
zypper -n in nginx

echo 'worker_processes  1;

events {
    worker_connections  1024;
}

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;

    keepalive_timeout  60;
    client_body_timeout 20s;
    client_header_timeout 10s;
    send_timeout 30s;

    server {
        listen       80;
        limit_req zone=one burst=5;
        server_name www.eternalcenter.com eternalcenter.com;

        rewrite ^/(.*)$ https://eternalcenter.com/$1 permanent;
      
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        }

    server {
        listen 443 ssl;
        server_name www.eternalcenter.com eternalcenter.com;

        if ($request_method !~ ^(GET|POST)$){
        return 444;
        }

        ssl_certificate      /etc/nginx/ssl/eternalcenter.com.crt;
        ssl_certificate_key  /etc/nginx/ssl/eternalcenter.com.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        root /srv/www/htdocs;

        location / {
            index index.php;
            try_files $uri $uri/ /index.php$is_args$args;
            if (-f $request_filename/index.html){rewrite (.) $1/index.html break;}
            if (-f $request_filename/index.php){rewrite (.) $1/index.php;}
            if (!-f $request_filename){rewrite (.) /index.php;}
        }

        location ~ \.php$ {
            include fastcgi_params;
	    include fastcgi.conf;
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME /srv/www/htdocs/$fastcgi_script_name;

        }
	
	location ~ ^/\.user\.ini {
            deny all;
        }

        location ~*\.(jpd|jpeg|gif|png|css|js|ico|xml)$ {
            expires 30d;
        }

        error_page  404              /404.html;
    }

        gzip on;
	gzip_min_length 1000;
	gzip_comp_level 4;
	gzip_types text/plain test/css application/json application/x-javascript text/xml application/xml
	application/xml+rss text/javascripts;

	client_header_buffer_size 1k;

	open_file_cache_valid  60s;
	open_file_cache_min_uses 5;
	open_file_cache_errors off;

}' > /etc/nginx/nginx.conf

sed -i "s/server_name www.eternalcenter.com eternalcenter.com;/server_name www.$webdomain $webdomain;/" /etc/nginx/nginx.conf
sed -i "s@rewrite ^/(.*)$ https://eternalcenter.com/\$1 permanent@rewrite ^/(.*)$ https://$webdomain/\$1 permanent@" /etc/nginx/nginx.conf;
sed -i "s/eternalcenter.com.crt/$webcrt/" /etc/nginx/nginx.conf
sed -i "s/eternalcenter.com.key/$webkey/" /etc/nginx/nginx.conf

mkdir /etc/nginx/ssl
mv $webcrt /etc/nginx/ssl
mv $webkey /etc/nginx/ssl

rm -rf /srv/www/htdocs/*
tar -xvf $webtar -C /srv/www/htdocs/ && rm -rf $webtar

zypper -n in policycoreutils

systemctl start nginx
systemctl enable nginx

#部署 MariaDB
zypper -n in mariadb mariadb-server

grep "^log_bin=" /etc/my.cnf
if [ $? -ne 0 ];then
	sed -i '/^datadir/a log_bin=ec' /etc/my.cnf
fi

grep "^binlog_format=" /etc/my.cnf
if [ $? -ne 0 ];then
	sed -i '/^datadir/a binlog_format=\"mixed\"' /etc/my.cnf
fi

grep "^server_id=" /etc/my.cnf
if [ $? -ne 0 ];then
	sed -i '/^datadir/a server_id=51' /etc/my.cnf
fi

sed -i 's/^plugin-load-add=auth_gssapi.so/#plugin-load-add=auth_gssapi.so/' /etc/my.cnf

sed -i '/^user=.*/d' /etc/my.cnf
sed -i "/\[mysqld\]/a user=mysql" /etc/my.cnf

sed -i '/^bind-address=.*/d' /etc/my.cnf
sed -i "/\[mysqld\]/a bind-address=127.0.0.1" /etc/my.cnf

systemctl start mariadb
systemctl enable mariadb

chown -R mysql:mysql /var/lib/mysql

ls $sqlbackup
if [ $? -ne 0 ];then
        mysql -uroot -e "create database $db;"
        mysql -uroot -e "create user \"$dbuser\"@\"localhost\" identified by \"$dbuserpw\";"
        mysql -uroot -e "grant all privileges on $db.* to \"$dbuser\"@\"localhost\" identified by \"$dbuserpw\";"
        mysql -uroot -e "set password for 'root'@'localhost'=password(\"$dbrootpw\")"
else
        mysql -uroot -e "create database $db;"
        mysql -uroot $db < $sqlbackup
        mysql -uroot -e "create user \"$dbuser\"@\"localhost\" identified by \"$dbuserpw\";"
        mysql -uroot -e "grant all privileges on $db.* to \"$dbuser\"@\"localhost\" identified by \"$dbuserpw\";"
        mysql -uroot -e "set password for 'root'@'localhost'=password(\"$dbrootpw\")"
        rm -rf $sqlbackup
fi
	
systemctl restart mariadb

#部署 PHP
zypper -n in php7 php7-fpm php7-mysql php7-gd php7-mbstring php7-opcache php7-json php7-xmlrpc php7-zlib
useradd php-fpm -s /sbin/nologin
groupadd php-fpm
chown -R php-fpm:php-fpm /srv/www/htdocs
cp /etc/php7/fpm/php-fpm.conf.default /etc/php7/fpm/php-fpm.conf

sed -i /"^user =.*"/d /etc/php7/fpm/php-fpm.conf
sed -i /"^group =.*"/d /etc/php7/fpm/php-fpm.conf
sed -i /"^listen =.*"/d /etc/php7/fpm/php-fpm.conf
sed -i /"^[www]"/d /etc/php7/fpm/php-fpm.conf
sed -i /"^pm = .*"/d /etc/php7/fpm/php-fpm.conf
sed -i /"^pm.start_servers = .*"/d /etc/php7/fpm/php-fpm.conf
sed -i /"^pm.min_spare_servers = .*"/d /etc/php7/fpm/php-fpm.conf
sed -i /"^pm.max_spare_servers = .*"/d /etc/php7/fpm/php-fpm.conf
sed -i /"^pm.max_children = .*"/d /etc/php7/fpm/php-fpm.conf
sed -i /"^pm.max_requests = .*"/d /etc/php7/fpm/php-fpm.conf
sed -i /"^request_terminate_timeout = .*"/d /etc/php7/fpm/php-fpm.conf

echo '[www]' >> /etc/php7/fpm/php-fpm.conf
echo 'user = php-fpm' >> /etc/php7/fpm/php-fpm.conf
echo 'group = php-fpm' >> /etc/php7/fpm/php-fpm.conf
echo 'listen = 127.0.0.1:9000' >> /etc/php7/fpm/php-fpm.conf
echo 'pm = dynamic' >> /etc/php7/fpm/php-fpm.conf
echo 'pm.start_servers = 2' >> /etc/php7/fpm/php-fpm.conf
echo 'pm.min_spare_servers = 2' >> /etc/php7/fpm/php-fpm.conf
echo 'pm.max_spare_servers = 4' >> /etc/php7/fpm/php-fpm.conf
echo 'pm.max_children = 4' >> /etc/php7/fpm/php-fpm.conf
echo 'pm.max_requests = 1024' >> /etc/php7/fpm/php-fpm.conf
echo 'request_terminate_timeout = 300' >> /etc/php7/fpm/php-fpm.conf

systemctl start php-fpm
systemctl enable php-fpm

#提高系统性能
grep "^* soft nofile" /etc/security/limits.conf
if [ $? -ne 0 ];then
	echo '* soft nofile 1024' >> /etc/security/limits.conf
fi

grep "^* hard nofile" /etc/security/limits.conf
if [ $? -ne 0 ];then
	echo '* hard nofile 1024' >> /etc/security/limits.conf
fi

#打开防火墙
systemctl start firewalld
systemctl enable firewalld
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --add-port=443/tcp --permanent
firewall-cmd --reload

#限制日志占用空间
echo "/var/log/mariadb/mariadb.log {
        create 600 mysql mysql
        notifempty
	daily
        rotate 3
        missingok
        compress
    postrotate
	# just if mysqld is really running
        if [ -e /run/mariadb/mariadb.pid ]
        then
           kill -1 $(</run/mariadb/mariadb.pid)
        fi
    endscript
}" > /etc/logrotate.d/mariadb

echo "/var/log/nginx/*log {
    create 0664 nginx root
    size 1024M
    rotate 1
    missingok
    notifempty
    compress
    sharedscripts
    postrotate
        /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endscript
}" > /etc/logrotate.d/nginx

echo "/var/log/php-fpm/*log {
    size 100M
    rotate 1
    missingok
    notifempty
    sharedscripts
    delaycompress
    postrotate
        /bin/kill -SIGUSR1 `cat /run/php-fpm/php-fpm.pid 2>/dev/null` 2>/dev/null || true
    endscript
}" > /etc/logrotate.d/php-fpm

echo "/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
    size 100M
    rotate 1
    missingok
    sharedscripts
    postrotate
        /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
    endscript
}" > /etc/logrotate.d/syslog

#删除此脚本
scriptwhere=`readlink -f "$0"`
rm -rf $scriptwhere

#重启系统
reboot

[步骤] MariaDB 的安装

步骤一:系统环境要求

服务器系统要配置好可用的软件源

2.1 CentOS&RHEL 安装 MariaDB

# yum -y install mariadb mariadb-devel mariadb-server

2.2 openSUSE&SUSE 安装 MariaDB

# zypper -n mariadb mariadb-devel mariadb-server

[工具] Shell 在 MariaDB & MySQL 的配置文件里设置部分安全策略

介绍:

作者:朱明宇
名称:在 MariaDB & MySQL 的配置文件里设置部分安全策略
作用:在 MariaDB & MySQL 的配置文件里设置部分安全策略

使用方法:
1. 确认 MariaDB & MySQL 已提前装好
2. 在此脚本的分割线内写入相应的内容
3. 给此脚本增加执行权限
4. 执行此脚本

脚本:

#!/bin/bash

#At the system level, start the database as a MySQL user
chown -R mysql /var/lib/mysql
sed -i '/^user=/d' /etc/my.cnf.d/mariadb-server.cnf
sed -i '/^datadir/a user=mysql' /etc/my.cnf.d/mariadb-server.cnf

#Disable client local data reading at the system level
sed -i '/^local-infile=/d' /etc/my.cnf.d/mariadb-server.cnf
sed -i '/^datadir/a local-infile=0' /etc/my.cnf.d/mariadb-server.cnf

#At the system level, remote login of database is prohibited
sed -i '/^bind-address=/d' /etc/my.cnf.d/mariadb-server.cnf
sed -i '/^datadir/a bind-address=127.0.0.1' /etc/my.cnf.d/mariadb-server.cnf

#Restart database
systemctl restart mariadb ; systemctl restart mysql