美文网首页
补充 - 事务 & 锁机制

补充 - 事务 & 锁机制

作者: 慕知 | 来源:发表于2021-03-21 10:18 被阅读0次

一,事务

1,什么是事务
  transactions,一个事务里可以包含多条sql语句,这些操作要么全部执行,要么全部不执行。


2,事务的4大特征ACID
通常称为ACID特征(首字母)

    1)原子性
#事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
    2)一致性
#事务应确保数据库的状态从一个一致状态转变为另一个一致状态,例如转账行为中,一个人减了10元,另外一个人就应该加上这10元,而不能是5元。
#其他一致状态的含义是数据库中的数据应满足完整性约束,例如字段约束不能为负数,事务执行完毕后的该字段也同样不是负数
    3)隔离性
#多个事务并发执行时,一个事务的执行不应影响其他事务的执行
    4)持久性
#一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。

3,事务的3种运行模式
隐式 == 自动

显式 == 手动

1. 自动提交事务(隐式开启、隐式提交)

2. 显式事务(显式开启、显式提交)

3. 隐式事务(隐式开启、显式提交)






总结:MYSQL 默认为每条sql开启事务,并且会在本条sql执行完毕后自动执行commit提交

若想设置手动提交,有两种方式

1, 直接用 SET 来改变 MySQL 的自动提交模式(下述设置均为会话级别的设置):

SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交


2, 手动开启的事务里默认不会自动提交
需要手动commit或者回滚操作 backroll

4,如何开启事务(默认开启)
1,mysql默认开启事务

mysql> select * from excel;
+----+---------+--------+--------+--------+
| id | name    | gender | office | salary |
+----+---------+--------+--------+--------+
|  1 | tom     | f      | a1     |  12000 |
|  2 | lily    | m      | b2     |   8000 |
|  3 | alex    | f      | c3     |   6700 |
|  4 | xiaohua | m      | a1     |   9700 |
+----+---------+--------+--------+--------+

mysql> update excel set name='ttom' where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0




mysql> select * from excel;
+----+---------+--------+--------+--------+
| id | name    | gender | office | salary |
+----+---------+--------+--------+--------+
|  1 | ttom    | f      | a1     |  12000 |
|  2 | lily    | m      | b2     |   8000 |
|  3 | alex    | f      | c3     |   6700 |
|  4 | xiaohua | m      | a1     |   9700 |
+----+---------+--------+--------+--------+







2,开启事务
开启事务 start transaction;或者begin;
提交事务 commit;
回滚事务 rollback

commit或者rollback事务都结束

mysql> select * from excel;
+----+---------+--------+--------+--------+
| id | name    | gender | office | salary |
+----+---------+--------+--------+--------+
|  1 | ttom    | f      | a1     |  12000 |
|  2 | lily    | m      | b2     |   8000 |
|  3 | alex    | f      | c3     |   6700 |
|  4 | xiaohua | m      | a1     |   9700 |
+----+---------+--------+--------+--------+



mysql> update excel set name='ttttom' where id=1;


mysql> select * from excel;
+----+---------+--------+--------+--------+
| id | name    | gender | office | salary |
+----+---------+--------+--------+--------+
|  1 | ttttom  | f      | a1     |  12000 |
|  2 | lily    | m      | b2     |   8000 |
|  3 | alex    | f      | c3     |   6700 |
|  4 | xiaohua | m      | a1     |   9700 |
+----+---------+--------+--------+--------+


mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from excel;
+----+---------+--------+--------+--------+
| id | name    | gender | office | salary |
+----+---------+--------+--------+--------+
|  1 | ttom    | f      | a1     |  12000 |
|  2 | lily    | m      | b2     |   8000 |
|  3 | alex    | f      | c3     |   6700 |
|  4 | xiaohua | m      | a1     |   9700 |
+----+---------+--------+--------+--------+





以上在rollback后,事务已经结束,查询表并没有更新
如下,commit提交后,查询表已经提交更新

