一天学会MySQL数据库

MySQL学习笔记
登录登出
-- 登录数据库服务器
$ mysql -uroot -p1234
-- 登出数据库服务器
exit;
基本语法
-- 显示所有数据库
show databases;

-- 创建数据库
CREATE DATABASE databaseName;

-- 切换数据库
USE databaseName;

-- 删除数据库
DROP DATABASE databaseName;

-- 显示数据库中的所有表
show tables;

-- 创建表
CREATE TABLE pet (
    name VARCHAR(20),
    owner VARCHAR(20),
    species VARCHAR(20),
    gender CHAR(1),
    birth DATE,
    death DATE   
);

-- 删除表
DROP TABLE pet;

-- 查看表结构
DESC pet;

-- 插入数据 - 增
INSERT INTO pet VALUES ("jiaomei","lily","dog","male","2025-01-01","2035-01-01");
INSERT INTO pet (name,owner) VALUES ("jiaomei","lily");

-- 删除数据 - 删
DELETE FROM pet WHERE owner="lily";

-- 修改数据 - 改
UPDATE pet SET name="gouzi" WHERE owner="lily";

-- 查询表 - 查
SELECT * FROM pet;
数据类型
  • 数值 : INT , FLOAT , DOUBLE .. ;
  • 日期/时间 : DATE , DATETIME .. ;
  • 字符串 : CHAR , VARCHAR .. .
建表约束
- 主键约束

在表中定义一个主键以唯一确定表中每一行数据的标识符 .
只要 联合的主键值不完全相同 且 联合的主键值中的任何一个字段不为空 即可 .

-- 主键约束
-- 在表中定义一个主键以唯一确定表中每一行数据的标识符
-- 定义为主键的字段不重复且不为空 以确保表内所有数据的唯一性
CREATE TABLE user (
    id INT PRIMARY KEY,
    name VARCHAR(20)
);

-- 联合主键
-- 联合主键中的每个字段不为空 且加起来不能和已设置的联合主键重复
CREATE TABLE user (
    id INT,
    name VARCHAR(20),
    passwd VARCHAR(20),
    PRIMARY KEY (id, name)
);

-- 添加主键约束
-- 如果在建表时未设置主键 可通过SQL语句设置(两种方式)
ALTER TABLE user ADD PRIMARY KEY (id);
ALTER TABLE user MODIFY id INT PRIMARY KEY;

-- 删除主键约束
ALTER TABLE user DROP PRIMARY KEY;
- 自增约束

同主键约束搭配使用 .

-- 自增约束和主键约束搭配使用 且自增约束的主键由系统自动递增分配
CREATE TABLE user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20)
);
- 唯一约束

保证一个字段或一组字段里的数据与表中其它行数据相比是唯一的 .

  • 主键约束 - 值不为空
  • 唯一约束 - 值可为空
-- 唯一约束
CREATE TABLE user (
    id INT,
    name VARCHAR(20),
    UNIQUE (name)
);

-- 添加唯一约束
-- 如果在建表时未设置唯一键 可通过SQL语句设置(两种方式)
ALTER TABLE user ADD UNIQUE (name);
ALTER TABLE user MODIFY name VARCHAR(20) UNIQUE;

-- 删除唯一约束
ALTER TABLE user DROP INDEX name;
- 非空约束

保证某个字段不能为空 .

-- 建表时设置非空约束 约束某个字段不能为空
CREATE TABLE user (
    id INT,
    name VARCHAR(20) NOT NULL
);

-- 删除非空约束
ALTER TABLE user MODIFY name VARCHAR(20);
- 默认约束

保证某个字段有默认值 .

-- 建表时设置默认约束 约束某个字段的默认值
CREATE TABLE user (
    id INT,
    name VARCHAR(20),
    age INT DEFAULT 20
);

-- 删除默认约束
ALTER TABLE user MODIFY age INT;
- 外键约束

