1、基础
1、安装
1、MySQL服务的启停
systemctl start mysql
2、设置开机自启动
chkconfig mysql on
3、查看linux的运行级别
cat /etc/inittab
4、查看服务
ntsysv
2、MySQL的安装位置
硬盘上如何存储数据库的基础信息
- datadir:所有的数据库信息都会存放在这里。
路径 | 解释 | 备注 |
---|---|---|
/var/lib/mysql | datadir数据文件存放路径 |
3、修改配置文件
MySQL的默认配置文件为:my-huge.cnf/my-default.cnf
MySQL默认使用/etc/my.cnf文件
每一个表对应的文件都是*.ipd文件
修改MySQL的编码格式:# 服务端使用的字符集默认为8比特编码的latin1字符集 character-set-server=utf8
查看字符编码:show variables like '%char%';
[client]
no-beep
socket =/software/mysql/mysql.sock
#pipe
#socket=0.0
port=3306
[mysql]
default-character-set=utf8 # 设置为utf-8
[mysqld]
basedir=/software/mysql
datadir=/data/mysql
port=3306
pid-file=/software/mysql/mysqld.pid
#skip-grant-tables
skip-name-resolve
socket = /software/mysql/mysql.sock
character-set-server=utf8
default-storage-engine=INNODB
explicit_defaults_for_timestamp = true
#Server Id.
server-id=1
max_connections=2000
query_cache_size=0
table_open_cache=2000
tmp_table_size=246M
thread_cache_size=300
#limit stack
thread_stack = 192k
key_buffer_size=512M
read_buffer_size=4M
read_rnd_buffer_size=32M
innodb_data_home_dir = /data/mysql
innodb_flush_log_at_trx_commit=0
innodb_log_buffer_size=16M
innodb_buffer_pool_size=256M
innodb_log_file_size=128M
innodb_thread_concurrency=128
innodb_autoextend_increment=1000
innodb_buffer_pool_instances=8
innodb_concurrency_tickets=5000
innodb_old_blocks_time=1000
innodb_open_files=300
innodb_stats_on_metadata=0
innodb_file_per_table=1
innodb_checksum_algorithm=0
lower_case_table_names=1
back_log=80
flush_time=0
join_buffer_size=128M
max_allowed_packet=1024M
max_connect_errors=2000
open_files_limit=4161
query_cache_type=0
sort_buffer_size=32M # 再不考虑索引的问题,让order by增加查询速度可以适当增大这个值
table_definition_cache=1400
binlog_row_event_max_size=8K
sync_master_info=10000
sync_relay_log=10000
sync_relay_log_info=10000
#default 8M
bulk_insert_buffer_size = 64M
interactive_timeout = 120
wait_timeout = 120
log-bin-trust-function-creators=1
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
#
#include all files from the config directory
#
!includedir /etc/my.cnf.d
4、配置文件
log-bin
:二进制文件,用于主从复制。
log-error
:错误日志文件,记录严重的警告和错误信息,每次启动和关闭的详细信息,默认为关闭的。
查询日志log
:比如慢sql
数据文件
:
- frm文件:存放表的结构
- myd文件:存放的数据 my data
- myi文件:存放的表索引 my index
5、MySQL的架构
存储引擎架构上,插件式的存储引擎架构将查询处理和其他的系统任务以及数据的存储提取想分离
2、02
1、SQL性能优化
1、复现
2、尽量晒擦、磁盘?sql写的问题?
3、执行时间长,等待时间长。
- 有没有建索引
- 有没有使用上索引
- join太多
- 服务器优化参数问题
1、创建索引
- 单值索引
create index idx_user_name on user(name); -- 给user表的那么字段添加索引
idx_name:索引名
- 多值索引
create index idx_user_name_email on user(user, email);
2、sql的执行顺序
3、七种join理论
内连接、外连接、左连接、交叉连接、笛卡尔积、全连接
左连接减去内连接
outer join
outer join and b.key = null
4、Join使用
内连接:AB共有
左连接:A的全部,B不满足补NULL
右链接:B的全部,A不满足补NULL
A独有:B一定是NULL
B独有:A一定是NULL
全部:A左B union B左A
全部独有:B一定是NULL union A一定是NULL(前者左链接,后者右链接)
5、索引 (index)
索引是一种数据结构 B+树
优势:提高数据检索的效率,降低数据库的IO成本、通过索引列对数据进行排序,减低数据排序的成本,降低CPU消耗。
劣势:索引太多,降低修改速度
6、索引分类
1、单值索引
2、唯一索引
所有列的值必须唯一,但是可以为空值
3、复合索引
7、建/不建索引的场所
1、建立
1、主键自动建立唯一索引
2、频繁查找的创建索引
3、外键关系创建索引
4、频繁更新的字段
5、where不用的字段不要用索引
6、排序字段添加索引
7、统计或者分组的字段
2、不建
1、经常增删改不要建
2、数据重复
3、索引的选择性num/sun越接近1,索引效率越高
8、性能优化Explain
使用Explain关键字可以模拟优化其执行SQL查询语句,从而指导MySQL是如何处理你的SQL语句的,分析SQL的执行效率是表结构还是性能瓶颈(CPU\IO\机器不行)
explain
select task.id as id , deduct.estimate_content as estimateContent,task.estimate_status as estimateStatus , deduct.estimate_standard as estimateStandard, deduct.estimate_method as estimateMethod, deduct.estimate_deduct_point as estimateDeductPoint, deduct.estimate_cause as estimateCause, depart.depart_name as departName,depart.contact_person as contactPerson, depart.mobile as mobile, deduct.create_time as createTime ,sum(task.estimate_score) as estimateScore from su_estimate_task_list as task left join su_estimate_task_deduct_list as deduct on task.id = deduct.estimate_method_id left join sys_depart as depart on depart.id = task.depart_id where task.del_flag = '0' and task.estimate_status = '3' and task.create_time > '2012-05-26 07:07:24' and task.create_time < '2027-06-05 07:07:24' and task.template_id = '1524650346326302722' group by task.depart_id ORDER BY task.create_time desc
1、能做什么?
- 表的读取顺序:id越大越先执行,同一组的顺序执行
- 数据读取操作的操作类型
- 哪些索引可以使用
- 表之间的引用
- 每张表有多少行被优化器查询
explain的表头:id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、extra。
字段 | 含义 | 值 |
---|---|---|
id | select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序。 | id相同:加载表执行顺序由上至下 id不行:id值越大执行的有限循序越高,越先被执行 |
select_type | 查询方式 | |
table | 表名;衍生虚表 | id相同的情况下,执行顺序由上至下 |
partitions | ||
type | ||
possible_keys | ||
key | ||
key_len | ||
ref | ||
rows | ||
filtered | ||
extra |
1、id
select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序。
id相同:加载表执行顺序由上至下 id不行:id值越大执行的有限循序越高,越先被执行
2、select_type
SIMPLE | 简单的select查询,查询中不包含子查询或者union |
PRIMARY | 查询中若包含任何复杂的子部分,最外层查询则被标记为(最后加载的) |
SUBQUERY | 在where里面有子查询(select * from t1 where t1.id = select id from t2 …) |
DERIVER | 在from列表中包含的子查询被标记为DERIVER(衍生) MySQL会递归执行这些子查询,把结果放在临时衍生表里。 |
UNION | 若第二个select出现在union之后,则被标记为UNION;若union包含在from子句的子查询中,外层的select将被标记为DERIVED(衍生) |
UNION RESULT | 从union表获取结果SELECT |
3、type:访问类型
最好到最差以此如下:system>const>eq_ref>ref>range>index>all;只要能达到range或者ref级别就可以。
system | 表中只有一条记录 |
const | 表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为匹配一行数据,所以很快就能找到主键置于where列表中,MySQL就能将该查询转换为一个常量;唯一索引查询或者值只有一条 where id = 1。 |
eq_ref | 唯一性索引扫描,对每一个索引建,表中只有一条记录与之匹配。常见于主键或者唯一索引扫描;按照索引只查出来了一条数据。 |
ref | 非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问。他返回所有匹配某个单独值的行,然而,他可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体;本质上相当于按照索引找出了多条符合条件的值。 |
range | 给索引划定一个范围,如果给时间预先划定一个范围,只需要查询指定范围的时间即可。 |
index | Full Index Scan,index和all区别为index类型只遍历索引树,通常比ALL快。 |
all | 全表扫描 |
1、理解const和system的区别
select * from (select * from t1 where id = 1) d
t1为const、d为system:因为t1通过id索引查出了一条数据,d表其实就只有一条数据了,所以d是system,通过索引查出来的t1是cosnt
2、理解const和eq_ref的区别
-- eq_ref用到了索引,但是查出来只有一条记录
EXPLAIN update sys_depart d inner join sys_user u on d.id=u.depart_id set u.org_code=d.org_code
-- 修改的时候,只有其中一条可以和目标修改的数据进行匹配,所以是eq_ref
3、理解ref和eq_ref的区别
-- eq_ref用到了索引,但是查出来只有一条记录
EXPLAIN update sys_depart d inner join sys_user u on d.id=u.depart_id set u.org_code=d.org_code
-- ref :相当于我用到索引了,但是查出了多条数据。他应该是扫描(索引)和查找(查询)的混合体,比如联合索引的时候,只用到其中一个,查出了多个值。
create index idx_user_pwd on t(username,password);
EXPLAIN select * from t where username = '44'
-- 1 SIMPLE t ref idx_user_pwd,idx_id_user idx_user_pwd 768 const 2 100.00 Using index
4、理解range
create index inx_task_start_time on frt_important_work_task(task_start_time)
-- 时间的大于小于
EXPLAIN select * from frt_important_work_task where task_start_time BETWEEN '2022-05-31 11:01:44' and '2022-06-07 11:01:44'
-- 让索引in一个范围
5、理解index
EXPLAIN select id from frt_important_work_task ;
4、possible_keys和keys
1、是否使用到了索引,判断索引是否失效
2、多个索引竞争,MySQL用到了哪个索引
1、possible_keys:指定表中一共有哪些索引可能会用到
2、key:实际上用了哪个索引,查询中若使用了覆盖索引,则该索引尽出现在key列表中
key如果为null,说明索引失效,要么没有索引,要么建了没有用。
情况一:理论上不用索引,但是实际上用了索引
select 后面查询的字段,和我建立的联合索引的字段一一吻合。
情况二:理论上会用到多个索引,实际上用到了一个索引
5、key_len
-
表示索引中使用的字节数,可通过该列计算查询中使用的索引长度。在不损失精确性的情况下,长度越短越好。
-
key_len显示的值为索引字段最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。
6、ref
表之间的引用
显示索引的哪一列被使用了,如果可能的话,通常是一个常数。哪些列或者常量被用于查找索引列上的值。
test.t1.ID:test库的t1表的ID字段。
const:表示具体的常量
7、rows
根据表统计信息及索引的选用情况,大致估算出找到所需的记录所需要读取的行数。
每个表有多少行被优化器查询,越小越好。
8、Extra
包含不适合在其他列中显示,但十分重要的额外信息。
Using filesort | 说明MySQL会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL中无法利用索引完成的排序操作成为“文件排序” |
Using temporary | 排序的时候产生了内部临时表,然后再删除临时表。常见于order by 或 group by |
Using Index | 表示了相应的select操作中使用了覆盖索引,避免了访问表的数据行,效果不错!如果同时出现了using where 表示索引被用来执行索引键值的查找;如果没有using where ,表明索引用来读取数据,而不是查找 |
Using where | 使用where过滤 |
using join buffer | 使用了join缓存,可以适当调大 |
impossible where | where的值总是false,获取不到数据 |
select tables optimized away | 在没有group by子句的情况下,基于索引优化 MIN/MAX 聚合函数操作,不必等到执行阶段在进行计算,查询执行计划生成的阶段即可完成优化 |
distinct | 去重时第一个匹配就收工。 |
Using index condition; Using where; Using temporary; Using filesort
Using where; Using join buffer (Block Nested Loop)
Using where; Using join buffer (Block Nested Loop)
Using where; Using join buffer (Block Nested Loop)
Using where; Using join buffer (Block Nested Loop)
1、Using filesort
常见于where 条件和order by子句作用在不同的列上。
2、Using temporary
排序的时候产生了内部临时表,然后再删除临时表。常见于order by 或 group by
3、Using Index
表示了相应的select操作中使用了覆盖索引,避免了访问表的数据行,效果不错!如果同时出现了using where 表示索引被用来执行索引键值的查找;如果没有using where ,表明索引用来读取数据,而不是查找
覆盖索引
建了几个字段的索引,就查那几个字段,就叫覆盖索引。
9、单表优化
1、范围后索引会索引失效,所以尽可能给等于的范围,不要给范围。
如果有返回不要给返回查询后添加索引,因为范围后索引索引会失效
解决方案:将范围字段的索引删掉,直接给不加范围的字段添加联合索引
10、两表优化
左连接应该在右表中添加索引。左边是驱动表,右边是查找表,所以给右边表添加索引。反之右链接也一样。
如果发现索引不好使,可以将原来的左连接的对调。
11、三表优化
借鉴两表优化,左连接添加右边,让小结果集驱动大的结果集。
总结
1、尽量减少join语句中NestedLoop的循环总次数:永远都是小的结果集驱动大的结果集
2、优化NestedLoop的内层循环
3、保证joinyuju被驱动表上join条件字段已经被索引
4、当无法保证被驱动表的join条件字段被索引且内存资源充足的前提下,不要太吝啬JoinBuffer的设置。
12、索引失效
1、全值匹配,索引怎么建的就怎么用,不要挑着用
2、最佳左前缀法则
- 如果索引了多个列,要遵循最左前缀法则。指的是查询从索引的最左列开始并且不要跳过索引中的列
3、不在索引列上做任何操作(计算、函数、自动或手动的类型转换),会导致索引失效专向全盘扫描
4、存储引擎不能使用索引中范围条件右边的列
5、尽量使用覆盖索引,避免使用select *
6、MySQL在使用不等于、大于、小于时无法使用索引会导致全表扫描
7、is null、is not null也无法使用索引
8、like以通配符开头的也无法使用索引,会导致全表扫描,如果必须要使用百分号加在左边,那么可以使用覆盖索引。
9、字符串不加单引号会导致索引失效
10、少用or,用or连接会导致索引失效。
2、总结
索引大哥不能死,中间兄弟不能断。
索引列上少计算,范围后面全失效。
百分like加右边,字符串要有引号。
3、查询截取分析
分析流程
1、观察,至少跑一天,看看生产的慢SQL情况
2、开启慢查询日志,设置阙值,比如超过5秒的就是慢SQL,并将他抓取出来
3、explain+慢sql分析
4、show profile查询SQL在MySQL服务器里面执行细节和生命周期情况
5、运维经理 or DBA进行SQL数据库服务器的参数调优。
1、查询优化
- 永远小表驱动大表
- 类似嵌套循环Nested Loop
- order by关键字优化
- group by关键字优化
1、in和exists
-- in
select * from A where id (select id from B)
-- exists
select * from A where exists (select 1 from B where B.id = A.id)
如果A的表的数据远小于B表的数据时,可以把in改成exists
EXPLAIN select * from clazz where EXISTS (select 1 from book where clazz.card = book.card);
EXPLAIN select * from book where EXISTS (select 1 from clazz where clazz.card = book.card);
因为前面的from是驱动表,后面是被驱动表,前面表要全部遍历一遍,所以前面的表示小表比较好。
将主查询的结果放到子查询中做条件验证,根据验证结果(True或False)来决定主查询的结果是否得以保留。
in和exists使用哪个?
看前表和后表哪个数据集大,前表大用in,后表大用exists
2、order by优化(Group by优化相似)
-
尽量使用Index方式排序,避免使用FileSort方式
-
尽可能在索引列上完成排序操作,遵照索引建的最佳左前缀
-
如果不在索引列上,filesort有两种算法
- 双路排序
- 单路排序
-
优化策略
EXPLAIN select * from tbA where age > 30 ORDER BY bri
排序的时候,要有带头大哥。
索引:排好序的,如果没有带头大哥,或者排序的时候顺序不对,都不出现filesort
复合索引排序的时候全部使用到了,只有两种情况不会出现fileSort
1、完全按照创建索引的顺序排序
EXPLAIN select * from tbA ORDER BY age , bri
2、按照索引的顺序排倒序
EXPLAIN select * from tbA ORDER BY age desc, bri desc
sort_buffer的长度如果被限制住了,就可能需要多访问几次
可以sql服务器进行调优。
使用排序要注意什么
1、不要使用select * ,如果使用*的话,可能会将sort buffer用完了,导致多次IO操作,所以也可以适当的调整sort_buffer_size的大小。
2、尝试提高max_length_for_sort_data
提高这个参数,会增加改进算的概率。但是如果设置的太高,数据总容量超出sort_buffer_size的概率就会增大,明显症状就是高的磁盘IO操作和低的处理器效率问题。
2、慢查询
默认情况下,MySQL数据库是没有开启慢查询日志,需要我们手动设置参数。
当然,如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会或多或少的带来一定的性能影响。慢查询日志支持将日志记录写入文件。
1、查看慢查询是否开启
show variables like '%slow_query_log%'
2、开启慢查询
set global slow_query_log = 1 -- 只会针对当前mysql生效,重启就不失效
3、查看什么样的sql被定义为慢sql
show variables like 'long_query_time%'
/usr/sbin/mysqld, Version: 8.0.28 (MySQL Community Server - GPL). started with:
Tcp port: 4406 Unix socket: /var/lib/mysql/mysql.sock
Time Id Command Argument
# Time: 2022-06-11T04:34:26.309998Z
# User@Host: root[root] @ localhost [] Id: 29
# Query_time: 4.000748 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 1
use db01;
SET timestamp=1654922062;
select sleep(4);
3、mysql日志分析工具
mysqldumpslow
[root@localhost datadir]# mysqldumpslow --help
Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]
Parse and summarize the MySQL slow query log. Options are
--verbose verbose
--debug debug
--help write this text to standard output
-v verbose
-d debug
-s ORDER what to sort by (al, at, ar, c, l, r, t), 'at' is default
al: average lock time
ar: average rows sent
at: average query time
c: count
l: lock time
r: rows sent
t: query time
-r reverse the sort order (largest last instead of first)
-t NUM just show the top n queries
-a don't abstract all numbers to N and strings to 'S'
-n NUM abstract numbers with at least n digits within names
-g PATTERN grep: only consider stmts that include this string
-h HOSTNAME hostname of db server for *-slow.log filename (can be wildcard),
default is '*', i.e. match all
-i NAME name of server instance (if using mysql.server startup script)
-l don't subtract lock time from total time
4、大数据集插入
函数有返回值,存储过程没有返回值
1、建表
-- 批量插入数据
-- 1、建表
create table dept (
id int UNSIGNED PRIMARY key auto_Increment,
deptno MEDIUMINT UNSIGNED not null default 0,
dname VARCHAR (20) not null DEFAULT "",
loc VARCHAR (12) not null DEFAULT ""
)
select * from dept;
create table emp (
id INT UNSIGNED PRIMARY KEY auto_Increment,
empno VARCHAR (20) not null DEFAULT "",
ename VARCHAR(20) NOT NULL DEFAULT "",
job VARCHAR(9) NOT NULL DEFAULT "",
mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
hiredate DATE NOT NULL,
sal DECIMAL(7,2) NOT NULL,
comm DECIMAL(7,2) NOT NULL,
deptno VARCHAR (20) not null DEFAULT ""
)
select * from emp
2、设置参数log_bin_trust_function_creators
-- 查看
show variables like '%log_bin_trust_function_creators%';
-- 设置开启
set global log_bin_trust_function_creators = 1
3、创建函数,保证每条数据都不同
- 随机产生字符串
- 随机生成部门编号
DELIMITER $$
CREATE FUNCTION rand_string ( n INT ) RETURNS VARCHAR ( 255 ) BEGIN
DECLARE
chars_str VARCHAR ( 100 ) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
DECLARE
return_str VARCHAR ( 255 ) DEFAULT '';
DECLARE
i INT DEFAULT 0;
WHILE
i < n DO
SET return_str = CONCAT( return_str, SUBSTRING( chars_str, FLOOR( 1+RAND () * 52 )), 1 );
SET i = i + 1;
END WHILE;
RETURN return_str;
END $$
DELIMITER $$
CREATE FUNCTION rand_num () RETURNS INT ( 5 ) BEGIN
DECLARE
i INT DEFAULT 0;
SET i = FLOOR( 100+RAND ()* 10 ) RETURN i;
END $$
4、创建存储过程
- 向emp表中插入数据的存储过程
DELIMITER $$
CREATE PROCEDURE insert_emp (
IN START INT ( 10 ),
IN max_num INT ( 10 )) BEGIN
DECLARE
i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO emp ( empno, ename, job, mgr, hiredate, sal, comm, deptno )
VALUES
((
START + i
),
rand_string ( 6 ),
'SALESMAN',
0001,
CURDATE(),
2000,
400,
rand_num ());
UNTIL i = max_num
END REPEAT;
COMMIT;
END $$
- 向dept表中插入数据的存储过程
DELIMITER $$
CREATE PROCEDURE insert_emp (
IN START INT ( 10 ),
IN max_num INT ( 10 )) BEGIN
DECLARE
i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO dept ( `deptno`, `dname`, `loc` )
VALUES
( ( START + i ), rand_string ( 10 ), rand_string ( 8 ) );
UNTIL i = max_num
END REPEAT;
COMMIT;
END $$
5、调用 call insert_dept(100,10);
5、show profile
1、show profile是mysql提供可以用来分析当前绘画中语句执行的资源消耗情况。可以用于SQL的调优测量。
2、默认情况下关闭,保存最近15词的运行结果。
-- 查看
show variables like 'profiling';
-- 开启
set profiling = on;
3、查看历史15条执行记录
show profiles;
4、分析诊断SQL
show profile cpu,block io for query 132;
以下四个参数出现说明SQL有问题
6、全局查询日志
只能在测试环境用,永远不要在生产开启
set global general_log = 1;
-- 取表
set global log_output='TABLE';
设置以后,编写的sql语句,将会记录到mysql库里的general_log表,可以用一下命令查看
select * from mysql.general_log;
4、锁
1、分类
操作类型分类
- 读锁
- 写锁
操作的粒度
- 表锁
- 行锁
三表:
- 表锁:锁住整张表,偏向于开销小,枷锁快,无死锁,锁定力度大,发生冲突概率最高,并发度最低
- 行锁:锁住一行或者多行
- 页锁
1、表锁
锁住整张表,偏向于开销小,枷锁快,无死锁,锁定力度大,发生冲突概率最高,并发度最低
-- 添加一个表锁
lock table tableName read(write), tableName read(write), 其他;
-- 查看表上加过的锁
show open tables;
-- 释放锁
unlock tables;
-
读锁:如果添加了读锁,就只能读当前锁住的表,不能读、不能修改别的表。别的session去读这个被锁的表,那么就会出现阻塞。需要给当前表解锁以后,才可以实现其他session的读操作。
-
写锁:自己可以读自己锁的表,自己可以修改自己锁的表,当前session不能操作别已经被锁住的表;别的session来操作当前表,读和写对于别的session都不能操作。
2、行锁
如何锁一行
begin;
select * from test where a = 8 for update;
commit;
查看行锁
show status like 'innodb_row_lock%'
事务问题
偏向于innoDB存储引擎,开销大,加锁慢,锁的粒度小,发生冲突概率低,并发度也很高。数据库的事务以及ACID属性。
并发事务处理带来的问题
-
更新丢失:数据覆盖,当两个或者多个session同时选择到同一个数据同一时刻的值进行修改,回写回来就可能会造数据覆盖。
-
脏读:事务A读到了事务B已修改但是未提交的数据,如果事务B回滚,事务A读取的数据是无效的。
-
不可重读:事务A读到了事务B已提交的修改数据。不符合隔离性。
-
幻读:事务A读到了事务B的新增数据。
事务隔离级别
读数据一致性允许的并发副作用隔离级别 | 读数据一致性 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|---|
读未提交(RU) | 最低级别,只能保证不读取物理上所怀的数据 | 是 | 是 | 是 |
读已提交(RC) | 语句级 | 否 | 是 | 是 |
可重复读(RR) | 事务级 | 否 | 否 | 是 |
可序列化(S) | 最高级别,事务级 | 否 | 否 | 否 |
查看事务隔离级别: show VARIABLES like 'tx_isolation';
脏读:读不到别的session未提交的数据
innodb存储引擎不会出现脏读
可重复读:事务A读到了事务B提交的数据
innodb默认是不可重复读,session A执行操作时,没有提交,那么session B是不能修改的。
2、索引失效行锁变表锁
索引字段如果不加单双引号,就会出现索引失效,导致行锁变表锁。
3、间隙锁
当使用范围条件,会给符合条件的数据加锁,但是符合条件但是并不存在的数据称为“间隙”