首页 > 技术文章 > mysql

czlong 2018-08-17 12:33 原文

一、mysql的常用命令
启动mysql服务与停止mysql服务命令:
net start mysql
net stop mysql

登陆与退出命令:
--
--mysql -h 服务器IP -P 端口号 -u 用户名 -p 密码 --prompt 命令提示符 --delimiter 指定分隔符
--mysql -h 127.0.0.1 -P 3306 -u root -p
退出:quit------exit----\q;
--
-- \s; ------my.ini文件:[mysql] default-character-set=gbk [mysqld] character-set-server=gbk
--
-- prompt 命令提示符(\D:当前日期 \d:当前数据库 \u:当前用户)
--
-- \T(开始日志) \t(结束日志)
--
-- show warnings;
--
-- help() ? \h
--
-- \G;
--
-- select now();
-- select version();
-- select user;
--
-- \c 取消命令
--
-- delimiter 指定分隔符

二、sql及其规范
1. 在数据库系统中,SQL语句不区分大小写(建议用大写) 。但字符串常量区分大小写。建议命令大写,表名库名小写
2. SQL语句可单行或多行书写,以“;”结尾。关键词不能跨多行或简写。
3. 用空格和缩进来提高语句的可读性。子句通常位于独立行,便于编辑,提高可读性。
4. 注释:单行注释:-- 多行注释:/*......*/(js)
5. sql语句可以折行操作
6. DML、DDL、DCL区别
DML(data manipulation language):用来对数据库里的数据进行操作的语言
DDL(data definition language):主要是用在定义或改变表(TABLE)的结构,数据类型,表之间的链接和约束等
初始化工作上,他们大多在建立表时使用
DCL(Data Control Language):是数据库控制功能。是用来设置或更改数据库用户或角色权限的语句
三、数据类型:
大致可以分为三类:数值、日期/时间和字符串(字符)类型。
1.数字
TINYINT --小整数,特别的: MySQL中无布尔值,使用tinyint(1)构造。
SMALLINT
MEDIUMINT
INT\INTEGER --整数类型中的m仅用于显示,对存储范围无限制。int(5),当插入数据2时,select 时数据显示为: 00002
BIGINT
FLOAT --单精度浮点数(非准确小数值),m是数字总个数,d是小数点后个数。
DOUBLE --数值越大,越不准确
DECIMAL --对于精确数值计算时需要用此类型
2.日期/时间
DATE YYYY-MM-DD
TIME HH-MM-SS
YEAR
DATETIME YYYY-MM-DD HH-MM-SS
TIMESTAMP YYYYMMDD HHMMSS
3.字符串
CHAR --定长,规定长度,拿取效率高,即使数据小于m长度,也会占用m长度
VARCHAR # 变长
TINYBLOB
TINYTEXT
BLOB # 二进制
TEXT # 长文本
MEDIUMBLOG
MEDIUMTEXT
LONGBLOB
LONGTEXT
4.枚举类型
enum --size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
5.集合类型
set --SET('a', 'b', 'c', 'd')

四、DDL
1.创建数据库(在磁盘上创建一个对应的文件夹)
create database [if not exists] db_name [character set xxx]
2.查看数据库
show databases;查看所有数据库
show create database db_name; 查看数据库的创建方式
3.修改数据库
alter database db_name [character set xxx]
4.删除数据库
drop database [if exists] db_name;
5.使用数据库
切换数据库 use db_name; -- 注意:进入到某个数据库后没办法再退回之前状态,但可以通过use进行切换
查看当前使用的数据库 select database();

1.创建表
create table tab_name(
field1 type[完整性约束条件],
field2 type,
...
fieldn type
)[character set xxx];

例子:
create table employee(
id int primary key auto_increment ,
name varchar(20),
gender bit default 1, -- gender char(1) default 1 ----- 或者 TINYINT(1)保存状态更多
birthday date,
entry_date date,
job varchar(20),
salary double(4,2) unsigned,
resume text -- 注意,这里作为最后一个字段不加逗号
);