涉及到两个表 : 父表(主表) - 子表(副表) .
主表中没有的数据值 , 在副表中是不可以使用的 ;
主表中的记录被副表使用 , 是不可以被删除的 .

-- 创建班级表
CREATE TABLE classes (
    id INT PRIMARY KEY,
    name VARCHAR(20)
);

-- 创建学生表
CREATE TABLE students (
    id INT PRIMARY KEY,
    name VARCHAR(20),
    class_id INT,
    FOREIGN KEY (class_id) REFERENCES classes (id)
);
三大范式
1. 第一范式

数据表中的所有字段都是不可分割的原子值 .
只要字段值还可以继续拆分 , 就不满足第一范式 .
范式设计得越详细 , 对于某些实际操作可能更好 , 但是也不一定都是好处 .
以实际开发的便捷性确定 .

2. 第二范式

在满足第一范式的前提下 , 第二范式要求 :
除主键外的每一列都必须完全依赖于主键 , 如果出现不完全依赖 , 只可能发生在联合主键的情况下 .

CREATE TABLE myorder (
    product_id INT,
    consumer_id INT,
    product_name VARCHAR(20),
    consumer_name VARCHAR(20),
    PRIMARY KEY (product_id, consumer_id)
);

-- 拆表重新设计
-- ====================>
CREATE TABLE myorder (
    order_id INT PRIMARY KEY,
    product_id INT,
    consumer_id INT,
);

CREATE TABLE product (
    id INT PRIMARY KEY,
    name VARCHAR(20),
);

CREATE TABLE consumer (
    id INT PRIMARY KEY,
    name VARCHAR(20),
);
3. 第三范式

在满足第二范式的前提下 , 第三范式要求 :
除主键外的其它列不能有传递依赖关系 .

CREATE TABLE myorder (
    order_id INT PRIMARY KEY,
    product_id INT,
    consumer_id INT,
    consumer_phone VARCHAR(11)
);

-- 拆表重新设计
-- ======================>
CREATE TABLE myorder (
    order_id INT PRIMARY KEY,
    product_id INT,
    consumer_id INT
);

CREATE TABLE consumer (
    id INT PRIMARY KEY,
    phone VARCHAR(11)
);
查询练习
数据准备
1. 建库并选择该库
CREATE DATABASE selectTest;
USE selectTest;
2. 建表
-- 创建学生表
CREATE TABLE student (
    no VARCHAR(20) PRIMARY KEY,
    name VARCHAR(20) NOT NULL,
    gender VARCHAR(10) NOT NULL,
    birthday DATE,
    class VARCHAR(20)
);

-- 创建教师表
CREATE TABLE teacher (
    no VARCHAR(20) PRIMARY KEY,
    name VARCHAR(20) NOT NULL,
    gender VARCHAR(10) NOT NULL,
    birthday DATE,
    prof VARCHAR(20) NOT NULL,
    dept VARCHAR(20) NOT NULL
);

-- 创建课程表
CREATE TABLE course (
    no VARCHAR(20) PRIMARY KEY,
    name VARCHAR(20) NOT NULL,
    t_no VARCHAR(20) NOT NULL,
    FOREIGN KEY (t_no) REFERENCES teacher (no)
);

-- 创建成绩表
CREATE TABLE score (
    s_no VARCHAR(20) NOT NULL,
    c_no VARCHAR(20) NOT NULL,
    degree DECIMAL,
    FOREIGN KEY (s_no) REFERENCES student (no),
    FOREIGN KEY (c_no) REFERENCES course (no),
    PRIMARY KEY (s_no,c_no)
);

