MYSQL进阶学习笔记
MySQL在Linux中的使用:
1、查看mysql在linux的安装版本
mysqladmin –version
2、mysql服务的启动与停止
(1)、启动:
service mysql start
(2)、停止:
service mysql stop
数据库的设计范式(防止数据冗余):
关系数据库有六种范式,一般来说,数据库只需满足三大范式即可:
1、第一范式:任何一张表都应有主键,且每一字段原子性不可再分;
2、第二范式:在第一范式基础上,非主键字段不能产生部分依赖(多对多,三张表,关系表两外键);
3、第三范式:在第二范式基础上,非主键字段不能产生传递依赖(一对多,两张表,多的表加外键);
4、第四范式:在第三范式基础上,禁止主键和非主键字段的一对多关系不受约束。
注:在实际开发中,为满足客户的需求,有时会那冗余换执行速度
MySQL的存储引擎:
1、介绍:
数据库存储引擎是数据库底层软件组件,数据库管理系统使用数据引擎进行创建、查询、更新和删除数据操作。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎还可以获得特定的功能。
(1)、查看已提供的存储引擎:
mysql> show engines;
(2)、查看当前默认的存储引擎:
mysql> show variables like '%storage_engine%';
2、存储引擎简介(了解):
(1)、InnoDB存储引擎
InnoDB是MySQL的默认事务型引擎,主要用来处理大量的短期事务。行级锁,适合高并发情况;
(2)、MyISAM存储引擎
MyISAM提供全文索引、压缩、空间函数(GIS)等特性,但MyISAM不支持事务和行级锁(myisam改表时会将整个表全锁住),存在崩溃后无法安全恢复的缺陷。
(3)、Archive引擎
Archive存储引擎只支持INSERT和SELECT操作,在MySQL5.1之前不支持索引。
Archive表适合日志和数据采集类应用。适合低访问量大数据等情况。
(4)、Blackhole引擎
Blackhole引擎没有实现任何存储机制,它会丢弃所有插入的数据,不做任何保存。但服务器会记录Blackhole表的日志,所以可以用于复制数据到备库,或者简单地记录到日志。但这种应用方式会碰到很多问题,因此并不推荐。
(5)、CSV引擎
CSV引擎可以将普通的CSV文件作为MySQL的表来处理,但不支持索引。
CSV引擎可以作为一种数据交换的机制,非常有用。
CSV存储的数据直接可以在操作系统里,用文本编辑器,或者excel读取。
(6)、Memory引擎
如果需要快速地访问数据,并且这些数据不会被修改,重启以后丢失也没有关系,那么使用Memory表是非常有用。Memory表至少比MyISAM表要快一个数量级。
(7)、Federated引擎
Federated引擎是访问其他MySQL服务器的一个代理,尽管该引擎看起来提供了一种很好的跨服务器的灵活性,但也经常带来问题,因此默认是禁用的。
3、MyISAM与InnoDB比对(重):
选择:
(1)、是否要支持事务,如果要请选择innodb,如果不需要可以考虑MyISAM;
(2)、如果表中绝大多数都只是读查询,可以考虑MyISAM,如果既有读也有写,请使用InnoDB。
(3)、系统奔溃后,MyISAM恢复起来更困难,能否接受;
SQL执行顺序:
1、手写SQL顺序:
2、机读SQL顺序:
3、MySQL查询执行路径:
(1)、客户端发送一条查询给服务器;
(2)、服务器先会检查查询缓存,如果命中了缓存,则立即返回存储在缓存中的结果。否则进入下一阶段;
(3)、服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划;
(4)、MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询;
(5)、将结果返回给客户端。
SQL JOIN连接查询解析:
1、SQL JOIN将来自多张表的数据行,根据一定的规则连接起来,形成一张大的数据表。
2、JOIN解析:
(1)、左连接LEFT JOIN:
SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key = B.Key;
(2)、右连接RIGHT JOIN
SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.Key = B.Key;
(3)、内连接INNER JOIN
SELECT <select_list> FROM TableA A INNER JOIN TableB B ON A.Key = B.Key;
(4)、全连接(MySQL不支持FULL JOIN,使用UNION)
SELECT <select_list> FROM TableA A LEFT JOIN TableB B ON A.Key = B.Key
UNION
SELECT <select_list> FROM TableA A RIGHT JOIN TableB B ON A.Key = B.Key;
SQL中FROM多表联查:
SELECT * FROM table_one t1,table_two t2
FROM关键字后面跟多个表的写法等价于内连接写法——取的是数据交集
SQL中drop、delete、truncate删除命令的区别:
1、Delete用来删除表的全部或者一部分数据行,执行delete之后,用户需要提交(commmit)或者回滚(rollback)来执行删除或者撤销删除, delete命令会触发这个表上所有的delete触发器;
2、Truncate删除表中的所有数据,这个操作不能回滚,也不会触发这个表上的触发器,TRUNCATE比delete更快,占用的空间更小;
3、Drop命令从数据库中删除表,所有的数据行,索引和权限也会被删除,所有的DML触发器也不会被触发,这个命令也不能回滚。
注:在不再需要一张表的时候,用drop;在想删除部分数据行时候,用delete;在保留表而删除所有数据的时候用truncate。
JAVA在查询大量数据时,如何提高查询效率:
1、从数据库设计方面考虑:
(1)、建立索引,提高检索效率;
(2)、在数据库设计范式中拿冗余换执行速度;
(3)、创建视图;
(4)、分区(MySQL,比如按时间分区)
(5)、尽量使用固定长度的字段
2、从数据库I/O方面:
(1)、增加缓冲区
(2)、如果涉及表的级联,不同的表存储在不同的硬盘上,以增加I/O读取的速度
3、从SQL语句方面:
(1)、优化SQL语句,减少DML比较的次数
(2)、限制返回的条目数(MySQL中用的limit)
4、从Java代码方面:
(1)、如果反复使用的查询,使用preparedStament减少查询的次数
(2)、使用批量处理
索引优化分析:
1、索引的理解:
索引是数据结构,可以避免全表扫描,提高检索效率(DQL),但是会降低表的更新速度(DML)
2、索引的适用条件:
(1)、数据量庞大
(2)、该字段很少DML操作
(3)、该字段经常出现在where子句中,但对于Where条件里用不到的字段不创建索引
(4)、group by 和 order by 后面的字段有索引可提高效率
(5)、多表连接的关联字段(join…on)建立索引能提高查询效率
3、索引的数据存储方式:
(1)、聚簇索引:
表数据按照索引的顺序来存储的。对于聚集索引,叶子结点即存储了真实的数据行,不再有另外单独的数据页。
(2)、非聚簇索引:
表数据存储顺序与索引顺序无关。对于非聚集索引,叶结点包含索引字段值及指向数据页数据行的逻辑指针,该层紧邻数据页,其行数量与数据表行数据量一致。
注:MySQL数据库目前只有innodb存储引擎支持聚簇索引,而Myisam并不支持聚簇索引。
4、索引的底层原理(数据结构):
底层原理:通过相应的数据结构(主流默认B+树)缩小扫描范围,对数据进行排序、分区,同时携带数据在表中的“物理地址”,通过物理地址定位表中的数据,提高检索效率。
(1)、B-Tree索引:
MyISAM的普通索引
(2)、B+Tree索引:
InnoDB的普通索引
(3)、FULL-TEXT全文索引:
全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它能够利用【分词技术】等多种算法智能分析出文本文字中关键词的频率和重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。在mysql5.6.4以前只有Myisam支持,5.6.4版本以后innodb才支持。大数据时代逐渐被solr,elasticSearch等专门的搜索引擎所替代。
注:
1)、使用全文索引前,搞清楚版本支持情况;
2)、全文索引比 like + % 快 N 倍,但是可能存在精度问题;
3)、如果需要全文索引的是大量数据,建议先添加数据,再创建索引;
4)、对于中文,可以使用 MySQL 5.7.6 之后的版本,或者第三方插件。
(4)、Hash索引:
Hash索引只有Memory, NDB两种引擎支持,Memory引擎默认支持Hash索引,如果多个hash值相同,出现哈希碰撞,那么索引以链表方式存储。
(5)、R-tree索引:
R-Tree在mysql很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有myisam、bdb、innodb、ndb、archive几种。相对于b-tree,r-tree的优势在于范围查找。
5、索引的分类:
(1)、主键索引(PRIMARY KEY):
ALTER TABLE t_table ADD PRIMARY KEY (id); //不允许重复,不允许空值
(2)、唯一索引(UNIQUE):
ALTER TABLE t_table ADD UNIQUE index_name (id); //唯一的,允许空值
(3)、普通索引(INDEX):
ALTER TABLE t_table ADD INDEX index_name (id);
(4)、组合索引:
ALTER TABLE t_table ADD INDEX index_name('col1','col2','col3'); //遵循“最左前缀”原则
6、索引的使用:
(1)、创建索引:
//方式一: create [unique|fulltext] index 索引名 on 表名(字段名(长度)); //方式二: alter table 表名 add [unique|fulltext] index 索引名(字段名[(长度)] [ase|desc]);
(2)、使用索引:
explain select 语句;
(3)、删除索引:
drop index 索引名 on 表名;
SQL查询优化分析:
SQL的优化主要涉及SQL语句及索引的优化、数据表结构的优化、系统配置的优化和硬件的优化四个方面:
1、SQL语句及索引的优化:
(1)、对查询进行优化,应尽量避免全表扫描,首先应考虑在where及order by涉及的列上建立索引;
(2)、应尽量避免在where子句中对字段进行操作(使用参数、表达式、函数、运算)
(3)、不能对索引列进行任何操作(计算、类型转换等);
(4)、减少使用(!=、<>、<、>)、is not null、is null,否则将导致引擎放弃使用索引而进行全表扫描;
(5)、like以`%`开头会导致索引失效;
(6)、字符串不加单引号会导致索引失效(mysql会将字符串类型强制转换导致索引失效);
(7)、减少使用or,会导致索引失效
(8)、ORDER BY子句,尽量使用Using Index方式排序,避免使用Using FileSort方式排序(执行计划)
(9)、尽可能在索引列上完成排序操作,遵照索引建的最佳左前缀
(10)、尽量不要使用 distinct
(11)、优化嵌套查询:子查询可以被更有效率的连接(Join)替代
(12)、很多时候用exists或between代替in是一个好的选择
(13)、存储引擎不能使用索引中范围条件右边的列;
(14)、尽量使用覆盖索引,即查询不要使用select *的用法;
(15)、尽可能的使用varchar/nvarchar代替char/nchar,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。
假设index(a,b,c)
Where语句 |
索引是否被使用 |
where a = 3 |
Y,使用到a |
where a = 3 and b = 5 |
Y,使用到a,b |
where a = 3 and b = 5 and c = 4 |
Y,使用到a,b,c |
where b = 3 或者 where b = 3 and c = 4 或者 where c = 4 |
N |
where a = 3 and c = 5 |
使用到a, 但是c不可以,b中间断了 |
where a = 3 and b > 4 and c = 5 |
使用到a和b, c不能用在范围之后,b后断了 |
where a = 3 and b like 'kk%' and c = 4 |
Y,使用到a,b,c |
where a = 3 and b like '%kk' and c = 4 |
Y,只用到a |
where a = 3 and b like '%kk%' and c = 4 |
Y,只用到a |
where a = 3 and b like 'k%kk%' and c = 4 |
Y,使用到a,b,c |
2、数据表结构的优化:
包括选择合适数据类型、表的范式的优化、表的垂直拆分和表的水平拆分等手段
注:
(1)、表的垂直拆分
将含有多个列的表拆分成多个表,解决表宽度问题:
1)、把不常用的字段单独放在同一个表中;
2)、把大字段独立放入一个表中;
3)、把经常使用的字段放在一起;
(2)、表的水平拆分
表的水平拆分用于解决数据表中数据过大的问题,水平拆分每一个表的结构都是完全一致的。一般地,将数据平分到N张表中的常用方法包括以下两种:
(1)、对ID进行hash运算,如果要拆分成5个表,mod(id,5)取出0~4个值;
(2)、针对不同的hashID将数据存入不同的表中;
3、系统配置的优化:
(1)、操作系统配置的优化:增加TCP支持的队列数
(2)、mysql配置文件优化:Innodb缓存池设置(推荐总内存的75%)和缓存池的个数
4、硬件的优化:
(1)、CPU:核心数多并且主频高的
(2)、内存:增大内存
(3)、磁盘配置和选择:磁盘性能
mysql问题排查手段(总结):
1、使用explain命令查询sql语句执行计划。
2、开启慢查询日志,查看慢查询的sql。
3、使用show processlist命令查看当前所有连接信息。
一、执行计划Explain:
1、作用:
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而分析查询语句与表结构的性能瓶颈,提升查询效率。
2、使用:
Explain + SQL语句
3、解析:
(1)、id:
查询的序列号
id相同 |
执行顺序由上至下 |
id不同
|
如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行 |
id相同与不同,同时存在 |
id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行 |
(2)、select_type:
查询的类型
SIMPLE |
简单的select查询,查询中不包含子查询或者UNION |
PRIMARY |
查询中最外层子查询被标记为Primary |
DERIVED |
某个查询的子查询的结果临时表 |
SUBQUERY |
在SELECT或WHERE列表中包含了子查询 |
DEPENDENT SUBQUERY |
在SELECT或WHERE列表中包含了子查询,子查询基于外层 |
UNCACHEABLE SUBQUREY |
无法被缓存的子查询 |
UNION |
若第二个SELECT出现在UNION之后,则被标记为UNION; 若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED |
UNION RESULT |
从UNION表获取结果的SELECT |
(3)、table:
涉及表
(4)、type:(重)
访问类型排列
结果值从最好到最坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range(尽量保证) > index > ALL
ALL |
MySQL将进行全表扫描 |
index |
index与ALL区别为index类型只遍历索引树 |
range |
只检索给定范围的行,使用一个索引来选择行。常见于between、<、>等的查询 |
ref |
非唯一性索引扫描,返回匹配某个单独值的所有行。常见于使用非唯一索引或唯一索引的非唯一前缀进行的查找。 |
eq_ref |
唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描。 |
const、system |
当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量。 |
NULL |
MySQL在优化过程中分解语句,执行时甚至不用访问表或索引。 |
注:一般来说,尽量保证查询级别至少达到range,最好能达到ref。
(5)、possible_keys
显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。
(6)、key
实际使用的索引。如果为NULL,则没有使用索引;当查询中若使用了覆盖索引,则该索引仅出现在key列表中。
(7)、key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。
(8)、ref
表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值。
(9)、rows
rows列显示MySQL认为它执行查询时必须检查的行数。(越少越好)
(10)、Extra
包含不适合在其他列中显示但十分重要的额外信息。
Using filesort |
MySQL会对数据使用非索引列进行排序,而不是按照索引顺序进行读取;若出现改值,应优化索引 |
Using where |
表明使用了where过滤 |
Using temporary |
使用临时表保存中间结果,比如,MySQL在对查询结果排序时使用临时表,常见于order by和group by;若出现改值,应优化索引 |
Using index |
表示select操作使用了索引覆盖,避免回表访问数据行,效率不错 |
二、慢查询日志:
1、简介:
(1)、MySQL的慢查询日志是MySQL提供的一种日志记录,用来记录在MySQL中响应时间超过long_query_time阀值的语句。long_query_time的默认值为10,意思是运行10秒以上的语句。
(2)、默认情况下,MySQL数据库没有开启慢查询日志,需要手动来设置这个参数。
注:不是调优需要的话,不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。
2、使用:
临时使用开启设置:(注:永久使用对配置文件进行修改)
3、日志分析工具:
使用mysqldumpslow命令分析日志:
4、springboot开启慢查询日志配置:
spring: datasource: druid: filter: stat: enabled: true # 开启DruidDataSource状态监控 db-type: mysql # 数据库的类型 log-slow-sql: true # 开启慢SQL记录功能 slow-sql-millis: 2000 # 默认3000毫秒,这里超过2s,就是慢,记录到日志
三、SQL调优的测量
1、SHOW PROFILE
(1)、简介:
分析当前语句执行的资源消耗情况,对SQL进行调优测量
(2)、使用流程:
1)、查看当前mysql是否支持:
Show variables like 'profiling';
2)、默认关闭,手动开启功能:
set profiling=1;
3)、运行SQL语句
4)、查看结果:
show profiles;
5)、显示查询过程 sql生命周期:
show profile cpu,block io for query n; 注:n为show profile中的Query_ID数字号码
对诊断结果的Status分析(出现以下任何一个需优化查询语句):
converting HEAP to MyISAM |
查询结果过大,内存不够用 |
Copying to 表名 table on disk |
将内存中临时表数据复制到了磁盘 |
Creating 表名table |
拷贝数据到创建临时表,用完再删除 |
locked |
|
注:show profile方式将从5.6.7开始不推荐使用,并且在以后的版本中会删除
2、SHOW PROCESSLIST:
show processlist命令可以查看当前MySQL实例的连接情况,用于观察是否有大量的连接处于非正常状态。
(1)、使用:
SHOW PROCESSLIST; #查询MySQL进程列表;
KILL id序列号; #可以杀掉故障进程;
(2)、详情:
字段 |
解释 |
Id |
连接标识符 |
User |
当前用户 |
Host |
操作的主机,指客户端 |
db |
默认数据库(如果已选择);否则为NULL |
Command |
线程正在执行的命令类型 |
Time |
线程处于其当前状态的持续时间(以秒为单位) |
State |
指示线程正在执行的操作,事件或状态 |
Info |
线程正在执行的语句,如果未执行任何语句,则为NULL。 该语句可能是发送到服务器的那条语句,或者是最内部的语句(如果该语句执行其他语句,比如存储过程中的select语句) |
注:
Command字段的对应状态:
1)、sleep:正在等待客户端发送新的请求
2)、query:正在执行查询或者正在将结果发送给客户端
3)、locked:在MySQL服务层,线程正在等待表锁
4)、analyzing and statistics:线程正在收集存储引擎的统计信息,并生成查询的执行计划
5)、copying to tmp table:线程正在执行查询,并且将其结果集都复制到一个临时表中
6)、sorting result:正在对结果集进行排序
7)、sending data:线程可能在多个状态之间传送数据,或者在生成结果集或者向客户端返回数据
MySQL的锁机制:
锁机制可以保证数据并发访问的一致性与有效性,MySQL各存储引擎使用了三种类型(级别)的锁机制:表级锁、行级锁和页级锁。
注:
读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响
写锁(排它锁):当前写操作没有完成时,它会阻断其他写锁和读锁
1、表锁:
偏向MyISAM引擎,开销小,加锁快;锁定粒度大,发生锁冲突的概率最高,并发度最低。
(1)、表锁操作命令:
1)、手动增加表锁
lock table 表名字1 read(或write),表名字2 read(或write),……;
2)、查看表上加过的锁
show open tables;
3)、释放表锁:
unlock tables;
(2)、总结:
锁类型 |
当前进程可读 |
当前进程可写 |
其他进程可读 |
其他进程可写 |
当前进程其他表 |
其他进程其他表 |
读锁 |
可读 |
不可写 |
可读 |
阻塞到当前进程锁释放 |
不可读,不可写 |
可读,可写 |
写锁 |
可读 |
可写 |
阻塞到当前进程锁释放 |
阻塞到当前进程锁释放 |
不可读,不可写 |
可读,可写 |
1)、对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。
2)、对MyISAM表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。
(3)元数据锁(MDL):
MySQL里面表级别的锁有两种:一种是表锁、一种是元数据锁(MDL);元数据锁由MySQL5.5版本引入;当对一个表做增删改查操作的时候,加MDL读锁;当要对表做结构变更操作的时候,加MDL写锁;MDL不需要显式使用,在访问一个表的时候会被自动加上。
2、行锁:
偏向InnoDB引擎,开销大,加锁慢,会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并发量高。
(1)、InnoDB(支持事务)实现行锁的类型:
1)、共享锁(S):
又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
共享锁方式:
set autocommit=0;
select * from 表名 where ... + lock in share more
2)、排他锁(X):
又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。
排他锁方式:
set autocommit=0; select * from 表名 where ... + for update
3)、间隙锁
当我们用范围条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙”,InnoDB也会对这个间隙进行加锁,这种锁机制就叫做间隙锁;若执行的条件是范围过大,则InnoDB会将整个范围内所有的索引键值全部锁定,很容易对性能造成影响。
(2)、分析行锁定:
通过检查InnoDB_row_lock 状态变量分析系统上的行锁的争夺情况:
show status like 'innodb_row_lock%;
Innodb_row_lock_current_waits |
当前正在等待锁定的数量; |
Innodb_row_lock_time |
从系统启动到现在锁定总时间长度;(重要) |
Innodb_row_lock_time_avg |
每次等待所花平均时间;(重要) |
Innodb_row_lock_time_max |
从系统启动到现在等待最长的一次所花的时间; |
Innodb_row_lock_waits |
系统启动后到现在总共等待的次数;(重要:直接决定优化的方向和策略) |
(3)、行锁优化:
1)、尽可能让所有数据检索都通过索引来完成,避免无索引行或索引失效导致行锁升级为表锁。
2)、尽可能避免间隙锁带来的性能下降,减少或使用合理的检索范围。
3)、尽可能减少事务的粒度,比如控制事务大小,而从减少锁定资源量和时间长度,从而减少锁的竞争等,提供性能。
4)、尽可能低级别事务隔离,隔离级别越高,并发的处理能力越低。
3、页锁:
开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
4、总结
(1)、InnoDB支持表锁和行锁,使用索引作为检索条件修改数据时采用行锁,否则采用表锁;
(2)、InnoDB自动给修改操作加锁,给查询操作不自动加锁;
(3)、行锁可能因为未使用索引而升级为表锁,所以除了检查索引是否创建的同时,也需要通过explain执行计划查询索引是否被实际使用;
(4)、行锁相对于表锁来说,优势在于高并发场景下表现更突出,毕竟锁的粒度小;
(5)、当表的大部分数据需要被修改,或者是多表复杂关联查询时,建议使用表锁优于行锁;
(6)、为了保证数据的一致完整性,任何一个数据库都存在锁定机制。锁定机制的优劣直接影响到一个数据库的并发处理能力和性能。
5、MySQL的乐观锁和悲观锁:
如果一个事务先读后写同一份数据,就可能发生丢失修改,采用乐观锁与悲观锁处理。
(1)、乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
注:乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
(2)、悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。(事务排队执行)
注:传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
(3)、数据库的乐观锁需要自己实现,在表里面添加一个 version版本字段,每次修改成功值加1,这样每次修改的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否一致,如果不一致就不修改,这样就实现了乐观锁。
参考:
尚硅谷周阳MySQL进阶思维导图提取码:4u4z