【MySQL】MySQL(四)存储引擎、索引、锁、集群 (6)

不同存储引擎支持的锁

存储引擎 表级锁 行级锁 页级锁
MyISAM   支持   不支持   不支持  
InnoDB   支持   支持   不支持  
MEMORY   支持   不支持   不支持  
BDB   支持   不支持   支持  
演示InnoDB锁

数据准备

-- 创建db13数据库 CREATE DATABASE db13; -- 使用db13数据库 USE db13; -- 创建student表 CREATE TABLE student( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10), age INT, score INT ); -- 添加数据 INSERT INTO student VALUES (NULL,'张三',23,99),(NULL,'李四',24,95), (NULL,'王五',25,98),(NULL,'赵六',26,97);

共享锁

-- 标准语法 SELECT语句 LOCK IN SHARE MODE; -- 窗口1 /* 共享锁:数据可以被多个事务查询,但是不能修改 */ -- 开启事务 START TRANSACTION; -- 查询id为1的数据记录。加入共享锁 SELECT * FROM student WHERE id=1 LOCK IN SHARE MODE; -- 查询分数为99分的数据记录。加入共享锁 SELECT * FROM student WHERE score=99 LOCK IN SHARE MODE; -- 提交事务 COMMIT; -- 窗口2 -- 开启事务 START TRANSACTION; -- 查询id为1的数据记录(普通查询,可以查询) SELECT * FROM student WHERE id=1; -- 查询id为1的数据记录,并加入共享锁(可以查询。共享锁和共享锁兼容) SELECT * FROM student WHERE id=1 LOCK IN SHARE MODE; -- 修改id为1的姓名为张三三(不能修改,会出现锁的情况。只有窗口1提交事务后,才能修改成功) UPDATE student SET WHERE id = 1; -- 修改id为2的姓名为李四四(修改成功,InnoDB引擎默认是行锁) UPDATE student SET WHERE id = 2; -- 修改id为3的姓名为王五五(注意:InnoDB引擎如果不采用带索引的列。则会提升为表锁) UPDATE student SET WHERE id = 3; -- 提交事务 COMMIT;

排他锁

-- 标准语法 SELECT语句 FOR UPDATE; -- 窗口1 /* 排他锁:加锁的数据,不能被其他事务加锁查询或修改 */ -- 开启事务 START TRANSACTION; -- 查询id为1的数据记录,并加入排他锁 SELECT * FROM student WHERE id=1 FOR UPDATE; -- 提交事务 COMMIT; -- 窗口2 -- 开启事务 START TRANSACTION; -- 查询id为1的数据记录(普通查询没问题) SELECT * FROM student WHERE id=1; -- 查询id为1的数据记录,并加入共享锁(不能查询。因为排他锁不能和其他锁共存) SELECT * FROM student WHERE id=1 LOCK IN SHARE MODE; -- 查询id为1的数据记录,并加入排他锁(不能查询。因为排他锁不能和其他锁共存) SELECT * FROM student WHERE id=1 FOR UPDATE; -- 修改id为1的姓名为张三(不能修改,会出现锁的情况。只有窗口1提交事务后,才能修改成功) UPDATE student SET WHERE id=1; -- 提交事务 COMMIT;

注意:锁的兼容性

共享锁和共享锁 兼容

共享锁和排他锁 冲突

排他锁和排他锁 冲突

排他锁和共享锁 冲突

演示MyISAM锁

数据准备

-- 创建product表 CREATE TABLE product( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(20), price INT )ENGINE = MYISAM; -- 指定存储引擎为MyISAM -- 添加数据 INSERT INTO product VALUES (NULL,'华为手机',4999),(NULL,'小米手机',2999), (NULL,'苹果',8999),(NULL,'中兴',1999);

读锁

-- 标准语法 -- 加锁 LOCK TABLE 表名 READ; -- 解锁(将当前会话所有的表进行解锁) UNLOCK TABLES; -- 窗口1 /* 读锁:所有连接只能读取数据,不能修改 */ -- 为product表加入读锁 LOCK TABLE product READ; -- 查询product表(查询成功) SELECT * FROM product; -- 修改华为手机的价格为5999(修改失败) UPDATE product SET price=5999 WHERE id=1; -- 解锁 UNLOCK TABLES; -- 窗口2 -- 查询product表(查询成功) SELECT * FROM product; -- 修改华为手机的价格为5999(不能修改,窗口1解锁后才能修改成功) UPDATE product SET price=5999 WHERE id=1;

写锁

-- 标准语法 -- 加锁 LOCK TABLE 表名 WRITE; -- 解锁(将当前会话所有的表进行解锁) UNLOCK TABLES; -- 窗口1 /* 写锁:其他连接不能查询和修改数据 */ -- 为product表添加写锁 LOCK TABLE product WRITE; -- 查询product表(查询成功) SELECT * FROM product; -- 修改小米手机的金额为3999(修改成功) UPDATE product SET price=3999 WHERE id=2; -- 解锁 UNLOCK TABLES; -- 窗口2 -- 查询product表(不能查询。只有窗口1解锁后才能查询成功) SELECT * FROM product; -- 修改小米手机的金额为2999(不能修改。只有窗口1解锁后才能修改成功) UPDATE product SET price=2999 WHERE id=2; 演示悲观锁和乐观锁

悲观锁的概念

就是很悲观,它对于数据被外界修改的操作持保守态度,认为数据随时会修改。

整个数据处理中需要将数据加锁。悲观锁一般都是依靠关系型数据库提供的锁机制。

我们之前所学的行锁,表锁不论是读写锁都是悲观锁。

乐观锁的概念

就是很乐观,每次自己操作数据的时候认为没有人会来修改它,所以不去加锁。

但是在更新的时候会去判断在此期间数据有没有被修改。

需要用户自己去实现,不会发生并发抢占资源,只有在提交操作的时候检查是否违反数据完整性。

悲观锁和乐观锁使用前提

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwjzpj.html