-- 创建等地表
CREATE TABLE grade (
    low INT(3),
    upp INT(3),
    grade CHAR(1)
);
3. 向表中添加数据
-- 添加学生表数据
INSERT INTO student VALUES ('101','曾华','男','1977-09-01','95033');
INSERT INTO student VALUES ('102','匡明','男','1975-10-02','95031');
INSERT INTO student VALUES ('103','王丽','女','1976-01-23','95033');
INSERT INTO student VALUES ('104','李军','男','1976-02-20','95033');
INSERT INTO student VALUES ('105','王芳','女','1975-02-10','95031');
INSERT INTO student VALUES ('106','陆军','男','1974-06-03','95031');
INSERT INTO student VALUES ('107','王尼玛','男','1976-02-20','95033');
INSERT INTO student VALUES ('108','张全蛋','男','1975-02-10','95031');
INSERT INTO student VALUES ('109','赵铁柱','男','1974-06-03','95031');

-- 添加教师表数据
INSERT INTO teacher VALUES ('804','李诚','男','1958-12-02','副教授','计算机系');
INSERT INTO teacher VALUES ('856','张旭','男','1969-03-12','讲师','电子工程系');
INSERT INTO teacher VALUES ('825','王萍','女','1972-05-05','助教','计算机系');
INSERT INTO teacher VALUES ('831','刘冰','女','1977-08-14','助教','电子工程系');

-- 添加课程表数据
INSERT INTO course VALUES ('3-105','计算机导论','825');
INSERT INTO course VALUES ('3-245','操作系统','804');
INSERT INTO course VALUES ('6-166','数字电路','856');
INSERT INTO course VALUES ('9-888','高等数学','831');

-- 添加成绩表数据
INSERT INTO score VALUES ('103','3-245','86');
INSERT INTO score VALUES ('105','3-245','75');
INSERT INTO score VALUES ('109','3-245','68');
INSERT INTO score VALUES ('103','3-105','92');
INSERT INTO score VALUES ('105','3-105','88');
INSERT INTO score VALUES ('109','3-105','76');
INSERT INTO score VALUES ('103','6-166','85');
INSERT INTO score VALUES ('105','6-166','79');
INSERT INTO score VALUES ('109','6-166','81');

-- 添加等地表数据
INSERT INTO grade VALUES (90,100,'A');
INSERT INTO grade VALUES (80,89,'B');
INSERT INTO grade VALUES (70,79,'C');
INSERT INTO grade VALUES (60,69,'D');
INSERT INTO grade VALUES (0,59,'E');
五张表的数据展示

1. 学生表
+-----+--------+--------+------------+-------+
| no | name | gender | birthday | class |
+-----+--------+--------+------------+-------+
| 101 | 曾华 | 男 | 1977-09-01 | 95033 |
| 102 | 匡明 | 男 | 1975-10-02 | 95031 |
| 103 | 王丽 | 女 | 1976-01-23 | 95033 |
| 104 | 李军 | 男 | 1976-02-20 | 95033 |
| 105 | 王芳 | 女 | 1975-02-10 | 95031 |
| 106 | 陆军 | 男 | 1974-06-03 | 95031 |
| 107 | 王尼玛 | 男 | 1976-02-20 | 95033 |
| 108 | 张全蛋 | 男 | 1975-02-10 | 95031 |
| 109 | 赵铁柱 | 男 | 1974-06-03 | 95031 |
+-----+--------+--------+------------+-------+
2. 教师表
+-----+------+--------+------------+--------+------------+
| no | name | gender | birthday | prof | dept |
+-----+------+--------+------------+--------+------------+
| 804 | 李诚 | 男 | 1958-12-02 | 副教授 | 计算机系 |
| 825 | 王萍 | 女 | 1972-05-05 | 助教 | 计算机系 |
| 831 | 刘冰 | 女 | 1977-08-14 | 助教 | 电子工程系 |
| 856 | 张旭 | 男 | 1969-03-12 | 讲师 | 电子工程系 |
+-----+------+--------+------------+--------+------------+
3. 课程表
+-------+------------+------+
| no | name | t_no |
+-------+------------+------+
| 3-105 | 计算机导论 | 825 |
| 3-245 | 操作系统 | 804 |
| 6-166 | 数字电路 | 856 |
| 9-888 | 高等数学 | 831 |
+-------+------------+------+
4. 成绩表
+------+-------+--------+
| s_no | c_no | degree |