mysql> update excel set name='ttttom' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)


mysql> select * from excel;
+----+---------+--------+--------+--------+
| id | name    | gender | office | salary |
+----+---------+--------+--------+--------+
|  1 | ttttom  | f      | a1     |  12000 |
|  2 | lily    | m      | b2     |   8000 |
|  3 | alex    | f      | c3     |   6700 |
|  4 | xiaohua | m      | a1     |   9700 |
+----+---------+--------+--------+--------+

二,数据库读现象

1,脏读
# 事务终端2 修改了一条数据,这时事务终端1读取更新后的行;终端2做了回滚操作,取消刚刚的修改;这时终端一读取的行便无效了,称之为脏读

2,不可重复读
# 事务终端1读取了行记录,事务终端2对刚刚事务终端1读取的行做了修改并提交;终端1再次读取了行记录发现结果不一样,称之为不可重复读

3,幻像读(不可重复读的特殊场景)
# 事务终端1查询了where的一条记录,事务终端2插入了一行记录,正好满足终端1的查询语句;这时终端1再次检索刚刚的语句,发现多出了一条记录,称之为幻像读


三,锁机制

锁的分类

按照锁的颗粒划分:行级锁,表级锁,页级锁
按照锁的级别划分:共享锁,排他锁
按照使用的方式划分:乐观锁,悲观锁

1,行级锁—排它锁(X锁)

行级锁:
概念:行级锁只针对当前操作的行进行加锁。
用处:行级锁能大大减少数据库操作的冲突。
种类:行级锁分为共享锁 和 排他锁。


insert delete update  ----->默认排它锁
select默认不加锁,如果加锁
select... from... for update;排它锁
select... from... lock in share mode;共享锁



注意⚠️
排它锁:
事务1一旦对数据A加了排它锁,其他事务无法对数据A加任何锁;只有事务1可以操作数据A,可读可写

示例一:


开启两个终端
终端1:
mysql> select * from excel;
+----+---------+--------+--------+--------+
| id | name    | gender | office | salary |
+----+---------+--------+--------+--------+
|  1 | ttttom  | f      | a1     |  12000 |
|  2 | lily    | m      | b2     |   8000 |
|  3 | alex    | f      | c3     |   6700 |
|  4 | xiaohua | m      | a1     |   9700 |
+----+---------+--------+--------+--------+


mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update excel set name='abc' where id=3;
Query OK, 1 row affected (0.01 sec)

#并没有执行commit或者rollback




终端2:
mysql> update excel set name='cccc' where id=3;

#会一直停在原地,执行不了,直接锁定


PS:以上,一旦终端1执行commit或者rollback,会释放锁,终端2便可以执行


示例二:   select


终端1:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from excel where name=4 for update;
Empty set, 4 warnings (0.00 sec)
# for update排它锁


终端2:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from excel where id > 2 for update;

或
mysql> update excel set name='huaer' where id=3;

#也会停在原地,执行不了


PS:
一旦终端一 commit或者rollback,终端2就可以执行;
注意:如果表没有设置索引,执行以上操作会锁表!!!(没有命中索引)

2,行级锁—共享锁(S锁)

注意⚠️
共享锁:又称连锁,多个事务对于同一数据可以共享一把锁,只读数据,释放所有的共享锁才能修改


示例:


事务1:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from excel where name=4 lock in share mode;
Empty set, 4 warnings (0.00 sec)




事务2:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from excel where name=4 for update;

#在事务1加了共享锁的基础上,事务2对同行记录做排它锁执行不成功

mysql> select * from excel where name=4 lock in share mode;
Empty set, 4 warnings (0.00 sec)
# 也加上共享锁成功





PS:
在以上事务1和事务2都加了共享锁的情况下,都执行以下
会出现“死锁”

事务1:
mysql> update excel set name='777' where id=1;

#会停在原地,执行不成功