/* 约束:
primary key (非空且唯一) :能够唯一区分出当前记录的字段称为主键!
unique
not null
auto_increment 主键字段必须是数字类型。
外键约束 foreign key */
另法:create table aa(select * from bb) --把数据都复制过来,而外键那些不复制
2.查看表信息
desc tab_name 查看表结构
show columns from tab_name 查看表结构 --效果一样
show tables 查看当前数据库中的所有的表
show create table tab_name 查看当前数据库表建表语句
3.修改表结构
-- (1)增加列(字段)
alter table tab_name add [column] 列名 类型[完整性约束条件][first|after 字段名];
--alter table user add addr varchar(20) not null unique first/after username;
#添加多个字段
alter table users2
add addr varchar(20),
add age int first,
add birth varchar(20) after name;

-- (2)修改一列类型
alter table tab_name modify 列名 新类型 [完整性约束条件][first|after 字段名];
--alter table users2 modify age tinyint default 20;
--alter table users2 modify age int after id;

-- (3)修改列名(可修改类型)
alter table tab_name change [column] 列名 新列名 类型 [完整性约束条件][first|after 字段名];
--alter table users2 change age Age int default 28 first;

-- (4)删除一列
alter table tab_name drop [column] 列名;
-- 删除多列,删一个填一个,都可以
alter table users2
add salary float(6,2) unsigned not null after name,
drop addr;

-- (5)修改表名
rename table 表名 to 新表名;
-- (6)修该表所用的字符集
alter table student character set utf8;

4.删除表
drop table tab_name;
5.修改默认值:ALTER TABLE testalter_tbl ALTER i SET DEFAULT 1000;
删除默认值:ALTER TABLE testalter_tbl ALTER i DROP DEFAULT;

五、表纪录操作DML(不需加表名)
1.增加一条记录insert
/*insert [into] tab_name (field1,filed2,.......) values (value1,value2,.......);*/
insert into employee_new (id,name,birthday,salary) values (1,'yuan','1990-09-09',9000);
insert into employee_new values (2,'alex','1989-08-08',3000);
insert into employee_new (name,salary) values('xialv',1000);
-- 插入多条数据(不带字段时默认全部字段)
insert into employee_new values (4,'alvin1','1993-04-20',3000),(5,'alvin2','1995-05-12',5000);
-- set插入: insert [into] tab_name set 字段名=值
insert into employee_new set id=12,name="alvin3";

2.修改表记录 update tab_name set field1=value1,field2=value2,......[where 语句]

/* UPDATE语法可以用新值更新原有表行中的各列。
SET子句指示要修改哪些列和要给予哪些值。
WHERE子句指定应更新哪些行。如没有WHERE子句,则更新所有的行。*/
update employee_new set birthday="1989-10-24" WHERE id=1;
--- 将yuan的薪水在原有基础上增加1000元。
update employee_new set salary=salary+4000 where name='yuan';

3.删除表纪录
delete from tab_name [where ....]
/* 如果不跟where语句则删除整张表中的数据
delete只能用来删除一行记录
delete语句只能删除表中的内容,不能删除表本身,想要删除表,用drop
TRUNCATE TABLE也可以删除表中的所有数据,词语句首先摧毁表,再新建表。此种方式删除的数据不能在
事务中恢复。*/

-- 删除表中名称为’alex’的记录。
delete from employee_new where name='alex';
-- 删除表中所有记录。
delete from employee_new;-- 注意auto_increment没有被重置:alter table employee auto_increment=1;
-- 使用truncate删除表中记录。(时间快)
truncate table emp_new;
4.表记录之查(单表查询)
-- 查询表达式
SELECT *|field1,filed2 ... FROM tab_name
WHERE 条件
GROUP BY field
HAVING 筛选
ORDER BY field
LIMIT 限制条数