+------+-------+--------+
| 103 | 3-105 | 92 |
| 103 | 3-245 | 86 |
| 103 | 6-166 | 85 |
| 105 | 3-105 | 88 |
| 105 | 3-245 | 75 |
| 105 | 6-166 | 79 |
| 109 | 3-105 | 76 |
| 109 | 3-245 | 68 |
| 109 | 6-166 | 81 |
+------+-------+--------+

5. 等地表
+------+------+-------+
| low | upp | grade |
+------+------+-------+
| 90 | 100 | A |
| 80 | 89 | B |
| 70 | 79 | C |
| 60 | 69 | D |
| 0 | 59 | E |
+------+------+-------+

测试练习
  1. 查询student表中的所有记录
SELECT * FROM student;
  1. 查询student表中所有记录的name,gender,class
SELECT name, gender, class FROM student;
  1. 查询teacher表中的所有单位 - DISTINCT 去重
SELECT DISTINCT dept FROM teacher;
  1. 查询score表中成绩在60-80之间的所有记录 - BETWEEN AND 范围
SELECT * FROM score WHERE degree BETWEEN 60 AND 80;
  1. 查询score表中成绩为85,86或88的记录 - IN 或者
SELECT * FROM score WHERE degree IN (85,86,88);
  1. 查询student表中"95031"班或性别为"女"的同学记录 - AND 交集
SELECT * FROM student WHERE class="95031" OR gender="女";
  1. 以class降序查询student表中的所有记录 - ORDER BY DESC 排序
SELECT * FROM student ORDER BY class DESC;
  1. 以c_no升序 degree降序查询score表中的所有记录 - ORDER BY DESC 排序
SELECT * FROM score ORDER BY c_no, degree DESC;
  1. 查询"95031"班的学生人数 - COUNT 统计
SELECT COUNT(*) FROM student WHERE class="95031";
  1. 查询每门课的平均成绩 - GROUP BY 分组 AVG 均值
SELECT c_no, AVG(degree) FROM score GROUP BY c_no;
  1. 查询score表中至少有2名学生选修且以3开头的课程的平均分数 - 均值 AVG 分组 GROUP BY 条件 HAVING 统计 COUNT 模糊匹配 LIKE
SELECT c_no, AVG(degree) FROM score GROUP BY c_no HAVING COUNT(*) >= 2 AND c_no LIKE "3%";
  1. 查询"计算机系" "电子工程系"不同职称的教师的姓名和职称 - 求并集
SELECT name, prof FROM teacher WHERE dept = "计算机系" AND prof NOT IN (SELECT prof FROM teacher WHERE dept = "电子工程系")
UNION
SELECT name, prof FROM teacher WHERE dept = "电子工程系" AND prof NOT IN (SELECT prof FROM teacher WHERE dept = "计算机系");
  1. 查询所有"女"教师和"女"同学的姓名,性别,生日 - 求并集
SELECT name, gender, birthday FROM student WHERE gender = "女"
UNION
SELECT name, gender, birthday FROM teacher WHERE gender = "女";
  1. 查询student表中最大最小的birthday日期值
SELECT MAX(birthday) AS "maxValue", MIN(birthday) AS "minValue" FROM student;
  1. 查询选修编号"3-105"且成绩至少高于选修编号"3-245"的同学的学号,课程号,分数,并按degree从高到低排序.
SELECT s_no, c_no, degree FROM score WHERE c_no = "3-105" AND degree > ANY (SELECT degree FROM score WHERE c_no = "3-245") ORDER BY degree DESC;
  1. 查询选修编号"3-105"且成绩高于选修编号"3-245"的同学的学号,课程号,分数
SELECT s_no, c_no, degree FROM score WHERE c_no = "3-105" AND degree > ALL (SELECT degree FROM score WHERE c_no = "3-245") ORDER BY degree DESC;
  1. 查询score表中最高分的学生学号和课程号 - 子查询
