Mysql-事务及锁机制

事务的基本概念
数据库事务是构成单一逻辑工作单元的操作集合
注意点:
1.数据库事务可以包含一个或多个数据库操作,但这些操作构成一个逻辑上的整体
2.构成逻辑整体的这些数据库操作,要么全部执行成功,要么全部不执行
3.构成事务的所有操作,要么全部对数据库产生影响,要么全部都不产生影响,即数据库保持一致性状态
4.并发操作下,事务的控制尤为关键。

事务的种类:
基本事务 声明式事务 分布式事务

ACID
Atomicity :事务中的所有操作作为一个整体像原子一样不可分 要么成功要么失败
快照保证原子性 undo log之后总结

Consistency:事务执行结果必须使数据库从一个一致性状态到另一个一致性状态
一致性状态是指:1.系统的状态满足数据的完整性约束2.系统的状态反应数据库本应该描述的现实世界的真实状态,比如转账
一致性是ACID的最终追求

Isolation:并发执行的事务不会相互影响
锁机制来实现隔离性
这里提一下几个锁
共享锁:用户可以并发的读取数据,但任何事务都不能够修改直至释放所有的共享锁
排它锁:如果事务对数据加上排它锁之后,其他事务不能够在对其加上任何的锁
独占锁:和排它锁一个意思 但是是在myisam上面这么叫
record lock:单个记录上锁
gap lock:间隙锁 锁定一个范围 不包括记录本身
Next-key lock:record+gap 锁定一个范围 包括记录本身
意向锁:锁行的时候检查是否有表锁,如果没表锁则加锁成功 如果就表锁就直接失败 大范围到小范围的过程
自增锁:就是自增id自身支持的

duration:事务一旦提交,其对数据库的更新就是持久的。任何事务或系统故障都不会导致数据丢失
write ahead log预写日志保证数据->内存->硬盘这个过程不会因为断电等其他因素导致数据丢失
redo log保证持久性

原子性实现的原理:undo log
undo和redo日志是归属于innodb,bin是归属于mysql的server层

undo log是为了实现事务的原子性,这里就是指的数据回滚,在innodb还使用 undo log来实现多版本并发控制MVCC

在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方就是Undo log)。然后进行数据的修改。如果出现了错误或者用户执行了rollback语句,系统就利用undo log中的备份恢复数据

提一嘴这里的undo log是逻辑日志 是对数据的修改 实际的物理日志 是对内存页的修改

持久性实现原理:redo log
和undo log相反,redo log记录的是新数据的备份。在事务提交之前,只要将redo log持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是redo log已经持久化,系统可以将所有数据恢复到最新的状态

Mysql的隔离级别
事务具有隔离性,理论上来说事务之间的执行不应该相互产生影响,其对数据库的影响应该和他们串行执行时一样 然而完全地隔离性会导致系统并发性能很低,降低对资源的利用率,因而实际上对隔离性的要求会有所放宽,这也会一定程度造成数据库一致性要求降低
sql标准为事务定义了不同的隔离级别 从低到高一次是:
read-uncommitted 对事务处理的读取没有任何限制 引发脏读、不可重复读、幻读
read-committed: 引发不可重复度、幻读
repeatable read:(mysql默认) 引发幻读
serializable:

脏读:ab两个事务a查询到了b事务还没提交更改的数据
不可重复读:同一个事务里面读取相同的数据查到了不同的结果
幻读:幻读是读取相同的数据查到了多条不同的结果
这里区分一下不可重复读和幻读

####不可重复读和幻读的区别####
很多人容易搞混不可重复读和幻读,确实这两者有些相似。但不可重复读重点在于update和delete,而幻读的重点在于insert。
如果使用锁机制来实现这两种隔离级别,在可重复读中,该sql第一次读取到数据后,就将这些数据加锁,其它事务无法修改这些数据,就可以实现可重复 读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会 发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来避免。需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。
所以说不可重复读和幻读最大的区别,就在于如何通过锁机制来解决他们产生的问题。

这里了解下MVCC
每张表 都有两列用户不可见的 createtime和deletetime 其中createtime是事务递增id deletetime为空
在执行查询的时候 会查询开始事务createtime是<=当前事务createtime的数据 且deletetime是>=当前事务id 或是空的记录
所以RC永远都是读的最新数据 而RR是读的快照数据

innodb行锁是通过给索引上的索引项来实现的 只有通过索引条件来检索数据 innodb才使用行锁 否则 innodb将使用表锁

lock in share mode 是共享锁
for update 是排它锁

猜你喜欢

转载自blog.csdn.net/lirenci123/article/details/109549723