-- (1)select [distinct] *|field1,field2,...... from tab_name
-- 其中from指定从哪张表筛选,*表示查找所有列,也可以指定一个列
-- 表明确指定要查找的列,distinct用来剔除重复行。
-- 查询表中所有学生的信息。
select * from ExamResult;
-- 查询表中所有学生的姓名和对应的英语成绩。
select name,JS from ExamResult;
-- 过滤表中重复数据。
select distinct JS ,name from ExamResult;

-- (2)select 也可以使用表达式,并且可以使用: 字段 as 别名或者:字段 别名
-- 在所有学生分数上加10分特长分显示。
select name,JS+10,Django+10,OpenStack+10 from ExamResult;
-- 统计每个学生的总分。
select name,JS+Django+OpenStack from ExamResult;
-- 使用别名表示学生总分。
select name as 姓名,JS+Django+OpenStack as 总成绩 from ExamResult;
select name,JS+Django+OpenStack 总成绩 from ExamResult;
select name JS from ExamResult; --不加逗号会重命名

-- (3)使用where子句,进行过滤查询。(不能使用重命名)
-- 查询姓名为XXX的学生成绩
select * from ExamResult where name='yuan';
-- 查询英语成绩大于90分的同学
select id,name,JS from ExamResult where JS>90;
-- 查询总分大于200分的所有同学
select name,JS+Django+OpenStack as 总成绩 from
ExamResult where JS+Django+OpenStack>200 ;
-- where字句中可以使用:
-- 比较运算符:
> < >= <= <> !=
between 80 and 100 值在10到20之间
in(80,90,100) 值是10或20或30
like 'yuan%'
/*
pattern可以是%或者_,
如果是%则表示任意多字符,此例如唐僧,唐国强
如果是_则表示一个字符唐_,只有唐僧符合。两个_则表示两个字符:__
*/
-- 逻辑运算符
在多个条件直接可以使用逻辑运算符 and or not

-- (4)Order by 指定排序的列,排序的列即可是表中的列名,也可以是select 语句后指定的别名。
-- select *|field1,field2... from tab_name order by field [Asc|Desc]
-- Asc 升序、Desc 降序,其中asc为默认值 ORDER BY 子句应位于SELECT语句的结尾。
select * from ExamResult order by JS;
-- 对姓李的学生成绩排序输出
select name ,(ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))
总成绩 from ExamResult where name like 'a%' order by 总成绩 desc;

-- (5)group by 分组查询:(可搭配聚合函数使用,select的列名须在分组中,聚合函数中字段不受限制,id分组所有都可select)
-- 注意,按分组条件分组后,每一组不同的聚合函数结果显示同一列,作为列表
-- group by字句,其后可以接多个列名,也可以跟having子句,对group by 的结果进行筛选。
-- 按列的位置字段筛选
select * from order_menu group by 5;
-- 练习:对购物表按类名分组后显示每一组商品的价格总和
select class,SUM(price)from order_menu group by class;
-- 练习:对购物表按类名分组后显示每一组商品价格总和超过150的商品
select class,SUM(price)from order_menu group by class HAVING SUM(price)>150;
/*
having 和 where两者都可以对查询结果进行进一步的过滤,差别有:
<1>where语句只能用在分组之前的筛选,having可以用在分组之后的筛选;
<2>使用where语句的地方都可以用having进行替换,但where效率高
<3>having中可以用聚合函数,where中就不行。
*/
-- GROUP_CONCAT() 函数,连接字符串,下句返回列表
SELECT name,GROUP_CONCAT(name,age),GROUP_CONCAT(JS) from ExamResult GROUP BY name;

-- (6)聚合函数: 先不要管聚合函数要干嘛,先把要求的内容查出来再包上聚合函数即可。
-- (一般和分组查询配合使用)
-- COUNT(列名):统计行的个数
-- 统计总分大于280的人数有多少?
select count(name) from ExamResult
where (ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0))>280;
-- 注意:count(*)统计所有行; count(字段)不统计null值.

