mysql/数据库基础.md
2025-03-12 15:50:01 +08:00

467 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<h2><center>数据库基础</center></h2>
------
## 一:数据库简介
### 1. 数据库技术构成
- 数据库系统 DBS
1. 数据库管理系统DataBase Management SystemDBMS
- SQLRDSORACLE、Oracle MySQL、MariaDB、Percona server、DB2
- NoSQLRedis、MongoDB、Memcache
2. 数据库管理员DBA
- SQL语言Structured Query Language 即结构化查询语言)
1. DDL语句 数据库定义语言数据库、表、视图、索引、存储过程、函数CREATE ALTER
2. DML语句 数据库操作语言:插入数据 INSERT、输出输入 DELETEDROP、更新数据 UPDATE
3. DQL语句 数据库查询语言:查询数据 SELECT
4. DCL语句 数据库控制语言:例如控制用户的访问权限 GRANT、REVOKE
- 数据访问技术
1. ODBC PHP <.php>
2. JDBC JAVA <.jsp>
3. settings.py python <.py>
### 2. 数据库部署
版本
- mysql8.0以上
- mysql5.7
网址
[MySQL :: Developer Zone](https://dev.mysql.com/)
#### yum 安装
![](http://182.92.143.66:40072/directlink/img/mysql/images-202503090001.png)
![](http://182.92.143.66:40072/directlink/img/mysql/images-202503090002.png)
![](http://182.92.143.66:40072/directlink/img/mysql/images-202503090003.png)
![](http://182.92.143.66:40072/directlink/img/mysql/images-202503090004.png)
![](http://182.92.143.66:40072/directlink/img/mysql/images-202503090005.png)
下载mysql的yum仓库
```bash
[root@mysql ~]# wget https://dev.mysql.com/get/mysql84-community-release-el7-1.noarch.rpm
```
安装mysql的yum仓库
```bash
[root@mysql ~]# rpm -ivh https://dev.mysql.com/get/mysql84-community-release-el7-1.noarch.rpm
```
安装mysql
```bash
[root@mysql ~]# yum -y install mysql-server
[root@mysql ~]# systemctl start mysqld
[root@mysql ~]# systemctl enable mysqld
```
查看初始密码
```bash
[root@mysql ~]# grep 'password' /var/log/mysqld.log
2025-03-09T08:54:35.000643Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: +oplg.ua>4wR
```
修改密码
```
[root@mysql ~]# mysqladmin -u root -p'+oplg.ua>4wR' password 'Wjifja@7412347289'
```
```bash
[root@mysql ~]# mysql -uroot -p'+oplg.ua>4wR'
mysql> alter user 'root'@'localhost' identified by 'Wjifja@7412347289';
```
#### rpm 安装
![](http://182.92.143.66:40072/directlink/img/mysql/images-202503090006.png)
![](http://182.92.143.66:40072/directlink/img/mysql/images-202503090007.png)
![](http://182.92.143.66:40072/directlink/img/mysql/images-202503090008.png)
检查系统是否安装过mysql、mariadb
```bash
[root@mysql ~]# rpm -qa | grep mariadb
[root@mysql ~]# rpm -qa | grep mysql
```
卸载安装的mariadb
```bash
[root@mysql ~]# rpm -e --nodeps mariadb-libs
```
下载rpm包
```bash
[root@mysql ~]# wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.30-1.el7.x86_64.rpm-bundle.tar
```
解压tar文件
```bash
[root@mysql ~]# mkdir mysql
[root@mysql ~]# tar xvf mysql-5.7.30-1.el7.x86_64.rpm-bundle.tar -C mysql && cd mysql
```
安装
```bash
[root@mysql mysql]# rpm -i mysql-community-common-5.7.30-1.el7.x86_64.rpm
[root@mysql mysql]# rpm -i mysql-community-libs-5.7.30-1.el7.x86_64.rpm
[root@mysql mysql]# rpm -i mysql-community-client-5.7.30-1.el7.x86_64.rpm
[root@mysql mysql]# rpm -i mysql-community-server-5.7.30-1.el7.x86_64.rpm
[root@mysql mysql]# rpm -ivh mysql-community-libs-compat-5.7.30-1.el7.x86_64.rpm
```
启动服务
```bash
[root@mysql mysql]# systemctl start mysqld
[root@mysql mysql]# systemctl enable mysqld
```
查看初始密码
```bash
[root@mysql mysql]# grep password /var/log/mysqld.log
2025-03-09T09:31:55.267389Z 1 [Note] A temporary password is generated for root@localhost: (jbU*oyh-0d2
```
修改密码
```bash
[root@mysql mysql]# mysqladmin -uroot -p'(jbU*oyh-0d2' password 'Wdjia@3462713'
```
#### 编译安装
清理安装环境:
```bash
新环境:
[root@rpm ~]# rpm -qa | grep mariadb
[root@rpm ~]# rpm -e --nodeps mariadb-libs
旧环境:
[root@rpm ~]# yum remove mariadb mariadb-server mariadb-libs mariadb-devel -y
[root@rpm ~]# userdel -r mysql
[root@rpm ~]# rm -rf /etc/my*
[root@rpm ~]# rm -rf /var/lib/mysql
```
创建mysql用户
```bash
[root@rpm ~]# useradd -r mysql -M -s /sbin/nologin
-M 不创建用户的家目录
```
从官网下载tar包
```bash
[root@rpm ~]# wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-boost-5.7.27.tar.gz
```
安装编译工具:
```bash
[root@rpm ~]# yum -y install ncurses ncurses-devel openssl-devel bison gcc gcc-c++ make
[root@rpm ~]# yum -y install cmake
```
创建mysql目录
```bash
[root@rpm ~]# mkdir -p /usr/local/{data,mysql,log}
```
解压:
```bash
[root@rpm ~]# tar xzvf mysql-boost-5.7.27.tar.gz -C /usr/local/
```
编译安装:
```bash
cd 解压的mysql目录
[root@rpm ~]# cd /usr/local/mysql-5.7.27/
[root@rpm mysql-5.7.27]# cmake . \
> -DWITH_BOOST=boost/boost_1_59_0/ \
> -DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
> -DSYSCONFDIR=/etc \
> -DMYSQL_DATADIR=/usr/local/mysql/data \
> -DINSTALL_MANDIR=/usr/share/man \
> -DMYSQL_TCP_PORT=3306 \
> -DMYSQL_UNIX_ADDR=/tmp/mysql.sock \
> -DDEFAULT_CHARSET=utf8 \
> -DEXTRA_CHARSETS=all \
> -DDEFAULT_COLLATION=utf8_general_ci \
> -DWITH_READLINE=1 \
> -DWITH_SSL=system \
> -DWITH_EMBEDDED_SERVER=1 \
> -DENABLED_LOCAL_INFILE=1 \
> -DWITH_INNOBASE_STORAGE_ENGINE=1
参数详解:
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \ 安装目录
-DSYSCONFDIR=/etc \ 配置文件存放 (默认可以不安装配置文件)
-DMYSQL_DATADIR=/usr/local/mysql/data \ 数据目录 错误日志文件也会在这个目录
-DINSTALL_MANDIR=/usr/share/man \ 帮助文档
-DMYSQL_TCP_PORT=3306 \ 默认端口
-DMYSQL_UNIX_ADDR=/tmp/mysql.sock \ sock文件位置用来做网络通信的客户端连接服务器的时候用
-DDEFAULT_CHARSET=utf8 \ 默认字符集。字符集的支持,可以调
-DEXTRA_CHARSETS=all \ 扩展的字符集支持所有的
-DDEFAULT_COLLATION=utf8_general_ci \ 支持的
-DWITH_READLINE=1 \ 上下翻历史命令
-DWITH_SSL=system \ 使用私钥和证书登陆(公钥) 可以加密。 适用与长连接。坏处:速度慢
-DWITH_EMBEDDED_SERVER=1 \ 嵌入式数据库
-DENABLED_LOCAL_INFILE=1 \ 从本地倒入数据,不是备份和恢复。
-DWITH_INNOBASE_STORAGE_ENGINE=1 默认的存储引擎,支持外键
```
![](http://182.92.143.66:40072/directlink/img/mysql/images-202503100009.png)
```bash
[root@rpm mysql-5.7.27]# make -j4 && make install
如果安装出错,想重新安装:
不用重新解压只需要删除安装目录中的缓存文件CMakeCache.txt
```
初始化:
```bash
[root@rpm mysql-5.7.27]# cd /usr/local/mysql
[root@rpm mysql]# chown -R mysql.mysql .
[root@rpm mysql]# ./bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
---初始化完成之后,一定要记住提示最后的密码用于登陆或者修改密码
```
![](http://182.92.143.66:40072/directlink/img/mysql/images-202503100010.png)
初始化,只需要初始化一次
```bash
[root@rpm mysql]# vim /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql #指定安装目录
datadir=/usr/local/mysql/data #指定数据存放目录
```
启动mysql
```bash
[root@rpm mysql]# ./bin/mysqld_safe --user=mysql &
启动之后再按一下回车!即可后台运行
[root@rpm mysql]# netstat -lntp | grep 3306
tcp6 0 0 :::3306 :::* LISTEN 28550/mysqld
```
登入mysql
```bash
[root@rpm mysql]# /usr/local/mysql/bin/mysql -uroot -p'dewuqdQxa4&t'
```
### 3. mysql基础
**编译安装**
```bash
[root@rpm mysql]# ls
bin COPYING-test docs lib README share
COPYING data include mysql-test README-test support-files
```
- bin目录用于放置一些可执行文件mysql、mysqld、mysqlbinlog等
- include目录用于放置一些头文件mysql.h、mysql_ername.h等
- lib目录用于放置一系列库文件
- share目录用于存放字符集、语言等信息
**yum安装**
- /var/lib/mysql 存放数据文件
- /usr/share/mysql 用于存放字符集、语言等信息
**配置文件基本参数**
```bash
[root@rpm mysql]# vim /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
validate_password=off 添加后可设置弱密码强度
lower_case_table_names=1 不区分大小写
扩展:
key_buffer = 384M //key_buffer是用于索引块的缓冲区大小增加它可得到更好处理的索引(对所有读和多重写)。索引被所有的线程共享key_buffer的大小视内存大小而定
table_open_cache = 512 //MySQL每打开一个表都会读入一些数据到table_open_cache缓存中当MySQL在这个缓存中找不到相应信息时才会去磁盘上读取。默认值64, 假定系统有200个并发连接则需将此参数设置为200*N(N为每个连接所需的文件描述符数目)当把table_open_cache设置为很大时如果系统处理不了那么多文件描述符那么就会出现客户端失效连接不上
max_allowed_packet = 4M //接受的数据包大小增加该变量的值十分安全这是因为仅当需要时才会分配额外内存。例如仅当你发出长查询或MySQLd必须返回大的结果行时MySQLd才会分配更多内存。 该变量之所以取较小默认值是一种预防措施,以捕获客户端和服务器之间的错误信息包,并确保不会因偶然使用大的信息包而导致内存溢出
sort_buffer_size = 2M //MySQL执行排序使用的缓冲大小。如果想要增加ORDER BY的速度首先看是否可以让MySQL使用索引而不是额外的排序阶段。如果不能可以尝试增加sort_buffer_size变量的大小
read_buffer_size = 2M //读查询操作所能使用的缓冲区大小。和sort_buffer_size一样该参数对应的分配内存也是每连接独享。对表进行顺序扫描的请求将分配一个读入缓冲区MySQL会为它分配一段内存缓冲区。 如果对表的顺序扫描请求非常频繁,并且你认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能
thread_concurrency = 8 //最大并发线程数取值为服务器逻辑CPU数量×2
max_connections = 1000 //MySQL的最大连接数如果服务器的并发连接请求量比较大建议调高此值以增加并行连接数量当然这建立在机器能支撑的情况下因为如果连接数越多介于MySQL会为每个连接提供连接缓冲区就会开销越多的内存所以要适当调整该值不能盲目提高设值
```
### 4.数据库引擎
数据库存储引擎是数据库底层软件组织数据库管理系统DBMS使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能使用不同的存储引擎还可以获得特定的功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。MySQL的核心就是存储引擎。
#### InnoDB存储引擎
InnoDB是事务性型数据库的首选引擎支持事务安全表ACID支持行锁定和外键InnoDB是默认的MySQL引擎。
特点:
支持事务处理支持外键支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高比如银行要求实现并发控制比如售票那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库也可以选择InnoDB因为支持事务的提交和回滚。
#### MyISAM存储引擎
MyISAM基于ISAM存储引擎并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度但不支持事务。
特点:
插入数据块空间和内存使用比较低。如果表主要是用于插入新纪录和读出记录那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比较低也可以使用。
#### MEMORY存储引擎
MEMORY存储引擎将表中的数据存储到内存中为查询和引用其他表数据提供快速访问。
特点:
所有的数据都在内存中数据的处理速度快但是安全性不高。如果需要很快的读写速度对数据的安全性要求较低可以选择MEMORY。它对表的大小有要求不能建立太大的表。所以这类数据库只使用在相对较小的数据库表。
**如何选择引擎**
如果要提供提交、回滚、崩溃恢复能力的事务安全ACID兼容能力并要求实现并发控制InnoDB是一个好的选择如果数据表主要用来插入和查询记录则MyISAM引擎能够提供较高的处理效率如果只是临时存放数据数据量不大并且不需要较高的数据安全性可以选择将数据保存在内存中的Memory引擎MySQL中使用该引擎作为临时表存放查询的中间结果如果只有INSERT和SELECT操作可以选择ArchiveArchive支持高并发的插入操作但是本身不是事务安全的。Archive非常适合存储归档数据如记录日志信息可以使用Archive。
如果哪一种引擎需要灵活选择,一个数据库中多个表可以使用不同引擎以满足各种性能和实际需求,使用合适的存储引擎,将会提高整个数据库的性能。
#### 存储引擎查看
```bash
mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)
```
Support列的值表示某种引擎是否使用YES表示可以使用、NO表示不能使用、DEFAULT表示该引擎为当前默认的存储引擎。
### 5. mysql事务
MySQL事务主要用于处理操作量大复杂度高的数据。比如说在人员管理系统中你删除一个人员你既需要删除人员的基本资料也要删除和该人员相关的信息信箱、文章等等这要这些数据库操作语句就构成一个事务。
在MySQL中只有使用了InnoDB数据库引擎的数据库或表才支持事务。
事务处理可以用来维护数据库的完整性保证成批的SQL语句要么全部执行要么全部不执行。
事务用来管理INSERT、UPDATE、DELETE语句。
#### 满足事务条件
- 原子性一个事务transaction中的所有操作要么全部完全要么全部不完成不会结束在中间某个环节。事务在执行过程中发生错误会被回滚Rollback到事务开始前的状态就像这个事务从来没有执行过一样。
- 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完成符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
- 隔离性数据库允许多个并发事务同时对其数据进行读写和修改的能力隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别包括读未提交Read uncommitted、读提交read committed、可重复读repeatable read和串行化Serializable
- 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
#### 了解
MySQL事务处理主要有两种方法
1. 用 BEGINROLLBACKCOMMIT来实现
- BEGIN 开始一个事务
- ROLLBACK 事务回滚
- COMMIT 事务确认
2. 直接用 SET 来改变 MySQL 的自动提交模式:
- SET AUTOCOMMIT=0 禁止自动提交
- SET AUTOCOMMIT=1 开启自动提交
```bash
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.01 sec)
注意:在编写应用程序时,最好事务的控制权限交给开发人员
```
### 6. 数据库锁
锁是计算机协调多个进程或纯线程并发访问某一资源的机制。在数据库中除传统的计算资源CPU、RAM、I/O的争用以外数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所在有数据库必须解决的一个问题锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说锁对数据库而言显得尤其重要也更加复杂相对其他数据库而言MySQL的锁机制比较简单其最显著的特点是不同的存储引擎支持不同的锁机制。
MyISAM在执行查询语句SELECT会自动给涉及的所有表加读锁在执行更新操作UPDATE、DELETE、INSERT等会自动给涉及的表加写锁这个过程并不需要用户干预因此用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。给MyISAM表显示加锁一般是为了一定程度模拟事务操作实现对某一时间点多个表的一致性读取。
#### 锁分类
- 表级锁:开销小,加锁块;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
- 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
- 页面锁:开销和加锁时间介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般。
#### 案例
有一个订单表orders其中记录有订单的总金额total同时还有一个订单明细表order_detail其中记录有订单每一产品的金额小计subtotal假设我们需要检查这两个表的金额合计是否相等可能就需要执行如下两条SQL
```SQL
mysql> SELECT SUM(total) FROM orders;
mysql> SELECT SUM(subtotal) FROM order_detail;
```
这时如果不先给这两个表加锁就可能产生错误的结果因为第一条语句执行过程中order_detail表可能已经发生了改变。因此正确的方法应该是
```SQL
mysql> LOCK tables orders read local,order_detail read local;
mysql> SELECT SUM(total) FROM orders;
mysql> SELECT SUM(subtotal) FROM order_detail;
mysql> Unlock tables;
```
上面的例子在LOCK TABLES时加了local选项其作用就是在满足MyISAM表并发插入条件的情况下允许其他用户在表尾插入记录。
在用LOCKTABLES给表显式加表锁是时必须同时取得所有涉及表的锁并且MySQL支持锁升级也就是说在执行LOCK TABLES后只能访问显式加锁的这些表不能访问未加锁的表同时如果加的是读锁那么只能执行查询操作而不能执行更新操作。其实在自动加锁的情况下也基本如此MySQL问题一次获得SQL语句所需要的全部锁。
### 7. 外键
在实际开发的项目中,一个健壮数据库中的数据一定有很好的参照完整性。例如学生档案和成绩单两张表,如果成绩单中有张三的成绩,学生档案中张三的档案却被删除了,这样就会产生垃圾数据或者错误数据。为了保证数据的完整性,将两张表之间的数据建立关系,因此就需要在成绩表中添加外键约束。
外键是指引用另外一个表中的一列或多列数据,被引用的列应该具有主键约束或者唯一性约束。外键用来建立和加强两个表数据之间的连接。
#### 外键的定义
- 外键是某个表中的一列,它包含在另一个表的主键中
- 外键也是索引的一种,是通过一张表中的一列指向另一张表中的主键,来对两张表进行关联
- 一张表可以有一个外键,也可以存在多个外键,与多张表进行关联
#### 外键的作用
外键的主要作用是保证数据的一致性和完整性,并且减少数据冗余