常见的关系型数据库管理系统
- Oracle: 收费的大型数据库,Oracle公司产品
- MySQL: 开源免费的中小型数据库。
- SQL Server: MicroSoft 公司收费的中型数据库。C#、.net等语言常使用
- PostgreSQL: 开源免费中小型数据库
- DB2: IBM公司的大型收费数据库产品 -SQLite: 嵌入式的微型数据库。如:作为Android内置数据库。
- MariaDB: 开源免费中小型数据库。
数据库相关概念
-
数据库
- 存储数据的仓库,数据是有组织的进行存储
- 英文:DataBase,简称 DB
-
数据库管理系统
- 管理数据库的大型软件
- 英文:DataBase Management System, 简称 DBMS
-
SQL
- 英文:Structured Query Language, 简称 SQL,结构化查询语言
- 操作关系型数据库的编程语言
- 定义操作所有关系型数据库的统一标准
- 对于同一个需求,每一种数据库的操作方式可能有所不同,这些我们称之为方言
-
关系型数据库 关系型数据库是建立在关系模型基础上的数据库,简单说,关系型数据库是由多张能相互连接的
二维表组成的数据库- 优点
- 都是使用表结构,格式一致,易于维护
- 使用通用的SQL语言操作,使用方便,可用于复杂查询。
- 数据存储在磁盘中,安全。
- 优点
数据库设置
1. 软件的研发步骤
2. 数据库设计概念
- 数据库设计就是根据业务系统的具体需求,结合我们所选用的DBMS,为这个业务系统构造出最优的数据存储模型。
- 建立数据库中的
表结构以及表与表之间的关联关系的过程 - 有哪些表?表里有哪些字段?表和表之间有什么关系?
3. 数据库设计的步骤
-
- 需求分析(数据是什么?数据具有哪些属性?数据与属性的特点是什么?)
-
- 逻辑分析(通过ER图对数据库进行逻辑建模,不需要考虑我们所选用的数据库管理系统)
-
- 物理设计(根据数据库自身的特点把逻辑设计转换为物理设计)
-
- 维护设计(1.对新的需求进行建表。2.表优化)
表关系
- 一对一
- 如:用户和用户详情
- 一对一关系多用于表拆分,将一个实体中经常使用的字段放一张表,不经常使用的字段放另一张表,用于提升查询性能。
- 一对多
- 如:部门和员工
- 一个部门对应多个员工,一个员工对应一个部门
- 多堆多
- 如:商品和订单
- 一个商品对应多个订单,一个订单包含多个商品
- 实现方式:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
安装MYSQL数据库
使用命令行窗口连接MYSQL数据库
mysql -h 主机IP -P 端口 -u 用户名 -p密码
- 如果没写-h默认就是主机
- 如果没写-P默认就是3306
数据库三层结构
- 所谓安装MYSQL数据库,就是在主机安装一个数据库管理系统(DBMS),这个管理程序可以管理多个数据库。DBMS(database message system)
- 一个数据库中可以创建多个表,以保存数据
- 数据库管理系统(DBMS)
- 表的本质任然是文件
SQL语句分类
- DDL: 数据定义语句
- DML: 数据操作语句(增加、修改、删除)
- DQL: 数据查询语句(select)
- DCL: 数据控制语句(管理数据库)
创建数据库
CREATE DATABASE [IF NOT EXISTS] db_name
[create_spectification [,create_specification]...]
[DEFAULT] CHARACTER SET charset_name |
[DEFAULT] COLLATE collation_name
- CHARACTER SET: 指定数据库采用的字符集,如果不指定字符集,默认utf8
- COLLATE: 指定数据库字符集的校对规则(常用 utf8_bin【区分大小写】、utf8_general_ci【不区分大小写】 默认是 utf8_general_ci)
查看、删除数据库
# 显示数据库语句
SHOW DATABASES
# 显示数据库创建语句
SHOW CREATE DATABASE db_name
# 数据库删除语句
DROP DATABASE [IF EXISTS] db_name
- 在创建数据库、表的时候、为了规避关键字、可以用反引号解决
备份恢复数据库
- 备份
mysqldump -u 用户名 -p -B 数据库1 数据库2 数据库3 > 文件名.sql
- 恢复(需要进入Mysql 命令行执行)
source 文件名.sql
- 备份库的表
mysqldump -u 用户名 -p密码 数据库 表1 表2 表n > 文件名.spl
数据类型
数值类型
| 类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
|---|---|---|---|---|
| TINYINT | 1 Bytes | (-128,127) | (0,255) | 小整数值 |
| SMALLINT | 2 Bytes | (-32 768,32 767) | (0,65 535) | 大整数值 |
| MEDIUMINT | 3 Bytes | (-8 388 608,8 388 607) | (0,16 777 215) | 大整数值 |
| INT或INTEGER | 4 Bytes | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整数值 |
| BIGINT | 8 Bytes | (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 极大整数值 |
| FLOAT | 4 Bytes | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 单精度 浮点数值 |
| DOUBLE | 8 Bytes | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 双精度 浮点数值 |
| DECIMAL | 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 | 依赖于M和D的值 | 依赖于M和D的值 | 小数值 |
在能够满足需求的情况下,尽量使用存储空间小的
-
数值型(bit)
- 基本使用
create table ta (num bit(8));- 细节说明
- bit字段显示时,按照位的方式显示
- 查询的时候任然可以使用添加的数值
- 如果一个值之后0,1可以考虑用bit(1),可以节约空间
- 位类型。M指定位数,默认值1,范围1~64
- 使用不多
-
小数的基本使用
-
float/double [unsigned] float单精度,double 双精度
-
decimal[M,D] [unsigned]
可以支持更加精确的小数位。M是小数位数的总数,D是小数点后面的位数。
如果D是0,则值没有小数点或者分数部分。M最大65.D最大30.如果D被省略,默认是0.如果M被省略,默认是10. -
日期和时间类型
| 类型 | 大小 ( bytes) | 范围 | 格式 | 用途 |
|---|---|---|---|---|
| DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
| TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 时间值或持续时间 |
| YEAR | 1 | 1901/2155 | YYYY | 年份值 |
| DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
| TIMESTAMP | 4 | 1970-01-01 00:00:00/2038结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 | YYYYMMDD HHMMSS | 混合日期和时间值,时间戳 |
- 日期类型的基本使用
create table birthday( t1 date, t2 datetime, t3 timestamp not null default current_timestamp no update current_timestamp );
字符串类型
| 类型 | 大小 | 用途 |
|---|---|---|
| CHAR | 0-255 bytes | 定长字符串 |
| VARCHAR | 0-65535 bytes | 变长字符串 |
| TINYBLOB | 0-255 bytes | 不超过 255 个字符的二进制字符串 |
| TINYTEXT | 0-255 bytes | 短文本字符串 |
| BLOB | 0-65535 bytes | 二进制形式的长文本数据 |
| TEXT | 0-65535 bytes | 长文本数据 |
| MEDIUMBLOB | 0-16777215 bytes | 二进制形式的中等长度文本数据 |
| MEDIUMTEXT | 0-16777215 bytes | 中等长度文本数据 |
| LONGBLOB | 0-4294967295 bytes | 二进制形式的极大文本数据 |
| LONGTEXT | 0-4294967295 bytes | 极大文本数据 |
-
字符串基本使用
- char(size) 固定长度字符串 最大255字符
char(4) 是固定的大小,就是说,即使你插入'aa',也会分配4个字符
- varchar(size) 可变长度字符串 最大65532字节 【uft8 编码最大21844字符 1-3个字节用于记录大小】
varchar(4) 是变长,就是说如果,你插入了'aa',实际占用空间大小并不是4个字符,而是按照实际占用空间类分配【varchar 本身还需占用1-3个字节来记录存放内容的长度】
- 什么时候使用char,什么时候使用varchar
如果数据是定长,推荐使用cahr,比如MD5的密码,邮编,手机号,身份证号码等
如果一个字段的长度是不确定,我们使用varchar,比如留言,文章
创建表
CREATE TABLE table_name (
field1 datatype,
field2 datatype,
field3 datatype
) character set 字符集 collate 校对规则 engine 引擎
field:指定列名 datatype:指定列数据类型(字段类型)
character set:如不指定则为所在数据库字符集
collate:如不指定则为所在数据库校对规则
engine:引擎
- 创建表时,要根据需保存的数据创建相应的列,并根据数据的类型定义相应的列类型。
修改表
- 添加列
alter table tablename
add ( column datatype [default expr]
[, column datatype]...);
- 修改列
alter table tablename
modify (column datatype [default expr]
[, column datatype]...);
- 删除列
alter table tablename
drop (column);
- 修改列名
alter table tablename
change 原列名 新列明 (column datatype [default expr]
[, column datatype]...);
# 查看表结构
desc 表名;
# 修改表名
Rename table 表名 to 新表名;
# 修改表字符集
alter table 表名 character set 字符集;
CRUD
- insert语句
insert into table_name [(colum [, colum...])]
values (value, [,value...]);
- 细节说明
- 插入的数据应与字段的数据类型相同。
- 数据的长度应在列的规定范围内。
- 在values中列出的数据位置必须与被加入的列的排列位置相对应。
- 字符和日期类型数据应包含在单引号中。
- 列可以插入空值[前提\是该字段允许为空], insert into table value(null);
- insert into tab_name (列名) values (), (), () 形式添加多条记录。
- 如果是给表中的所有字段添加数据,可以不写前面的字段名称
- 默认值的使用,当不给某个字段值时,如果有默认值就会添加,否则报错。
- update语句
update table_name
set col_name1=expr1 [, col_name2=expr2 ...]
[where where_definition]
- 使用细节
- update 语法可以用新值更新原有表行中的各列。
- set 子句指示要修改哪些列和要给予哪些值。
- where 子句指定应更新哪些行。如果没有where子句,则更新所有的行。
- 如果需要修改多个字段,可以通过 set 字段1=值1, 字段2=值2...
- delete语句
delete from table_name
[where where_definition]
- 使用细节
- 如果不使用where子句,将删除表中所有数据。
- delete语句不能删除某一列的值 (可使用update设置为null或者‘’)
- 使用delete语句仅删除记录,不删除表本身。如果要删除表,使用drop table语句。
- select语句
select [distinct] * | {colunm1, column2...}
from tablename;
- 注意事项
- select指定查询哪些列的数据。
- column指定列名。
- 代表查询所有列。
- from指定查询哪张表。
- distinct 可选,指显示结果时,是否去掉重复数据。
- 使用表达式对查询的列进行运算
select * | {column1|expression, column2 | expression, 。。。}
from tablename;
- 在select语句中可使用as语句
select columnname as 别名 from 表名;
- 在where子句中经常使用的运算符
| 比较运算符 | > < <= >= =<> != | 大于、小于、大于(小于)等于、不等于 |
| between ...and... | 显示在某一区间的值 | |
| in(set) | 显示在in列表中的值, 例:in(100,200) | |
| like '小%' not like '' |
模糊查询 以'小'开头的 模糊查询 |
|
| is null | 判断是否为空 | |
| 逻辑运算符 | and | 多个条件同时成立 |
| or | 多个条件任一成立 | |
| not | 不成立,例:where not(salary > 100); |
- 使用order by语句排序查询结果
select column1, column2, ...
from table
order by column asc|desc, ...
- order by 指定排序的列,排序的列既可以是表中的列名,也可以是select语句后指定的列名.
- asc升序[默认]、desc 降序
- order by 字句应位于select 语句的结尾。
- 合计/统计函数 - count
select count(*)| count(列名) from table_name
[where where_definition]
count(*) 和 count(列)区别
count(*):返回满足条件的记录的行数
count(列):统计满足条件的某列有多少个,但是会排除为null
- 合计函数 - sum
# sum函数返回满足where条件的行的和 -- 一般使用在数值列
select sum(列名) {, sum(列名)...} from tablename
[where where_definition]
- 合计函数 - avg
select avg(列名) {, avg(列名)...} from tablename
[where where_definition]
- 合计函数 - max/min
select max(列名) from tablename
[where where_definition]
- 使用group by 子句对列进行分组
select colunm1,column2,... from tablename
group by column;
- 使用having字句对分组后的结果进行过滤
select cloumn1,column2... from tablename
group by column having ...
- group by 用于对查询的结果分组统计
- having 字句用于限制分组显示结果
- 字符串相关函数
| charsrt(str) | 返回字符串字符集 |
| concat(string,[.....]) | 连接字符串 |
| instr(string, substring) | 返回substring在string中出现的位置,没有返回0 |
| ucase(string) | 转成大写 |
| lcase(string) | 转成小写 |
| left(string,length) | 从string中的左边取length个字符 |
| length(str) 按字节返回 | str长度 |
| replace(str,search_str,replace_str) | 在str中用replace_str替换search_str |
| strcmp(string1, string2) | 逐字符比较两子串大小 |
| substring(str, position, [length]) | 从str的position开始【从1开始计算】,取length个字符 |
| ltrim(string) rtrim(string) trim | 去除前端空格或后端空格 |
dual 亚元表 ,系统表可以作为测试表使用
- 数学相关函数
| abs(num) | 绝对值 |
| bin(decimal_number) | 十进制转二进制 |
| ceiline(num) | 向上取整,得到比num大的最小整数 |
| conv(num, from_base, to_base) | 进制转换 |
| floor(num) | 向下取整,得到比num小的最大整数 |
| format(num, decimal_places) | 保留小数位数 |
| hex(decimalNumber) | 转十六进制 |
| least(num1, num2, [...]) | 求最小值 |
| mod(number, denominator) | 求余 |
| rand([seed]) | 范围 0 <= v <= 1.0 每次返回不同的随机数,如果使用seed,seed不变,随机数也不变 |
- 时间和日期相关函数
| current_date() | 当前日期 |
| current_time() | 当前时间 |
| current_timestamp() | 当前时间戳 |
| date(datetime) | 返回datetime的日期部分 |
| date_add(date, interval d_value d_type) | 在date中加上日期或时间 |
| date_sub(date, interval d_value d_type) | 在date上减去一个时间 |
| datediff(date1, date2) | 两个日期差(结果是天) |
| timediff(date1, date2) | 两个日期差(结果是多少小时多少分多少秒) |
| now() | 当前时间 |
| year|month|date (datetime) from_unixtime() |
年月日 |
date_add() 中的 interval 后面可以是year,minute,second,day 等 datediff(date1, date2) 得到的是天数,而且是date1 - date2 的天数,因此可以取负数
from_unixtime 把时间戳转成格式化时间
- 加密和系统函数
| user() | 查询用户 |
| database() | 数据库名称 |
| md5(str) | 为字符串算出一个md5 32的字符串,(用户密码)加密 |
| password(str) select * from mysql.user \G |
从原文密码str计算并返回密码字符串,通常用于对musql数据库的用户密码加密 |
- 流程控制函数
| if(expr1, expr2, expr3) | 如果expr1为TRUE,则返回expr2 否则返回expr3 |
| ifnull(expr1, expr2) | 如果expr1不为空 null,则返回expr1,否则返回expr2 |
| select case when expr1 then expr2 when expr3 then expr4 else expr5 end; [类似多重分支] |
如果expr1为TRUE,则返回expr2,如果expr3为TRUE,返回expr4,否则返回expr5 |
| password(str) select * from mysql.user \G |
从原文密码str计算并返回密码字符串,通常用于对musql数据库的用户密码加密 |
判断为空 需要使用 is null
判断不为空 需要使用 is not null
- 查询加强
日期类型也可以进行比较
使用like操作符(模糊比较):% 表示0到多个任意字符, _ 表示单个任意字符
desc tablename; 查询表结构
分页查询
select ... limit start, rows
-- 表示从start+1 行开始取,取出rows行,start从0开始
如果select 语句同时包含有group by,having,limit,order by 那么它们的顺序是:group by,having,order by, limit
- 多表查询
多表查询是指基于两个和两个以上的表查询在实际应用中,查询单个表可能不能满足你的需求。
在默认情况下:当两个表查询时,规则
- 从第一张表中,取出一行和第二章表的每一行进行组合,返回结果【含有两张表的所有列】
- 一共返回的记录数 第一张表行数 乘 第二张表行数
- 这样多表查询默认处理返回的结果,称之为笛卡尔集
- 解决这个多表的关键就是要学出正确的过滤条件 where
-
自连接
自连接是指在同一张表的连接查询【将同一张表看做两张表】
需要给表取别名:表名 表别名
列名不明确,可以指定列别名 -
子查询
什么是子查询
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询
单行子查询
单行子查询是值只返回一行数据的子查询语句
多行子查询 多行子查询指返回多行数据的子查询 使用in关键字
- 在多行子查询中使用all操作符
# all表示全部的
select ename,sal from emp where sal > all(
select sal from emp where depno=30
);
- 在多行子查询中使用any操作符
# any表示其中一个
select ename,sal from emp where sal > any(
select sal from emp where depno=30
);
- 多列子查询
多列子查询:返回多个列数据的子查询语句
(字段1,字段2...)=(select 字段1,字段2...)
表复制
- 自我复制数据
有时,为了对某个sql语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据。
# 把旧表的结构复制到新表
create table 新表 like 旧表;
- 表去重
1. 先创建一张临时表temp。该表结构和需要去重的表一样
2. 把需要去重的表的记录,通过distinct关键字处理后,把记录复制到temp表中
3. 清除掉需要去重表的全部记录
4. 把temp表的记录复制到 需要去重的表中
5. drop temp 表
合并查询
有时在实际应用中,为了合并多个select语句的结果,可以使用集合操作符 union,union all
- union all
该操作符用于取得两个结果集的并集。当使用该操作符时,不会取消重复行
- union
该操作符用于取得两个结果集的并集。当使用该操作符时,会去重
mysql 外连接
- 左外连接 (如果左侧表完全显示)
select .. from 表1 left join 表2 on 查询条件;
- 右外连接 (如果右侧表完全显示)
select .. from 表1 right join 表2 on 查询条件;
mysql约束
约束用于确保数据库数据满足特定的商业规则。在MySQL中约束包括:not null,unique,primary key,foreign key和check 五种。
- primary key(主键)
字段名 字段类型 primary key
用于唯一的标识表行的数据,当定义主键约束之后,该列不能重复
primary key 不能重复而且不能为null
一张表最多只能有一个主键,但可以是复合主键
主键的指定方式有两种:
- 直接在字段名后面指定:字段名 primary key
- 在表定义最后写 primary key(列名)
使用desc 表名,可以看到primary key 的情况
- not null(非空)
如果在列上定义了not null,那么当插入数据时,必须为列提供数据
- unique(唯一)
当定义了唯一约束后,该列值是不能重复的,
如果没有指定not null,则unique字段可以有多个null
一张表可以有多个unique字段
- foreign key 外键
用于定义主表和从表之间的关系:外键约束要定义在从表上,主表则必须具有主键约束或者是unique约束,当定义外键约束后,要求外键列数据必须在主表的主键列存在或是为null
foreign key (本表字段名) references
主表名(主键名或者unique字段)
- 外键指向的表的字段,要求是primary key 或者是unique。
- 表的类型是innodb,这样的表才支持外键。
- 外键字段的类型和主键字段的类型一致(长度可以不用)
- 外键字段的值,必须在主键字段中出现过,或者为null【前提是外键字段允许为null】
- 一旦建立外键的关系,数据不能随意删除了,
- check约束
用于强制行数必须满足的条件,假定在sal列上定义了check约束,并要求sal列值在1000
2000之间如果不在10002000之间就会提示出错。
列名 类型 check(check条件)
# mysql 5.7不支持check约束
- 自增长 auto_increment
字段名 类型 primary key auto_increment
insert into xxx(colum1, clomn2) value(null, '值');
# 设有自增长的列,传入null则会自增长
- 一般来说自增长是和primary key 配合使用的
- 自增长也可以单独使用【但需要配合一个unique】
- 自增长修饰的字段为整数型的(也可以小数,但是非常少这样使用)
- 自增长默认从1开始 ,也可以通过alter table 表名 auto_increment = 新的开始值;
- 如果你添加数据时,给自增长字段指定有值,则以指定的值为准。
mysql索引
说起提高数据库性能,索引是最物美价廉的东西了。不用加内存,不用改程序,不用调sql,查询速度就可能提升百倍千倍。
# 创建索引
create index 索引名称 on 表名字(列名字);
- 索引的原理
- 没有索引为什么会慢?
- 因为全表扫描
- 使用索引为什么会快?
- 形成一个索引的二叉树
- 索引的代价
- 磁盘占用空间大
- 对dml(update delete inster)语句的效率影响
- 没有索引为什么会慢?
- 索引的类型
- 主键索引,主键自动的为主索引(类型primary)
- 唯一索引(unique)
- 普通索引(index)
- 全文索引(fulltext)【适用于MyISAM】
一般开发,不使用MySQL自带的全文索引
开发中考虑使用:全文搜索 Solr 和 ElasticSearch(ES)
- 查看索引
show index from table_name;
- 索引使用
- 添加索引
create [unique] index index_name on table_name(col_name[(length)] [ASC|DESC],....);
# 或者
alter table table_name add index [index_name] (index_col_name, ...);
- 添加主键索引
alter table table_name add primary key (col_name,....);
- 删除索引
drop index index_name on table_name;
# 或者
alter table table_name drop index index_name;
- 删除主键索引
alter table table_name drop primary key;
- 在哪些列上适合使用索引
- 较频繁的作为查询条件字段应该创建索引
- 唯一性太差的字段不太适合单独创建索引,即使频繁作为查询条件
- 更新非常频繁的字段不太适合创建索引
- 不会出现在where字句中字段不该创建索引
事务
- 事务简介
- 数据库的
事务(transaction)是一种机制、一个操作序列,包含了一组数据库操作命令 - 事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令
要么同时成功,要么同时失败 - 事务一个不可分割的工作逻辑单元。
-- 开启事务 start transaction # 或者 begin -- 设置保存点 savepoint 保存点名 -- 回退事务 rollback to 保存点名 -- 回滚全部事务 rollback; -- 提交事务,所有操作生效,不能回退 commit; - 数据库的
- 事务和锁
当执行事务操作时(dml语句),MySQL会在表上加锁,防止其他用户改表的数据,这对用户来说非常重要
- 回退事务
在介绍回退事务前,先介绍一下保存点(savepoint),保存点是事务中的点,用于取消部分事务,当结束事务时(commit),会自动删除该事务所定义的所有保存点,当执行回退事务时,通过指定保存点可以回退到指定的点。
- 提交事务
使用commit语句可以提交事务,当执行了commit语句之后,会确认事务的变化、结束事务、删除保存点、释放锁、数据生效。当使用commit语句结束事务之后,其它会话
【其它连接】可以查看到事务变化后的新数据。
- 事务的四大特征
- 原子性(Atomicity):事务是不可分割的最小操作单位,要么同时成功,要么同时失败。
- 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
- 隔离性(Isolation):多个事务之间,操作的可见性
- 持久性(Durability):事务一旦提交或回滚,它对数据库中的改变就是永久的。
- MYSQL事务默认自动提交
-- 查看事务的默认提交方式
select @@autocommit;
-- 1 自动提交 0 手动提交
-- 修改事务提交方式
set @@autocommit = 0;
- 事务的细节
- 如果不开始事务,默认情况下,dml操作是自动提交的,不能回滚。
- 如果开始一个事务,你没有创建保存点,你可以执行rollback,默认就是回退到事务开始的状态。
- 可以在事务没有提交之前,创建多个保存点。
- 可以在事务没有提交之前,选择回退到哪个保存点。
- InnoDB 存储引擎支持事务,MyISAM不支持。
- 事务隔离级别
- 多个连接开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个连接在获取数据时的准确性。
- 如果不考虑隔离性,可能会引发如下问题。
- 脏读(dirty read)
当一个事务读取另外一个事务尚未提交的改变(update,insert,delete)时,产生脏读
- 不可重复读(nonrepeatable read)
同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生不可重复读。
- 幻读(phantom read)
同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻读(一个已经提交的事务影响到了另一个未提交的事务)。
MySQL隔离级别定义了事务与事务之间的隔离程度
| MySQL隔离级别 | 脏读 | 不可重复读 | 幻读 | 加锁读 |
|---|---|---|---|---|
| 读未提交(Read uncommitted) | ✅ | ✅ | ✅ | 不加锁 |
| 读已提交(Read committed) | ❌ | ✅ | ✅ | 不加锁 |
| 可重复读(Repeatable read) | ❌ | ❌ | ❌ | 不加锁 |
| 可串行化(Serializable) | ❌ | ❌ | ❌ | 加锁 |
# 查看事务隔离级别
select @@tx_ioslation;
# 查看系统当前隔离级别
select @@global.tx_ioslation;
# 设置当前会话隔离级别
set session transaction ioslation level repeatable read;
# 设置系统当前隔离级别
set global transaction ioslation level repeatable read;
# mysql 默认的事务隔离级别是 repeatable read,一般情况下,没有特殊要求,有没必要修改(因为该隔离级别可以满足绝大部分项目需求)
- 全局修改,修改my.ini配置文件,在最后加上
#可选参数有:READ-UNCOMMITTED,READ-COMMITTED,REPEATABLE-READ,SERIALIZABLE.
[mysql]
transaction-ioslation = REPEATABLE-READ
表类型和存储引擎
- 基本介绍
- MySQL的表类型由存储引擎(storage engines)决定,主要包括MyISAM、innoDB、Memory等。
- MySQL数据表主要支持六中类型,分别是:CSV、Memory、ARCHIVE、MRG_MYISAM、MYISAM、innoDB。
- 这六种又分为两类,一类是”事务安全型“(transaction-safe),比如:innoDB;其余都是第二类,称为”非事务安全型“(no-transaction-safe)【mysiam和memory】。
# 显示当前数据库支持的存储引擎
show engines;
- MyISAM不支持事务,也不支持外键,但其访问速度快,是事务完整性没有要求。
- innoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是比起MyISAM存储引擎,innoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。
- Memory存储引擎使用存在内存中的内容来创建表。每个Memory表只实际对应一个磁盘文件。Memory类型的表访问速度非常快,因为它的数据是存放在内存中的,并且默认使用HASH索引。但是一旦MySQL服务关闭,表中的数据就会丢失掉,表格结构还在。
- 如何选择表的存储引擎
- 如果你的应用不需要事务,处理的只是基本的CRUD操作,那么MyISAM是不二的选择。
- 如果需要支持事务,选择innoDB。
- Memory存储引擎就是将数据存储在内存中,由于没有磁盘I/O的等待,速度极快。但是由于是内存存储引擎,所做的任何修改在服务器重启后都将消失。【用户的在线状态】
# 修改存储引擎
alter table table_name engine='存储引擎';