-- SUM(列名):统计满足条件的行的内容和
-- 统计一个班级各科分别的总成绩
select sum(JS) as JS总成绩,
sum(Django) as Django总成绩,
sum(OpenStack) as OpenStack from ExamResult;
-- 统计一个班级各科的成绩总和
select sum(ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0))
as 总成绩 from ExamResult;
-- 统计一个班级JS成绩平均分
select sum(JS)/count(*) from ExamResult ;
-- 注意:sum仅对数值起作用,否则会报错。

-- AVG(列名):
-- 求一个班级JS平均分?先查出所有的JS分,然后用avg包上。
select avg(ifnull(JS,0)) from ExamResult;
-- 求一个班级总分平均分
select avg((ifnull(JS,0)+ifnull(Django,0)+ifnull(Database,0)))
from ExamResult ;
-- Max、Min(要想select额外的字段须group by)
-- 求班级最高分和最低分(数值范围在统计中特别有用)
select Max((ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0)))
最高分 from ExamResult;
select Min((ifnull(JS,0)+ifnull(Django,0)+ifnull(OpenStack,0)))
最低分 from ExamResult;

-- 注意:null 和所有的数计算都是null,所以需要用ifnull将null转换为0!
--ifnull(JS,0)

-- with rollup:用来在分组统计数据的基础上再进行统计汇总,即用来得到group by的汇总信息;
group by dep,pos with rollup;

-- (7) 重点:Mysql在执行sql语句时的执行顺序:
from where group by select having order by
-- 分析:
select JS as JS成绩 from ExamResult where JS成绩 >70; ---- 不成功
select JS as JS成绩 from ExamResult having JS成绩 >90; --- 成功
-- (8) limit
SELECT * from ExamResult limit 1;
SELECT * from ExamResult limit 2,5;--跳过前两条显示接下来的五条纪录
--- (9) 使用正则表达式查询
SELECT * FROM employee WHERE emp_name REGEXP '^yu';
SELECT * FROM employee WHERE emp_name REGEXP 'yun$';
SELECT * FROM employee WHERE emp_name REGEXP 'm{2}';

六、外键约束

1、主键:
一张表只能有一个主键,值唯一且不为空,unique and not null,可以设置自增auto_increment
--添加主键
field int PRAMARY KEY
--修改主键
alter table tab_name add primary key(字段名称,...)
--删除主键
alter table users drop primary key;
--主键唯一,自增必须为主键。先去自增,再删主键。
alter table test modify id int; -- auto_increment没了,但这样写主键依然存在,所以还要加上下面这句
alter table test drop primary key;-- 仅仅用这句也无法直接删除主键

多字段联合主键:
primary key(name,id)
-- 主键类型不一定非是整型,如果是多列,则其组合必须唯一。

2、外键
要和关联主键的数据类型保持一致,默认名字:子表_ibfk_1(show create table table_name)
--添加外键
charger_id TINYINT,
[CONSTRAINT fk_name] FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
--修改外键
ALTER TABLE student ADD CONSTRAINT abc
FOREIGN KEY(charger_id)
REFERENCES classcharger(id);
--删除外键
ALTER TABLE student DROP FOREIGN KEY abc;

INNODB支持的ON语句:
外键约束对子表的含义:如果在父表中找不到候选键,则不允许在子表上进行insert/update
外键约束对父表的含义:创建外键关系时,可指定:
--外键的级联删除:如果父表中的记录被删除,则子表中对应的记录自动被删除
FOREIGN KEY (charger_id) REFERENCES ClassCharger(id) ON DELETE CASCADE
--在父表上update/delete记录时,将子表上匹配记录的列设为null,前提该外键列不能为not null
ON DELETE SET NULL
--Restrict方式:拒绝对父表进行删除更新操作(了解)
--No action方式:在mysql中同Restrict,如果子表中有匹配的记录,则不允许对父表对应候选键进行update/delete操作(了解)

