目录
1、什么是数据库?
数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作(CRUD)。
2、数据库的特点
持久化存储数据的。其实数据库就是一个文件系统 。
2、方便存储和管理数据、存储数据有一定的格式、行和列的格式
3、 使用了统一的方式操作数据库、使用图形界面的形式查看数据、使用sql语言进行查看或管理数据
3、数据库的分类
数据库分为关系型数据库和非关系型数据库,关系型数据库就是我们平常见到的二维表,就是典型的关系型数据库,非关系型数据库存放的数据没有什么联系,所以存储获取效率比较高,一般用于做缓存数据的Redis数据库就是这样的特点。
如下图,就是数据库分类汇总
4、MySQL的登录和退出
4.1、MySQL的登录
本地登录
mysql -u用户名 -p密码 显示登录(密码会被显示出来)
mysql -u用户名 -p 隐式登录(不会显示密码 密码会被*替代 安全性高)
远程连接(指定ip登录)
mysql -h主机地址 -u用户名 -p密码
2、MySQL的退出
三种方式:
exit或quit,或者直接点击DOS窗口的×号。
5、SQL语句
5.1、什么是SQL?
结构化查询语言(Structured Query Language)简称SQL,SQL语句就是对数据库进行操作的一种语言。 SQL是一套标准,所有的数据库厂商都实现了此标准;但是各自厂商在此标准上增加了特有的语句,这部分内容我们称为方言。
5.2、通用语法
SQL语句可以单行或多行书写,以分号结尾
select * from stu; select * FROM stu;
可使用空格和缩进来增强语句的可读性。
MySQL 数据库的 SQL 语句不区分大小写(仅此于win系统),关键字建议使用大写,库名 表名 字段 别名 建议写小写,关键字建议大写: SHOW DATABASES CREATE。
3种注释
单行注释: -- 注释内容(这种方式是通用的) 或 # 注释内容(mysql 特有)
多行注释:
5.3、SQL语句的分类
分类 | 说明 |
---|---|
DDL(Data Definition Language)数据定义语言 | 定义数据库对象:数据库,表,列等.关键字:create, drop,alter 等 |
DML(Data Manipulation Language)数据操作语言(掌握) | 对数据库中表的数据进行增删改.关键字:insert, delete, update 等 |
DQL(Data Query Language)数据查询语言 (掌握) | 用来查询数据库中表的记录(数据).关键字:select, where 等 |
DCL(Data Control Language)数据控制语言(了解) | 用来定义数据库的访问权限和安全级别,及创建用户.关键字:GRANT,REVOKE 等 |
TCL(Transaction Control Language) 事务控制语言 | 用于控制数据库的事务操作,关键字; commit,savepoint,rollback等 |
6、操作数据库——DDL语言
创建数据库
create database 数据库名;
创建数据库,并指定字符集
create database 数据库名 character set 字符集名;
查询所有数据库名称
show databases;
查询某个数据库的字符集,查询某个数据库的创建语句及字符集
show create database 数据库名;
修改数据库的字符集
alter database 数据库名 character set 字符集名;
删除数据库
drop database 数据库名;
查询当前正在使用的数据库名
select database();
使用数据库/进入数据库
use 数据库名;
7、操作表——DDL语言
7.1、数据类型
数据类型 | 说明 |
---|---|
int | 整数类型,例如 : age |
double | 小数类型,例如 : score double(5,2) 111.11 |
date | 日期,只包含年月日,yyyy-MM-dd |
datetime | 日期,包含年月日时分秒 yyyy-MM-dd HH:mm:ss |
timestamp | 时间戳类型,包含年月日时分秒 yyyy-MM-dd HH:mm:ss 如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值 |
varchar | 可变字符 name varchar(20) |
char | 不可变字符 name varchar(20) |
varchar与char的长度区别
varchar的可变是指长度可变,比如定义一个name varchar(20) 但是用户输入了一个"张三"只有两个长度,剩余的18个长度会被系统自动释放,varchar的长度也自动降为2个。
char是固定长度,比如定义一个name char(20) 但是用户同样输入一个"张三" 剩余的18个长度不会被释放,而是用留白符补全,char的长度还是20。
通过比较两者区别,可以得出:
varchar可以自动释放多余空间,避免了存储空间的浪费,一般开发推荐使用varchar。
char固定长度,但性能好,如果定义较大长度会造成储存空间浪费,一般会用于定义性别或者身份证号等固定长度的字段。
7.2、创建表
语法
create table 表名( 字段名 数据类型, 字段名 数据类型, .... 字段名 数据类型);
示例
create table student( id int, name varchar(32), birthday date, money double(5,2));
注意事项:最后一个字段定义不用写逗号,其余每一行都要写逗号。
7.3、查询表
查询某个数据库中所有的表
show tables;
查询表结构
desc 表名;
7.4、修改表
column可以省略不写。
7.4.1、添加字段
alter table 表名 add 字段名 数据类型 约束;
默认在表中最后一列添加
alter table 表名 add column 字段名 类型 约束 默认值;
添加为第一行
alter table 表名 add column 字段名 类型 约束 默认值 first;
添加到指定字段之后
alter table 表名 add column 字段名 类型 约束 默认值 after 字段名;
实例
alter table student add height double(4,1);
7.4.2、修改列(字段)类型
alter table 表名 modify 列名 新类型;
实例
alter table student modify height int;
7.4.3、修改列(字段)名和类型
alter table 表名 change 旧列名 新列名 新类型;
实例
alter table student change height width double(4,1);
7.4.4、删除指定列(字段)
alter table 表名 drop 列名;
实例
alter table student drop width;
7.4.5、查看表的字符集
show create table 表名;
7.4.6、修改表字符集
alter table 表名 charset 字符集名;
实例
alter table student charset gbk;
7.4.7、修改表名
rename table 旧表名 to 新表名
实例
rename table student to teacher
7.4.8、删除字段
alter table 表名 drop column 字段名;
7.5、删除表
7.5.1、直接删除表
drop table 表名;
7.5.2、如果表存在就删除
drop table if exists 表名;
8、约束
约束:规定,限制。限制表中列的内容。需要满足一定的规则。数据库中的约束:限制列的内容。
意义:保证数据的有效性和完整性。可以确保数据库满足业务规则。
约束 | 说明 |
---|---|
primary key | 主键约束:非空且唯一 |
not null | 非空约束 : 某一列的值不能为空 |
unique | 唯一约束 : 某一列的值不能重复,但可以为空 |
auto_increment | 自增器,每一次+1 |
foreign key | 外键约束 |
8.1、主键约束(primary key)
限定当前字段中存放的值 非空且唯一,该约束,一张表只能存在一个。
说明:constraint 约束名 可以省略不写,这里只是给约束起名字,不影响约束创建。
列级约束(限定一个字段下的内容,声明字段时,在字段之后使用)
create table 表名( 字段 类型 primary key, .... 字段 类型);
表级约束
create table 表名( 字段 类型, 字段 类型, ..... 字段 类型, constraint 约束名 primary key(字段));
组合唯一
create table 表名( 字段 类型, 字段 类型, .... 字段 类型, constraint 约束名 primary key(字段1,字段2));
8.2、非空约束(not null)
限定字段中不能存入空值 not null
create table 表名( 字段 类型 not null, 字段 类型 not null, .... 字段 类型);
8.3、唯一约束(unique)
限定字段中不能存入重复值,不包含null
列级约束
create table 表名( 字段名 类型 unique, 字段名 类型 unique, .... 字段名 类型);
表级约束
create table 表名( 字段 类型, 字段 类型, ..... 字段 类型, constraint 约束名 unique(字段), constraint 约束名 unique(字段));
组合唯一
create table 表名( 字段 类型, 字段 类型, .... 字段 类型, constraint 约束名 unique(字段1,字段2));
8.4、外键约束(foreign key)
建立表与表之间的关系,限定从表中的外键字段的值只能依赖主表中的关联字段设置。
注意事项
添加数据时 必须先添加主表信息,后添加从表信息
2、删除数据时,必须先删除从表信息,再删除主表信息
3、外键字段的数据类型必须与主表关联字段类型一致
4、只能关联主表中的主键字段或被唯一约束的字段
列级约束(MySQL中失效)
create table 表名( 字段 类型 references 主表名(字段), ...... 字段 类型 );
表级约束
create table 表名( 字段 类型, ......... 字段 类型, constraint 约束名 foreign key(字段), references 主表名(字段));
组合外键
create table 表名( 字段 类型, ......... 字段 类型, constraint 约束名 foreign key(字段1,字段2), references 主表名(字段1,字段2));
8.5、检查约束(check)
给字段提供筛选条件。在mysql失效
列级约束
create table 表名( 字段 类型 check(字段条件), 字段 类型 check(字段条件and/or字段条件) );
实例
create table student( id int, name varchar(20), sex char(1) check(sex='男' or sex='女') );
表级约束
create table 表名( 字段 类型 , 字段 类型 , .... 字段 类型, constraint 约束名 check(字段条件));
组合约束
create table 表名( 字段 类型 , 字段 类型 , .... 字段 类型, constraint 约束名 check(字段条件1 and 字段条件2 or 字段条件3));
8.6、自增长(auto_increment)
产生一个每次增加1的序列
注意
自增长一张表中只能设置一个。
2、自增长只能设置在主键约束或者唯 一约束字段上。
3、该序列一旦使用会持续往后增长,不会自动回到之前的序号。
create table 表名( 字段 类型 primary key auto_increment, ....... 字段 类型 );
8.7、缺省约束 默认值(default)
未给字段输入值时,使用默认值填充
create table 表名( 字段 类型 default 值, 字段 类型 default 值, ..... 字段 类型);
注意: 默认值必须与字段类型一致。
8.8、给表中字段添加约束
8.8.1、给表中字段添加主键约束
alter table 表名 add constraint 约束名 primary key(字段名);
8.8.2、给表中字段添加非空约束
alter table 表名 modify 字段名 类型 not null;
8.8.3、给表中字段添加唯一约束
alter table 表名 add constraint 约束名 unique(字段名);
8.8.4、给表中字段添加外键约束
alter table 表名 add constraint 约束名 foreign key(字段名) references 主表名(字段名);
8.8.5、删除表中的约束
删除表中的主键约束
alter table 表名 drop primary key;
删除表中的唯一约束
alter table 表名 drop index 约束名;
删除非空约束
alter table 表名 modify 字段名 类型 null;
删除外键约束
alter table 表名 drop foreign key 约束名;
查询字段约束的详细信息
select * from information_schema.table_constraints where table_name='表名';
9、数据操作DML
9.1、添加数据(insert into)
全字段,单行数据添加
insert into 表名 value(值1,值2,...值n);
注意:值的个数、值的顺序、值的类型必须与表中的字段一致,如果某个字段不需要添加值,则以null占位。
部分字段添加数据
insert into 表名(字段名,字段名) value(值1,值2);
注意:值的个数、值的顺序、值的类型 必须与表名后指定的字段一致。
多行数据添加
insert into 表名 values(值1,....值n),(值1...值n),....(值1...值n);
复制添加
insert into 表名 select 字段,....字段 from 表名;
注意事项:
1、查询的字段个数、字段类型、字段顺序要与表中字段一一对应。
2、不能违反添加数据的表中的约束条件。
9.2、修改数据(update)
对指定字段下的所有值进行修改
update 表名 set 字段名1=值,字段2=值;
修改指定行的信息
update 表名 set 字段名=值 where 条件;
9.3、删除数据(delete)
清空表中数据,可通过 rollback 找回。
delete from 表名;
截断表,不可通过rollback找回,删除数据的速度特别快。
truncate table 表名;
删除部分数据
delete from 表名 where 条件;
10、数据查询DQL
10.1、单表查询
查询所有字段
select * from 表名;
查询部分字段
select 字段1,.... 字段n from 表名;
去重查询(distinct)
select distinct 字段 from 表名;
排序查询(order by),默认为升序排序
select * from 表名 order by 字段名;
降序排序 desc
select * from 表名 order by 字段名 desc;
多字段排序
select * from 表名 order by 字段1,字段2...字段n;
注意:
1、多字段排序时,第一个字段中重复的内容再根据第二个字段排序,第二个字段如果依然有重复,再根据后续字段进行排序。
2、多字段排序时如果每个字段都需要进行降序排序,则每个字段后都需要 desc
单条件查询
比较运算符进行条件设置
条件判断 | 说明 |
---|---|
= | 恒等 |
!= | 非等 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
where 字段>值 | 字段大于判断 |
where 字段<值 | 字段小于判断 |
2、betweent and 范围查询
select * from 表名 where 字段 between 值 and 值;
等同于
select * from 表名 where 字段>=值 and 字段<=值;
空值查询和非空值查询
空值查询
select * from 表名 where 字段 is null;
非空查询
select * from 表名 where 字段 is not null;
注意:
0、"null"、“NULL” 都不是 null
模糊查询 like
配合通配符使用 %或_ ,%:任意长度任意字符。 _: 匹配单个任意字符。
select * from 表名 where 字段 like “关键词%”;
包含查询 in 和 not in
字段的值只要符合()中的任意一个值即成立。
in
select * from 表名 where 字段 in (值1,值2,....值n);
等同于
select * from 表名 where 字段 =值1 or 字段=值2 or....字段=值n;
not in
select * from 表名 where 字段 not in (值1,值2,....值n);
等同于
select * from 表名 where 字段 !=值1 and 字段!=值2 and ....字段!=值n;
多条件查询
1、分组查询(group by)
select 分组字段 from 表名 group by 分组字段;
进行分组筛选
select 分组字段 from 表名 group by 分组字段 having 条件;
having 之后的条件只能通过分组字段或聚合函数进行设置,可以在 group by 之前写 where 条件查询,但是含义不同。
2、聚合函数查询
统计数量count(*),求字段中的最大值max(字段名),求字段中的最小值min(字段名),求字段中值的和sum(字段名),求平均值avg (字段名),通常,聚合函数和聚合函数一起使用,或和分组字段一起使用。
3、常用函数查询
字符串函数
获取字符串长度
char_length(字段名或字符串)拼接字符串
concat()用来进行字符串拼接
concat(字符串1,字符串2...,字符串n)注意:在mysql中+号不能拼接,字符串中如果为整数,那么会自动转换为整数类型。
截取字符串
substring(字符串或字段名,起始位置,截取长度);
起始位置是从1开始。替换内容
replace(字符串,原有内容,新内容)字符大写形式
upper(字符串)字符小写形式
lower(字符串)把日期字符串解析为日期
str to date ("日期字符串","格式");
日期函数
获取系统日期
now()把日期按照指定格式,转换为字符串
date_format(日期,"格式");%Y 四位年
%y 两位年
%m 月 2位数
%c 月
%d 日
%h 时
%i 分
%s 秒
求两个日期的相差天数
datediff(日期1,日期2);
日期加减
adddate(日期,interval 相加数量 类型);
adddate(日期,interval 2 DAY);
注意:减日期就是把天数改为负数
数学函数
向上取整
ceiling(数字)向下取整
floor(数字)四舍五入取整
round(数字)求次幂
pow(数字,次方)
平方根
SQRT(数字)
4、别名查询
字段别名
给查询结果中的内容指定一个新的字段名称
select 字段 as 别名,字段 as 别名 from 表名;
as 使用在 where 之前,不能用于 where 之后,可以省略,可以使用在 order by 之后。
表别名
多表查询时,替代表名,表名 as 别名,as 可以省略,在 where 之后可以使用。
10.2、多表查询
10.2.1、连表查询
多表查询之无条件多表查询
select * from 表1,表2,表3;
笛卡尔积形式,但是这样查出来的数据没有任何意义。
2、条件筛选查询
select * from 表1,表2 where 表1.字段=表2.字段;
有关联表字段进行相连,与字段的数据有关,与字段的名字无关。
3、连接查询join查询
3.1、外连接
左外连接 left join
select * from 表1 left join 表2 on 表1.字段=表2.字段;
注意:
左表中数据会全部展示,右表中只展示与左表关联的数据。左表中未找到连接信息的数据,则右表部分用 null 填充。
右外连接 right join
select * from 表1 right join 表2 on 表1.字段=表2.字段;
全外连接 full join (mysql中不生效,这里不再整理)
3.2、内连接 inner join
select * from 表1 inner join 表2 on 表1.字段=表2.字段;
注意:内连接只显示符合连接条件的信息,inner可以省略不写。
10.2.2、子查询
一个查询语句中包含其它一个或多个其它查询语句。
例如:查询成绩不及格的学生信息
select * from student where stuid in (select stuid from score where grade < 60)
exists 查询(替代 in 查询)
select * from student where exists ( select * from score where score.stuid = student.stuid and score <60);
not exists 不存在,对exists取反
select * from student where not exists ( select * from score where score.stuid = student.stuid and score <60);
11、用户权限DCL
11.1、创建用户
create user '用户名'@'主机名' identified by '密码';
注意:
主机名:限定客户端登录ip
指定ip:127.0.0.1 (localhost)
任意ip:%
实例
create user 'jack'@'%' IDENTIFIED by 'jack';
11.2、查看权限
show grants for '用户名'@'主机名';
实例
show grants for 'jack'@'%';
11.3、授予权限
11.3.1、授予单个权限
授于 select 单个权限,jack 这个用户对test库的emp表有select操作权限
grant select on test.emp to 'jack'@'%' ;
授予权限后,刷新权限
flush privileges;
11.3.2、授予多个权限
授于 select, update , insert 多个权限,jack 这个用户对test库的emp表
grant select, update , insert on test.emp to 'jack'@'%' ;-- 刷新权限flush privileges;
11.3.3、授予全部、指定的库和表
--授于整个test 库的权限--jack 这个用户对test库下的所有表有操作权限grant all on test.* to 'jack'@'%' ;-- 刷新权限flush privileges;
-- 授于整个test 库的权限-- jack 这个用户对所有库下的所有表有操作权限grant all on *.* to 'jack'@'%' ;-- 刷新权限flush privileges;
11.4、撤销授权
revoke 权限1,权限2... on 数据库名.表名 from '用户名'@'主机名';
演示
-- 撤销jack用户下test库中的emp表的select权限revoke select on test.emp from 'jack'@'%' ;-- 撤销jack用户下test库所有表的select权限revoke select on test.* from 'jack'@'%' ;
11.5、删除用户
drop user '用户名'@'主机名';
演示
drop user 'jack'@'%' ;
11.6、密码管理
11.6.1、超级管理用户的密码修改
修改mysql服务器中自带的mysql数据库的user表下有一个authentication_string修改即可
update user set authentication_string =password('abc') where user='root';
或者以下代码
set password for 'root'@'localhost' = password('abc');
11.6.2、普通用户修改密码
set password=password('新密码');
12、三大范式
12.1、数据库第一范式
数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。(保持数据的原子性)
数据原子性很好理解,就是表中的字段不可再分。符合数据库第一范式的表,每个字段表意明确,看个例子:
这是一张简单的员工信息表,其中有工号、姓名、电话三个字段。通过电话这个字段获得的信息有可能是家庭电话,或是工作地点的电话,或是手机,因此表达的信息并不明确,我们可以改成这样:
第一范式: 必须明确字段
12.2、数据库第二范式
在满足第一范式的基础上,实体的每个非主键属性完全函数依赖于主键属性(消除部分依赖)
主键:主键明确标识了每条记录,一般是一个字段,也可以由两个或两个字段组成。
依赖:对于X的每个值,Y都有一个值与之对应,反过来则不一定不成立,这叫做X函数决定Y,Y函数依赖X(X往往是主键)。
还拿上面的那张表举来说,对于每个工号,都有一个姓名与之对应,即工号决定姓名,姓名依赖工号;但由于员工之间可能有重名,一个姓名可能对应多个工号,所以姓名不能决定工号。
部分依赖:当主键由两个或两个以上字段构成,而表中的某些信息通过主键的一个字段就能唯一确定,我们称这样的依赖关系为部分依赖,比如这个例子:
学生选课(学号,姓名,专业,课程号,课程名,成绩),该表中一个学生可以选多门课,一门课有多个学生。学号和课程号可以唯一确定一条记录,因此用学号和课程号做主键。
表中的姓名、专业通过主键中的学号就能唯一确定,而课程名通过课程号唯一确定,这就是部分依赖,这样的设计不符合第二范式。
不符合第二范式会带来哪些问题呢?
数据信息冗余,可见上表。
增删改会出现问题,比如有一门《微机原理》没有人选,那么由于缺少学号(主键之一)那么这门课就不能出现在表里。
解决方法
让每张表只做每张表的事即可,不要把所有事都集中一块
第二范式:在第一范式的基础上,明确每一张表。
12.3、数据库第三范式
在满足第二范式的基础上,在实体中不存在非主键属性传递函数依赖于主键属性。(表中字段[非主键]不存在对主键的传递依赖)
传递依赖:A依赖于B,B依赖于C,就可以说A依赖C。
在这样一张表中则存在着传递依赖。也就是系名依赖系号,系号依赖学号,那么间接的系名依赖学号,宿舍号、宿舍电话和学号之间也有同样的关系。这样设计表的同样会带来数据冗余,操作异常等问题。那么我们同样可以用关系分解的分解的方法来消除传递依赖,将这张表分成三张表:
第三范式: 在第一范式和第二范式的基础上,让表与表之间建立关系。
13、索引
索引有作用: 提高查询的效率。一般用于数据量比较大的情况下我们建立索引,如果数据量太小也必要去建立索引。
-- 创建索引create index abc on emp(ename);-- 查看索引show index from emp;-- 测试索引select * from emp where ename = "name1577";-- 删除索引drop index abc on emp;
14、横表和纵表的转换
14.1、纵表转横表
首先创建一个表为proper
create table proper( student_name varchar(20), course_name varchar(20), score double);INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('张三', '语文', 67);INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('张三', '数学', 78);INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('李四', '语文', 90);INSERT INTO `proper`(`student_name`, `course_name`, `score`) VALUES ('李四', '英语', 89);
转表
select -- 第一列显示的字段p.student_name,-- 当course_name的名字是‘语文’,把对应的成绩显示sum(case p.course_name when '语文' then p.score end ) as 语文, sum(case p.course_name when '数学' then p.score end ) as 数学, sum(case p.course_name when '英语' then p.score end ) as 英语from proper p -- 对名字进行分组group by p.student_name
14.2、横表转纵表
create table score_horizontal ( student_name varchar(20), chinese varchar(20), math varchar(20), english varchar(20));INSERT INTO `score_horizontal`(`student_name`, `chinese`, `math`, `english`) VALUES ('张三', '67', '78', NULL);INSERT INTO `score_horizontal`(`student_name`, `chinese`, `math`, `english`) VALUES ('李四', '90', NULL, '89');
转表
select s.student_name,'chinese' as 科目,s.chinese as 成绩 from score_horizontal s unionselect s.student_name,'math' as 科目,s.math as 成绩 from score_horizontal sunionselect s.student_name,'english' as 科目,s.english as 成绩 from score_horizontal s;
15、悲观锁和乐观锁
乐观锁是在应用层加锁,而悲观锁是在数据库层加锁(for update)。
乐观锁顾名思义就是在操作时很乐观,这数据只有我在用,我先尽管用,最后发现不行时就回滚。
悲观锁在操作时很悲观,生怕数据被其他人更新掉,我就先将其先锁住,让别人用不了,我操作完成后再释放掉。
悲观锁需要数据库级别上的的实现,程序中是做不到的,如果在长事务环境中,数据会一直被锁住,导致并发性能大大地降低。
一般来说如果并发量很高的话,建议使用悲观锁,否则的话就使用乐观锁。
如果并发量很高时使用乐观锁的话,会导致很多的并发事务回滚、操作失败。
总之,冲突几率大用悲观,小就用乐观。
创建表准备工作
CREATE TABLE t_user ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(255) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;insert into t_user value('1','jack');insert into t_user value('2','rose');insert into t_user value('3','tom');
15.1、行级锁
-- 1、开启事务start transaction;-- 2、开启悲观锁(加锁),这条数据其他人是无法修改的(只针对 update delete 操作加锁)select * from t_user where id = 1 for update;-- 3、新开一个窗口,模拟另一个用户操作-- 对加锁的数据进行修改,此时是无法修改,因为锁没有释放update t_user set name = 'tom' where id = 1;-- 查看数据是否被修改select * from t_user;-- 4、释放锁(事务提交)别人才能操作commit;
15.2、表级锁
-- 1、开启事务start transaction;-- 2、开启悲观锁(加锁),这条数据其他人是无法修改的(只针对 insert update delete 操作加锁)select * from t_user for update;-- 3、打开新窗口模拟另一个用户操作update t_user set name = 'aa' where id = 3; -- 被加锁delete from t_user where id = 3; -- 被加锁insert into t_user values(null,'bb'); -- 被加锁select * from emp; -- 正常操作-- 4、释放锁commit;
16、MySQL引擎
16.1、Innodb引擎
Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别。该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQL后台的完整数据库系统,MySQL运行时Innodb会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎不支持FULLTEXT类型的索引,而且它没有保存表的行数,当SELECT COUNT(*) FROM TABLE时需要扫描全表。当需要使用数据库事务时,该引擎当然是首选。由于锁的粒度更小,写操作不会锁定全表,所以在并发较高时,使用Innodb引擎会提升效率。但是使用行级锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表。
16.2、MyIASM引擎
MyIASM是MySQL默认的引擎,但是它没有提供对数据库事务的支持,也不支持行级锁和外键,因此当INSERT(插入)或UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些。不过和Innodb不同,MyIASM中存储了表的行数,于是SELECT COUNT(*) FROM TABLE时只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么MyIASM也是很好的选择。
16.3、Innodb引擎、MyIASM引擎区别
MyIASM是非事务安全的,而InnoDB是事务安全的
2、MyIASM锁的粒度是表级的,而InnoDB支持行级锁
3、MyIASM支持全文类型索引,而InnoDB不支持全文索引
4、MyIASM相对简单,效率上要优于InnoDB,小型应用可以考虑使用MyIASM
5、MyIASM表保存成文件形式,跨平台使用更加方便
来源地址:https://blog.csdn.net/select_myname/article/details/126314725