一. ACID概念
- 原子性:事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全都不执行。
- 一致性:在事物开始和完成时,数据都必须保持一致,这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性。
- 隔离性:数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。事务处理过程中数据的中间态对外部不可见
- 持久性:事务完成后,其对数据的修改是永久性的,使出现系统故障也能够保持。
二. 并发事务处理带来的问题
- 脏写问题:当两个或多个事务选择同一行,会发生丢失更新问题–最后的更新覆盖了由其他事务所做的更新。
- 脏读问题:事务A读取到了事务B已经修改但尚未提交的数据,还在这个数据基础上做了操作。此时,如果B事务回滚,A读取的数据无效,不符合一致性要求。
- 不可重复读:事务A内部的相同查询语句在不同时刻读出的结果不一致,不符合隔离性。
- 幻读:事务A读取到了事务B提交的新增数据,不符合隔离性
相关现象:一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。
三. Mysql事务隔离级别
-
不同的事务隔离级别
(1)读未提交:可以读取到其他事务未提交的数据,会出现脏读,不可重复读,幻读等问题。
(2)读已提交:可以读取到其他事务已提交的数据,解决了事务的脏读问题,多次读取会出现不可重复读,幻读等问题
(3)可重复读:使用了MVCC机制,在同一事务内多次读取同一行记录不会读取到不一致的值,但无法避免幻读问题
(4)串行化方式:解决以上所有读取问题,但使得数据库中的事务无法并行
注:Mysql默认为可重复读级别 -
查询事务隔离级别命令:show variables like "tx_isolation";
设置隔离级别:set tx_isolation = 'Repeatable_read';
四. 数据库中的锁分类
数据库中的锁分类.png- 乐观锁:使用version版本号实现锁机制,无需进行锁等待,尝试更新数据,不成功则采用其他逻辑重试
- 悲观锁:争抢锁资源时触发锁等待机制
(1)读锁:对同一份数据,多个读操作可同时进行不受对方影响
(2)写锁:当前写操作未完成前,阻断其他写锁及读锁 - 表锁:
每次操作锁住整张表,开销小,加锁快。锁定粒度大,发生锁冲突的概率最高,并发度最低;一般用在整表数据迁移的场景。
(1)手动增加表锁:lock table table_name read(write_锁种类)
(2)查看表上加过的锁:show open tables;
(3)删除表锁:unlock tables; - 行锁:
每次操作锁住一行数据。开销大,加锁慢;会出现死锁;
锁定粒度最小,发生锁冲突的概率最低,并发度最高。
补充:Innodb与MyIsam引擎区别
(1)底层区别:聚集索引与非聚集索引
(2)Innodb支持事务,MyIsam不支持事务
(3)Innodb支持行锁,MyIsam仅支持到表锁
(4)MyISAM在执行查询语句SELECT前,会自动给涉及的所有表加读锁,在执行update、insert、delete操作会自动给涉及的表加写锁。
InnoDB在执行查询语句SELECT时(非串行隔离级别),
不会加锁。但是update、insert、delete操作会加行锁。 - 间隙锁(gap lock)
间隙锁,锁的就是两个值之间的空隙。间隙锁在某些情况下可以解决幻读问题。
(1)临键锁(Next-key Locks)
Next-Key Locks是行锁与间隙锁的组合。 - 其他
(1)无索引行锁会升级为表锁
锁主要是加在索引上,如果对非索引字段更新,行锁可能会变表锁
(2)添加共享锁/排他锁
select * from test_innodb_lock where a=2 for update(lock in share mode);
五. 锁性能分析
- 检查InnoDB_row_lock状态变量分析系统上的行锁的争夺情况
show status like 'innodb_row_lock%';
其中重要的指标:
(1)等待平均时长: Innodb_row_lock_time_avg
(2)等待总次数:Innodb_row_lock_waits
(3)等待总时长:Innodb_row_lock_time
- 查看INFORMATION_SCHEMA系统库锁相关数据表
(1) 查看事务:select * from INFORMATION_SCHEMA.INNODB_TRX;
(2) 查看锁:select * from
INFORMATION_SCHEMA.INNODB_LOCKS;
(3) 查看锁等待:select * from
INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
(4) 查看锁等待详细信息:
show engine innodb status\G; - 锁优化
(1)尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
(2)合理设计索引,尽量缩小锁的范围
(3)尽可能减少检索条件范围,避免间隙锁
(4)尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行
(5)尽可能低级别事务隔离
六. MVCC隔离机制
- 原理(依靠undo日志与read_view机制共同完成)
(1)undo日志:一行数据被多个事务依次修改后,Mysql保留修改前的undo数据
(2)查询一致性视图read_view:
事务开启后,执行任何查询SQL都会生成当前事务的一致性视图(read_view)该视图由执行查询时所有未提交事务id数组与已创建的最大事务id组成。 -
运行时规则
MVCC视图存储原理
MVCC运行原理.png
read_view视图展示规则
read_view视图展示.png
七. 其他规则补充
-
buffer pool机制
(1)undo日志, redo日志,binlog日志
buffer pool.png
(2)备注
为什么不能一次性写入磁盘中?性能考虑
基于内存操作远快于磁盘操作,磁盘的顺序I/O效率基本等同于内存操作。
磁盘插入数据时随机I/O性能极差。
网友评论