七、多表查询
1、连接查询
a.笛卡尔积查询
SELECT * FROM employee,department; --employee的每一行都对应department的所有行
b.内连接(表顺序没关系)
-- 查询两张表中都有的关联数据,相当于利用条件从笛卡尔积结果中筛选出了正确的结果。
select * from employee,department where employee.dept_id = department.dept_id;
select * from employee inner join department on employee.dept_id = department.dept_id;
c.外连接
-左外连接:在内连接的基础上增加左边有右边没有的结果
select * from employee left join department on employee.dept_id = department.dept_id;
-右外连接:在内连接的基础上增加右边有左边没有的结果
select * from employee RIGHT JOIN department on employee.dept_id = department.dept_id;
-全外连接:在内连接的基础上增加左边有右边没有的和右边有左边没有的结果
--mysql不支持全外连接 full JOIN,可以间接实现全外连接
select * from employee RIGHT JOIN department on employee.dept_id = department.dept_id
UNION
select * from employee LEFT JOIN department on employee.dept_id = department.dept_id;
2、复合条件连接查询
在连接查询的基础上添加AND\ORDER BY\DISTINCT等
3、子查询
将一个查询语句嵌套在另一个查询语句中,内层查询语句的查询结果,可以为外层查询语句提供查询条件。
--子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
--还可以包含比较运算符:= 、 !=、> 、<等
a.带IN关键字的子查询
select * from employee where dept_id IN (select dept_id from department);
b.带比较运算符的子查询
select dept_id,dept_name from department where dept_id IN
(select DISTINCT dept_id from employee where age>=25);
c.带EXISTS关键字的子查询
--返回一个真假值。Ture或False。Ture时,外层查询语句将进行查询;False时,外层查询语句不进行查询。
select * from employee WHERE EXISTS (SELECT dept_name from department where dept_id=203);

八、索引
创建和维护消耗时间和硬盘,但查询速度大大提高
创建索引:CREATE TABLE 表名(
字段名 类型[完整性约束条件],
[UNIQUE|FULLTEXT|SPACIAL] INDEX|KEY [索引名] (字段名)
)
添加索引:
CREATE [UNIQUE|FULLTEXT|SPACIAL] INDEX|KEY 索引名 ON 表名(字段名)
ALTER TABLE 表名 ADD [UNIQUE|FULLTEXT|SPACIAL] INDEX|KEY 索引名 (字段名)
删除索引:
DROP INDEX 索引名 ON 表名
查看索引
show index from table_name;
1、id
id具有唯一性,unique,索引的一种
2、属性unique
具有unique属性的字段按照唯一索引来创建
3、普通索引INDEX或者KEY
INDEX index_name(name)
4、唯一索引
UNIQUE INDEX index_name(name)
5、主键索引
primary key --alter table 表名 add primary key(列名);
5、全文索引
--一般给大文本索引
FULLTEXT INDEX index_name(name)
6、多列索引
--比逐个创建效果高,查询效率低,多个列查询时共享一个索引,其应用场景为:频繁的同时使用n列来进行查询
--对于同时搜索n个条件时,组合索引的性能好于多个单一索引合并。查询单个resume不使用索引
INDEX index_name(name,resume)

注意:对于创建索引时如果是BLOB 和 TEXT 类型,必须指定length。

--创建多行数据
delimiter $$ --更改结束符
create procedure autoinsert()
BEGIN
declare i int default 1; --declare声明,set设置值
while(i<50000)do --类似的函数有if,repeat until,loop_label:loop
insert into Indexdb.t1 values(i,'yuan');
set i = i+1;
end while;
END$$
delimiter ; --改回来

call autoinsert();

九、视图
视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时
只需使用【名称】即可获取结果集,并可以将其当作表来使用。
1、创建视图
CREATE VIEW v1 AS SELET nid,name FROM A WHERE nid > 4
2、删除视图
DROP VIEW v1
3、修改视图
ALTER VIEW v1 AS
4、使用视图
由于视图是虚拟表,所以无法使用其对真实表进行创建、更新和删除操作,仅能做查询用。
select * from v1

十、触发器
1、基本语法
a.插入前
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
...
END
b.插入后
CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
c.删除前
CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW
d.删除后
CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW
e.更新前
CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW
f.更新后
CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW

示例:
delimiter //
CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
BEGIN
IF NEW. NAME == 'alex' THEN
INSERT INTO tb2 (NAME)
VALUES
('aa')
END
END//
delimiter ;
特别的:NEW表示即将插入的数据行,OLD表示即将删除的数据行。
2、删除触发器
ROP TRIGGER tri_after_insert_tb1;
3、使用触发器
--触发器无法由用户直接调用,而知由于对表的【增/删/改】操作被动引发的。
insert into tb1(num) values(666)




2018/08/15 周三

一、Pymysql

import pymysql
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='',db='czl')

#更改获取数据结果的数据类型,默认是元组,可以改为字典等
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) #游标对象,具体的sql语句通过这个执行

sql ="""CREATE TABLE test(

id INT PRIMARY KEY auto_increment,
name VARCHAR (20),
charger_id TINYINT,
FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
) ENGINE=INNODB;
"""

# cursor.execute(sql)
# row_affected = cursor.execute("INSERT INTO test values (3,'wupeiqi',2),(4,'czl',1)")
# print(row_affected) # 影响行数

res = cursor.execute("select * from test") # 默认返回行数
print(cursor.fetchone())
cursor.scroll(-1,mode='relative') # 相对第几个位置
cursor.scroll(1,mode='absolute') # 绝对位置,第几个位置
print(cursor.fetchmany(2)) # 取多条,注意游标在动
print(cursor.fetchall())

conn.commit() # 提交数据需要commit
cursor.close()
conn.close()

二、事务
1、事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。
2、命令:
-- start transaction 开启事务
-- Rollback 回滚事务,即撤销指定的sql语句(只能回退insert delete update语句),回滚到上一次commit的位置
-- Commit 提交事务,提交未存储的事务
-- savepoint 保留点 ,事务处理中设置的临时占位符 你可以对它发布回退(与整个事务回退不同)

savepoint delete2;
rollback to xxx;

注意的点:开启事务后,修改生效,但还没提交。再打开一个新客户端可查询没变

3、pymysql中:
import pymysql
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='',db='czl')

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) #游标对象,具体的sql语句通过这个执行
try:
insertSQL0="INSERT INTO test (name,account) VALUES ('oldboy',4000)"
insertSQL1="UPDATE test set account=account-30 WHERE id=1"
insertSQL2="UPDATE test set account=account+30 WHERE id=2"

cursor.execute(insertSQL0)
conn.commit()

cursor.execute(insertSQL1)
raise Exception
cursor.execute(insertSQL2)
cursor.close()
conn.commit()

except Exception as e:
conn.rollback()
conn.commit()

cursor.close()
conn.close()

4、特性:
a.原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

b.一致性(Consistency):事务前后数据的完整性必须保持一致。在事务执行之前数据库是符合数据完整性约束的,
无论事务是否执行成功,事务结束后的数据库中的数据也应该是符合完整性约束的。在某一时间点,
如果数据库中的所有记录都能保证满足当前数据库中的所有约束,则可以说当前的数据库是符合数据完整性约束的。

c.隔离性(Isolation):事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务
所干扰,多个并发事务之间数据要相互隔离。

d.持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,
接下来即使数据库发生故障也不应该对其有任何影响。

5、隔离性:
不考虑隔离性可能出现的问题:
- 脏读:--一个事务读取到了另一个事务未提交的数据,这是特别危险的,要尽力防止。
- 不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同。
- 虚读:在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。

四个隔离级别:
Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)
Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读)不可以避免虚读
Read committed:可避免脏读情况发生(读已提交)
Read uncommitted:最低级别,以上情况均无法保证。(读未提交)

安全性考虑:Serializable>Repeatable read>Read committed>Read uncommitted
数据库效率:Read uncommitted>Read committed>Repeatable read>Serializable

一般情况下,我们会使用Repeatable read、Read committed mysql数据库默认的数据库隔离级别Repeatable read

mysql中设置数据库的隔离级别语句:
set [global/session] transaction isolation level xxxx;










推荐阅读