SELECT s_no, c_no FROM score WHERE degree = (SELECT MAX(degree) FROM score);
  1. 查询成绩高于学号"109"课程号"3-105"的成绩的所有记录 - 子查询
SELECT * FROM score WHERE degree > (SELECT degree FROM score WHERE s_no = "109" AND c_no = "3-105");
  1. 查询和学号"101""108"的同学同年出生的所有学生的学号,姓名,生日 - 子查询 YEAR()
SELECT no, name, birthday FROM student WHERE YEAR(birthday) IN (SELECT YEAR(birthday) FROM student WHERE no IN ("101", "108"));
  1. 查询"张旭"教师任课的学生成绩 - 子查询
SELECT * FROM score WHERE c_no IN (SELECT no FROM course WHERE t_no = (SELECT no FROM teacher WHERE name = "张旭"));
  1. 查询选修某课程的同学人数多于3人的教师姓名 - 子查询
SELECT name FROM teacher WHERE no IN (SELECT t_no FROM course WHERE no IN (SELECT c_no FROM score GROUP BY c_no HAVING COUNT(*) >= 3));
  1. 查询"计算机系"教师所教课程的成绩表 - 子查询
SELECT * FROM score WHERE c_no IN (SELECT no FROM course WHERE t_no IN (SELECT no FROM teacher WHERE dept = "计算机系"));
  1. 查询所有任课教师的姓名和单位 - 子查询
SELECT name, dept FROM teacher WHERE no IN (SELECT t_no FROM course WHERE no IN (SELECT DISTINCT c_no FROM score));
  1. 查询男教师所上的课程 - 子查询
SELECT * FROM course WHERE t_no IN (SELECT no FROM teacher WHERE gender = "男");
  1. 查询最高分同学的学号,课程号,分数 - 子查询
SELECT * FROM score WHERE degree = (SELECT MAX(degree) FROM score);
  1. 查询和"李军"同性别的所有学生的姓名 - 子查询
SELECT name FROM student WHERE gender = (SELECT gender FROM student WHERE name = "李军");
  1. 查询和"李军"同性别且同班的所有同学的姓名 - 子查询
SELECT name FROM student WHERE gender = (SELECT gender FROM student WHERE name = "李军") AND class = (SELECT class FROM student WHERE name = "李军");
  1. 查询所有选秀"计算机导论"课程的"男"同学的成绩表 - 子查询
SELECT * FROM score WHERE c_no IN (SELECT no FROM course WHERE name = "计算机导论") AND s_no IN (SELECT no FROM student WHERE gender = "男");
  1. 查询选修"3-105"课程的成绩高于"109"号同学"3-105"成绩的所有同学的记录 - 子查询 HARD
SELECT * FROM student WHERE no IN (SELECT DISTINCT s_no FROM score WHERE c_no = "3-105" AND degree > (SELECT degree FROM score WHERE s_no = "109" AND c_no = "3-105"));
  1. 查询所有学生的姓名,课程号,分数 - 多表查询
SELECT name, c_no, degree FROM student, score WHERE student.no = score.s_no;
  1. 查询所有学生的学号,课程名,分数 - 多表查询
SELECT s_no, name, degree FROM course, score WHERE course.no = score.c_no;
  1. 查询所有学生的姓名,课程名,分数 - 多表查询
SELECT student.name, course.name, degree FROM student, course, score WHERE student.no = score.s_no AND course.no = score.c_no;
  1. 查询 "95031"班学生每门课的课程名称和平均分 - 多表查询 子查询 分组
SELECT c_no, name, AVG(degree) FROM course, score WHERE course.no = score.c_no AND s_no IN (SELECT no FROM student WHERE class = "95031") GROUP BY c_no;
  1. 查询所有同学的学号,课程号,等地 - 按等地查询 多表查询
