查看mysql支持的引擎,以及对应引擎支持的功能,SHOW ENGINES
乐观锁
用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。
悲观锁
悲观锁中又分为排它锁和共享锁两种,共享锁又称为读锁(read-lock),而排他锁又称为写锁(write-lock)。
读锁是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。 测试脚本如下
1
2
3
4
5
6
7
8
9
create table t_user_score
(
score_id int not null
primary key,
user_id int not null,
name varchar(10) null,
score int null,
subject varchar(10) null
);
测试读锁脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
set session autocommit=0; --设置事务非自动提交
show session variables like 'autocommit'; --查看当前会话提交配置
show global variables like 'autocommit';
SELECT * from t_user_score where score_id =1 lock in share mode; -- 添加lock in share mode
select * from information_schema.innodb_trx; --查看当前事务
-- 在不设置autocommit=0的情况下可以手动提交,在执行了update命令后再执行commit,可以观察出锁的效果
begin;
SELECT * from t_user_score where score_id =1 lock in share mode;
commit ;
再打开一个命令窗口,执行以下脚本,查看执行情况
1
2
update t_user_score set score = 20 where score_id = 1; -- 挂起
SELECT * from t_user_score where score_id =1 lock in share mode; --查询出结果
在查询语句后面增加LOCK IN SHARE MODE,Mysql会对查询结果中的每行都加共享锁,当没有其他线程对查询结果集中的任何一行使用排他锁时, 可以成功申请共享锁,否则会被阻塞。其他线程也可以读取使用了共享锁的表,而且这些线程读取的是同一个版本的数据。
加上共享锁后,对于update,insert,delete语句会自动加排它锁。
排它锁是悲观锁的一种实现,在上面悲观锁也介绍过。
若事务 1 对数据对象A加上X锁,事务 1 可以读A也可以修改A,其他事务不能再对A加任何锁, 直到事物 1 释放A上的锁。这保证了其他事务在事物 1 释放A上的锁之前不能再读取和修改A。排它锁会阻塞所有的排它锁和共享锁
读取为什么要加读锁呢:防止数据在被读取的时候被别的线程加上写锁,
使用方式:在需要执行的语句后面加上for update就可以了。
行锁
行锁又分共享锁和排他锁,由字面意思理解,就是给某一行加上锁,也就是一条记录加上锁。 行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用页级锁或者表级锁。
表锁
行级锁都是基于索引的,如果一条SQL语句用不到索引是不会使用行级锁的,会使用表级锁。 行级锁的缺点是:由于需要请求大量的锁资源,所以速度慢,内存消耗大。
死锁
1
2
3
show OPEN TABLES where In_use > 0; --查询是否锁表
show processlist; --查看进程
kill id; --杀死进程
产生死锁的四个条件:
-
互斥条件 进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。 此时若有其他进程请求该资源,则请求进程只能等待。
-
不可剥夺条件 进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走, 即只能由获得该资源的进程自己来释放(只能是主动释放)。
-
请求与保持条件 进程已经保持了至少一个资源,但又提出了新的资源请求, 而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
-
循环等待条件 存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。
相关文章: https://blog.csdn.net/wljliujuan/article/details/79614019