MySQL数据库事务
2023-09-08 16:08:45 0 举报
登录查看完整内容
Mysql事务与锁的基础知识
作者其他创作
大纲/内容
所有事务都可以“看到”未提交事务的执行结果
“脏读”就是读取未提交的数据
存在并发问题
READ UNCOMMITTED(读取未提交内容)
支持不可重复读(Nonrepeatable Read)
解决脏读
READ COMMITTED(读取提交内容)
出现“幻读”(Phantom Read)
解决不可重复读(两次读取,中间可能被别人修改了),提交覆盖
MVCC 是通过保存数据在某个时间点的快照实现的
实现了非阻塞读,写操作只锁定必要行
Read Committed
Repeatable Read
只在MySQL的两个隔离级别下工作
隐藏字段(DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR)
回滚日志(undo log)
一致性读(consistent read)
MVCC的三种实现方式:
快照读
当前读
MVCC的类型
DB_ROW_ID 隐含ID
DB_TRX_ID 事务ID
DB_ROLL_PTR 回滚指针
工作原理
MVCC
不过,在InnoDB 和Falcon 存储引擎下通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读
MySQL的默认隔离级别
REPEATABLE READ(可重读)
最高级别的隔离级
通过强制事务排序,使之不发生冲突
InnoDB的查询也会被加上行锁。如果查询的是一个范围,那么该范围内的所有记录行包括每行记录所在的间隙区间范围都会被加锁,即使该行数据还没有被插入。
解决幻读(两次读取,中间被别人插入了,第二次读的更多或更少)
SERIALIZABLE(可串行化)
事务隔离级别:
每次操作锁住整张表,开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;一般用在整表数据迁移的场景。
表锁
每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高。
行锁
对数据库操作的粒度分:
通过代码实现
@Version private int version;
Mybatis OptimisticLockerInterceptor
框架实现
乐观锁(用版本对比来实现)
lock table t1 read;
lock table t1 write;
show open tables;
unlock tables;
表级的读锁,会阻塞写操作,不会阻塞读操作
写锁,会阻塞读,写操作
select ... from lock in share mode 只能读取,修改被阻塞
共享锁
select ... for update
基于索引,如果没有索引,锁全表
当前事务可以读取,修改,其他事务不能修改
排他锁
悲观锁
性能上区分的锁:
针对同一份数据,多个读操作可以同时进行而不会互相影响
读锁(也是共享锁):
当前写操作没有完成前,阻断其他写锁和读锁
写锁(悲观锁)
从数据库操作类型区分的锁:
select ....... lock in share mode (加共享锁)
select ........ for update (加排他锁)
显式锁
隐式锁
锁的类型
意向共享锁
意向排他锁
意向锁(Intention Lock)(表级别的)
select .... for update. 加X锁
select .... lock in share mode. 加S锁
一次性锁定读取
在read committed隔离级别下,读取被锁定行的最新一份快照数据. 产生了不可重复读的问题
在repeatable read 事务隔离级别下,读取事务开始时的行数据版本. 解决不可重复读的问题
一次性非锁定读
锁的分类()
死锁
InnoDB 行锁通过对索引数据页上的记录加锁实现
单个行记录的锁
Read LOCK 行锁(RC和RR)
间隙锁在可重复读隔离级别下才会生效
仅在id=10的主键索引记录上加X锁
主键加锁
现在唯一索引id上加X锁,然后再id=10的主键索引上加X锁
唯一主键:
非唯一主键:
表里所有行和间隙都会加X锁
当没有索引时,会导致全表锁定,因为Innodb引擎锁机制是基于索引实现的记录锁定
无索引:
GAP LOCK 间隙锁(RR)
Gap Lock+Record Lock 锁定一个范围并锁定记录本身.
Next-Key Lock(RR)
InnoDB 行锁的三种方式:
在 RR 隔离级别,InnoDB 对记录加锁行为都是先采用 Next-key Lock,当 SQL 操作包含索引时,InnoDB 会对 Netx-key进行优化,降级为 RecordLock,仅锁住索引本身而非范围
read committed隔离级别下采用的是: Record Lock 的方式来加锁
InnoDB在不同隔离级别下产生\"不可重复读\" 和 \"幻读\" 和解决它 的根本原因
InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁
InnoDB 规则:
InnoDB 锁算法
锁
InnDB
Falcon
NDB Cluster
事务存储引擎(三种)
存储引擎
MySQL默认的事务隔离级别是可重复读,用Spring开发程序时,如果不设置隔离级别默认用MySQL设置的隔离级别,如果Spring设置了就用已设置的隔离级别
InnoDB支持事务
InnoDB支持行锁
InnoDB和MyISAM最大的不同点
MyISAM在执行查询语句前,会自动给涉及的表加读锁;执行update、insert、delete操作加写锁;
InnoDB在执行查询语句前(非串行隔离级别),不会加锁;执行update、insert、delete操作会加行锁。
读锁会阻塞写,但不会阻塞读。而写锁会把读写都阻塞。
可重复读的隔离级别下使用了MVCC(multi-version concurrency control)机制(该机制在RC和RR都有使用),select操作不会更新版本号,是快照读(历史版本);insert、update和delete会更新版本号,是当前读(当前版本)
锁主要是加在索引上,如果对非索引字段更新,行锁可能会变表锁。
尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁;
合理设计索引,尽量缩小锁的范围;
尽可能减少索引条件范围,避免间隙锁;
尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行;
尽可能低级别事务隔离
锁优化建议:
事务隔离级别是锁的操作,锁是底层实现
先控制事务级别,如果无法解决问题再用锁解决
事务隔离级别与锁的关系
Atomicity原子
读未提交
读提交
可重复读
可串行化
Isolation 隔离
Binlog落地
发送Binlog
存储引擎提交
flush_logs
check_point
事务提交标记
Durability持久
约束一致性
数据一致性
Consistency 一致
ACID特性
MySQL数据库事务
收藏
收藏
0 条评论
回复 删除
下一页