SELECT s_no, c_no, grade FROM score, grade WHERE degree BETWEEN low AND upp;
SELECT s_no, student.name, c_no, course.name, grade FROM score, grade, student, course WHERE (degree BETWEEN low AND upp) AND (student.no = score.s_no) AND (course.no = score.c_no);
  1. 查询成绩比该课程平均成绩低的同学的成绩表 - 复制表数据做条件查询 HARD
    两层的嵌套循环 如 外层循环到"3-105"时 则内层过一遍所有的"3-105"并求均值
SELECT * FROM score a WHERE degree < (SELECT AVG(degree) FROM score b WHERE a.c_no = b.c_no);
  1. 查询至少有4名男生的班号 - HARD
SELECT class FROM student WHERE gender = "男" GROUP BY class HAVING COUNT(*) >= 4;
连接查询
数据准备
1. 建库并选择该库
CREATE DATABASE testJoin;
USE testJoin;
2. 建表
CREATE TABLE person (
    id INT,
    name VARCHAR(20),
    cardId INT
);

CREATE TABLE card (
    id INT,
    name VARCHAR(20)
);
3. 向表中添加数据
INSERT INTO person VALUES (1, '张三', 1), (2, '李四', 3), (3, '王五', 6);
INSERT INTO card VALUES (1, '饭卡'), (2, '建行卡'), (3, '农行卡'), (4, '工商卡'), (5, '邮政卡');
两张表的数据展现

1. 用户表
+------+------+--------+

| id | name | cardId |
+------+------+--------+
| 1 | 张三 | 1 |
| 2 | 李四 | 3 |
| 3 | 王五 | 6 |
+------+------+--------+

2. 卡表
+------+--------+
| id | name |
+------+--------+
| 1 | 饭卡 |
| 2 | 建行卡 |
| 3 | 农行卡 |
| 4 | 工商卡 |
| 5 | 邮政卡 |
+------+--------+

1. 内连接 - INNER JOIN

查询两张表的交集

SELECT * FROM person INNER JOIN card ON person.cardId = card.id;

查询结果
+------+------+--------+------+--------+
| id | name | cardId | id | name |
+------+------+--------+------+--------+
| 1 | 张三 | 1 | 1 | 饭卡 |
| 2 | 李四 | 3 | 3 | 农行卡 |
+------+------+--------+------+--------+

2. 左外连接 - LEFT OUTER JOIN

完整显示左边的表 右边的表如果符合条件就显示 不符合条件就补NULL

SELECT * FROM person LEFT OUTER JOIN card ON person.cardId = card.id;

查询结果
+------+------+--------+------+--------+
| id | name | cardId | id | name |
+------+------+--------+------+--------+
| 1 | 张三 | 1 | 1 | 饭卡 |
| 2 | 李四 | 3 | 3 | 农行卡 |
| 3 | 王五 | 6 | NULL | NULL |
+------+------+--------+------+--------+

3. 右外连接 - RIGHT OUTER JOIN

完整显示右边的表 左边的表如果符合条件就显示 不符合条件就补NULL

SELECT * FROM person RIGHT OUTER JOIN card ON person.cardId = card.id;

查询结果
+------+------+--------+------+--------+
| id | name | cardId | id | name |
+------+------+--------+------+--------+
| 1 | 张三 | 1 | 1 | 饭卡 |
| 2 | 李四 | 3 | 3 | 农行卡 |
| NULL | NULL | NULL | 2 | 建行卡 |
| NULL | NULL | NULL | 4 | 工商卡 |
| NULL | NULL | NULL | 5 | 邮政卡 |
+------+------+--------+------+--------+

4. 完全外连接 - FULL OUTER JOIN

查询两张表的并集 MySQL不支持该语法

SELECT * FROM person LEFT OUTER JOIN card ON person.cardId = card.id
UNION
SELECT * FROM person RIGHT OUTER JOIN card ON person.cardId = card.id;

查询结果
+------+------+--------+------+--------+
| id | name | cardId | id | name |
+------+------+--------+------+--------+
| 1 | 张三 | 1 | 1 | 饭卡 |