事务2:
mysql> update excel set name='777' where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0



这时再查看事务1:
mysql> update excel set name='777' where id=1;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction


#会提示死锁,默认强制退出事务

大多数死锁问题,innodb存储引擎都会发现并抛出异常,但是有一种死锁非常隐蔽;
innodb存储引擎锁的是索引,如果命中的是辅助索引,则会锁住辅助索引的记录,再锁住对应的聚集索引的记录

3,乐观锁悲观锁
悲观锁:担心别人会加锁,干错自己就直接加一把排他锁;
乐观锁:原理是不加锁的,比如,在生产环境中,先查询当前的版本号(类似对当前快照记录)对数据增删改之后,再次查看当前的排版号,如果不一样,则操作失败


4,innodb支持锁特点
1,如果命中了主键索引,则直接锁住主键所对应的一条记录
2,如果命中的辅助索引,会先锁住该非辅助索引,再锁定相关的主键索引
3,如果没有设置索引,则会锁住表




 PS:
1,拿到共享锁,只能看不能改(在别人已经为数据加了共享锁的前提下);如果只有自己设置了共享锁,自己也可以改也可以查

2,自己设置了排他锁,可以改也可以查
innodb存储引擎行锁的三种算法:

Record Lock行锁
Gap Lock  间隙锁
Next-Key Lock(默认)  =  Record Lock  + Gap Lock 


注:
id  num
1    2
2    4
4    5
4    6

id为聚簇索引,num为辅助索引
间隙锁,比如select 一条数据条件是num = 4 for updates;
那么插入一条数据为 3 5;其中num5 是在4的上下范围中;则会阻塞在原地



PS:

在RR机制下,才会有锁间隙,而RR机制是mysql的 默认事务隔离机制,所以在默认情况下,innodb其实是锁行以及锁间隙

RR(Repeatable reads),可重复度,一种隔离事务机制;解决了脏读和可重复读的事务现象;但是幻读现象依然存在;而以上的默认行算法正好解决了幻读







相关文章

  • 补充 - 事务 & 锁机制

    一,事务 1,什么是事务 2,事务的4大特征ACID 3,事务的3种运行模式 4,如何开启事务(默认开启) 二,数...

  • 面试问题记录(一) Day50 2019-01-09

    并发中的常用锁,乐观锁和悲观锁,实现及使用 事务的特性,原理,spring如何实现事务 spring的实现机制,I...

  • 第六章 锁(下)

    6.5 锁问题通过锁机制可以实现事务隔离性要求,使得事务可以并发地工作。锁提高了并发,但是却会带来潜在的问题。不过...

  • Mysql InnoDB行锁及表锁分享

    一. 背景知识 [事务(Transaction)、隔离级别、传播机制] 二. 步入正题:表锁和行锁 1.1. 表锁...

  • MySQL相关(一)——— 事务和锁

    事务的隔离级别和锁机制 【1】InnoDB 事务隔离级别和锁 【2】脏读、不可重复读、幻读 mysql 相关 常用...

  • 锁机制

    锁机制 Innodb是事务级数据库,支持事务,支持外键,rollback,mvcc(高并发:在readcommit...

  • MYSQL锁和事务机制

    mysql基础: mysql的四个特性,原子性、一致性、隔离性、持久性。1.原子性(atomicity):一个事务...

  • MySQL事务&锁机制

    一、事务(transaction) 1、概念事物用于保护多个SQL语句的执行,只要有一个失败则全部失败,反之都成功...

  • Mysql 事务 锁机制总结

    1、什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点。 原子性:要不全部成功,要不全部撤销...

  • mysql锁机制与事务

    概念 事务是一系列操作所构成的执行单元,具有原子性,隔离性等的特点。锁是为了防止多线程读写操作的并发问题而引入的解...

网友评论

      本文标题:补充 - 事务 & 锁机制

      本文链接:https://www.haomeiwen.com/subject/tzmscltx.html