这是我参与新手入门的第1篇文章数据库
事务的四个特性:原子性,一致性,隔离性,持久性。 其中原子性、一致性、持久性容易理解。今天重点来聊聊隔离性。markdown
隔离性简单来讲,就是每一个事务是相互隔离的,你作你的事,他作他的事,你们相互隔离开来。 可是,你们都是在同一个数据库下操做,那这个「隔离」到底隔离到什么程度呢?是“老死不相往来”,仍是”临时隔离“,又或者是"你中有我,我中有你"?这就是涉及到了新的概念:隔离级别。并发
事务隔离级别有:工具
MySQL默认隔离级别为:可重复读spa
经过实际演示,咱们能够很好理解各隔离级别。 相关准备:设计
MySQL 版本:5.7 (可经过
select version()
命令查询)code表:orm
CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `number` varchar(20) NOT NULL COMMENT '学号', `name` varchar(20) DEFAULT NULL COMMENT '姓名', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生表'; 复制代码
初始数据:索引
id number name 1 2021070501 张三 复制代码
演示工具:Navicat (经过开启多个查询窗口,实现开启多个事务)事务
演示一:
步骤 | 查询窗口1(事务1) | 查询窗口2(事务2) |
---|---|---|
step1 | 执行SQL: -- 开启事务 BEGIN; > OK > 时间: 0s UPDATE student SET name = '李四' WHERE id = 1; > Affected rows: 1 > 时间: 0.002s |
|
step2 | BEGIN; SELECT * FROM student WHERE id = 1; =======结果======= id number name 1 2021070501 张三 |
|
step3 | COMMIT; > OK > 时间: 0.004s; |
|
step4 | SELECT * FROM student WHERE id = 1; =======结果======= id number name 1 2021070501 张三 |
|
step5 | COMMIT; > OK > 时间: 0s |
|
step6 | BEGIN; SELECT * FROM student WHERE id = 1; =======结果======= id number name 1 2021070501 李四 |
从上面演示能够分析出:
事务之间虽然有隔离性,但若是两个事务操做同一数据,那结果会怎么样呢,最终以哪一个事务执行结果为准?没有事务的状况下,咱们很容易理解,哪条SQL语句最后执行,就以哪一个数据为准。但加了事务,状况就变得复杂起来了,SQL执行顺序与事务提交顺序可能不一致。好比:
事务1先执行
UPDATE student SET name = '张三1' WHERE id = 1;
复制代码
事务2再执行
UPDATE student SET name = '张三2' WHERE id = 1;
复制代码
而后先提交事务2,再提交事务1。那最终的结果是「张三1」仍是「张三2」呢?站在SQL执行顺序角度来讲,结果应该为「张三2」;站在事务提交顺序来讲,结果应为「张三1」。
那最终实际结果呢?答案是:这种状况永远不会发生!
咱们能够实际操做试试: 演示二:
步骤 | 查询窗口1(事务1) | 查询窗口2(事务2) |
---|---|---|
step1 | BEGIN > OK > 时间: 0s UPDATE student SET name = '张三1' WHERE id = 1 > Affected rows: 1 > 时间: 0.001s |
|
step2 | BEGIN > OK > 时间: 0s UPDATE student SET name = '张三2' WHERE id = 1 ======观察结果======= 没反应,查询时间一直走 |
|
step3 | COMMIT; > OK > 时间: 0.004s; |
|
step4 | 再次打开窗口,会发现有如下结果 > Affected rows: 1 > 时间: 4.843s |
从演示二咱们能够看出,step2并不能正常执行,须要等待step3提交。这就是MYSQL的锁机制。
当事务1先执行UPDATE student SET name = '张三1' WHERE id = 1
时便得到数据行(id=1)的锁。事务2想执行UPDATE student SET name = '张三2' WHERE id = 1
时,由于该数据行是被锁住的,因此不能执行,须要等待事务1释放锁。事务1提交事务便会把锁释放掉。因此,不一样事务之间修改同一数据不会出现修改顺序和提交顺序不一致的状况。
按照锁粒度,能够把MYSQL锁简单归为:行锁和表锁。行锁就是锁定行数据,表锁是锁定整张表数据。上面所说示例,就是行锁。通常来讲,匹配条件是主键或索引列时,数据的update和delete会加行锁。若是增删改查时匹配的条件字段不带有索引,innodb使用的将是表级锁。因而可知,咱们数据库表设计中合理的索引是很是关键的。
有锁的地方,必然就会出现死锁的问题。之后有机会再聊更多的锁及死锁问题