| 2 | 李四 | 3 | 3 | 农行卡 |
| 3 | 王五 | 6 | NULL | NULL |
| NULL | NULL | NULL | 2 | 建行卡 |
| NULL | NULL | NULL | 4 | 工商卡 |
| NULL | NULL | NULL | 5 | 邮政卡 |
+------+------+--------+------+--------+

事务
如何控制事务

在MySQL中 , 事务默认开启自动提交 .
自动提交 : 当我们执行一条SQL语句时 , 其产生的效果会立即体现 , 且不能回滚 .

  • 自动提交
    • 查看自动提交状态 : SELECT @@AUTOCOMMIT; ;
    • 设置自动提交状态 : SET AUTOCOMMIT=0; .
  • 手动提交
    @@AUTOCOMMIT=0时 , 使用COMMIT命令提交事务 ;
  • 事务回滚 : 撤销SQL语句执行效果
    @@AUTOCOMMIT=0时 , 使用ROLLBACK命令回滚事务 .
手动开启事务

事务的自动提交被默认开启之后 , 此时就不能使用事务回滚了 . 但我们可以手动开启一个事务 , 使其可以发生回滚 .
当autocommit=1时, 加 BEGIN 或者 START TRANSACTION 手动开启事务, 可回滚 .

事务的四大特征 - ACID
  • A(原子性) : 一个事务中的所有操作, 要么全部完成, 要么全部不完成, 不会结束在中间某个环节 ;
  • C(一致性) : 在事务开始之前和事务结束之后, 数据库的完整性没有被破坏 ;
  • I(隔离性) : 多个用户并发访问数据库时, 数据库为每一个用户开启的事务, 不能被其它事务的操作所干扰, 多个并发事务之间相互隔离 ;
  • D(持久性) : 一个事务一旦被提交, 它对数据库中数据的修改是永久的, 即便系统故障也不会丢失 .
事务的隔离性(性能从高到低)
  • READ-UNCOMMITTED(读未提交的-脏读)
    一个事务读取了另外一个事务未提交的数据 . 事务A对数据进行了修改 , 但是还未提交 , 另一个事务B可以读到A尚未提交的数据 , 当事务A进行回滚时 , 事务B读到的数据就是脏数据 .
  • 举个栗子 : 小明在淘宝店买了一双鞋 , 付完款之后 , 淘宝店发现钱已到账 , 小明执行ROLLBACK , 数据恢复原样 , 这是脏读-读取未提交的 . 如果执行COMMIT , 则不可ROLLBACK .
  • READ-COMMITTED(读已经提交的-不可重复读)
    同一个事务在事务过程中 , 对同一个数据进行读取操作 , 读取到的结果不同 . 事务B在事务A的更新操作前读到的数据 , 与事务A提交此更新操作后读到的数据 , 可能不同 . 要避免不可重复读 , 需要将事务所操作的记录都加上锁 , 不允许其它事务对此纪录进行写操作 .
  • 举个栗子 : 小明在淘宝店买了一双鞋 , 付完款之后未提交 , 在本地看发现钱已到账 , 淘宝店远程连接 , 发现钱未到账 , 即远程连接查询到的数据只能是已经提交过的 .
  • REPEATABLE-READ(可以重复读-幻读)
    事务A和事务B同时操作一张表 , 事务A提交的数据 , 不能被事务B读到 , 就会造成幻读 .
    举个栗子 : 小张和小王同时操作一张表 , 两人同时各自开启一个新的事务 , 小张添加了一条数据 , 无论他是否COMMIT , 小王都无法看到小张的事务记录 , 会出现 幻读 , 即一个事务提交的数据 , 另一个事务不能读取到 .
  • 串行化(SERIALIZABLE)
    事务序列化 , 前一个事务执行完 , 后面的事务才可以执行, 即同时只能执行一个事务的写入操作 . 因此 , 会导致大量的超时 , 性能差 .

隔离级别越高 , 性能越差 , MySQL默认隔离级别是REPEATABLE-READ .

参考资料目录 :