目录
详情参见:MySQL日志管理 - JasonJi - 博客园
多版本并发控制mvcc(multi-version concurrency controll) 基于多版本的并发控制.
在数据库并发量大的时候提高数据库的并发能力,即使有读写冲突的时候也可以做到不用加锁实现非阻塞并发. >>> 保存数据在某个节点的快照,读不加锁,写不冲突,增加并发创建时间版本号, 过期时间版本号, 开启新事务,版本号都会递增.
在mvcc并发控制中, 读操作分为两类>>> 快照读, 和当前读.
快照读就是普通的select 查询语句,不用加锁,
当前读 读取的时最新的记录版本,并且当前读的返回记录都会加上锁, 保证其他事务不会再并发修改这条记录. 指的是insert/ update/delete/select...for update/ select...lock in share mode语句时进行数据据的读取方式. < update/delete要先进行数据的查询才能去进行更改或者删除>
数据库读现象.
脏读,不可重复读,幻读
读的时候可能出现线程安全问题, >>> 脏读,幻读,重复读等.
写写的时候可能存在数据更新丢失的问题, mvcc可以解决读写冲突无锁时的并发控制.
脏读 : read uncommitted (未提交读) 事务中的修改即使没有提交,对其他事务也都是可见的, 事务可以读取未提交的数据

幻读是不可重复读的一种特殊场景. 当事务没有获取范围锁的情况下执行select...where 操作有而可能会发生幻读.
一般情况下解决欢度的方法是增加范围锁, 锁定检测范围为只读,这样就避免了幻读.
>>>>事务执行力两次相同的查询操作,但是两次操作中间事务B向数据库中增加了一条符合事务A的查询条件的数据, 导致幻读.
不可重复读: read committed(提交读) 大多数数据库系统默认的隔离级别
一个事务从开始直到提交前所做的任何修改对其他事务都是不可见的



可重复读 repeatable read 能解决脏读问题, 但无法解决幻读.
幻读指的是某个事物在读取某个范围内的记录时另一个事务又在该范围内插入了新的记录, 当之前的事物再次读取改范围的记录会产生幻行, innodb和xtradb通过多版本并发控制mvcc及间隙锁策略解决该问题.
可串行读 serializable 强制事务串行执行,很少使用该级别.
解决脏读,脏写,不可重复读,幻读都是因为业务系统会多线程并发执行, 每个线程可能都会开启一个事务, 每个事务都会执行增删改查操作. 数据库会并发执行多个事务. 多个事务可能会并发地对缓存页面里的同一批数据进行增删改查操作. 于是这个并发增删改查同一批数据的问题就会导致 上述那些问题.
问题的本质是数据库的多事务并发问题了为了解决这些问题 数据库设计了锁机制, 事务隔离机制.mvcc多版本隔离机制.用一整套的机制来解决多事务并发问题,
锁机制参见:数据库锁机制 - JasonJi - 博客园
首先对mysql锁进行划分: 按照锁的粒度划分:行锁、表锁、页锁
按照锁的使用方式划分:共享锁、排它锁(悲观锁的一种实现)
还有两种思想上的锁:悲观锁、乐观锁。
InnoDB中有几种行级锁类型(三种算法):Record Lock、Gap Lock、Next-key Lock Record Lock:在索引记录上加锁
Gap Lock:间隙锁
Next-key Lock:Record Lock+Gap Lock--》解决幻读问题
行锁:只针对当前操作的行加锁。行级锁能减少数据库操作的冲突。加锁力度最小,但加锁的开销也最大。有可能会出 现死锁的情况。
行级锁按照使用方式分为共享锁和排他锁。
表锁:只针对当前的操作对整张表加锁,资源开销比行锁少,不会出现死锁的情况,但是发生锁冲突的概率很大。
被大 部分的mysql引擎支持,MyISAM和InnoDB都支持表级锁,但是InnoDB默认的是行级锁。是mysql锁中粒度最大的一种锁,
页锁:页级锁是MySQL中锁定力度介于行级和表级中间的一种锁。
表级锁速度快冲突多,行级冲突少速度慢。所以取了 折衷的页级,一次锁定相邻的一组记录。BDB支持页级锁 无论是悲观锁还是乐观锁,他们本质上不是数据库中具体的锁概念,而是我们定义出来,用来描述两种类别的锁的思想
乐观锁和悲观锁的概念不仅仅存在于数据库领域,可以说存在线程安全,存在并发的场景几乎都有乐观锁和悲观锁的适 用场景
悲观锁和乐观锁是一种思想也叫悲观并发控制和乐观并发控制还有MVCC 多版本并发控制 悲观锁PCC:见名知意,悲观的认为你会修改数据,所以在我修改前就加锁,再进行修改
乐观锁OCC:假设数据不会冲突,在数据提交的时候才会进行冲突检测,如果发现冲突了,则让返回用户错误的信息,让 用户决定如何去做。
相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记 录数据版本
事务隔离级别
数据库事务指的则是作为单个逻辑工作单元执行的一系列操作(SQL语句) 功能:
1、为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性 的方法。 2、当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干 扰。 这些操作要么全部执行,要么全部不执行。
事务具有四大特性:
原子性>>> 事务包含多条SQL语句, 且这些SQL语句的特点是 要么同时执行成功, 要么同时执行失败
一致性>>> 事物必须使数据库从一个一致性状态编导另外一个一致性.
隔离性>>> 并发编程中 多个事务之间是相互隔离的,不会彼此干扰
持久性>>> 事务一旦提交产生的结果是永久的 不可逆.
开启事务>> start transaction; update xxx set xxx= xxx where xxx;
事务回滚 >>> roll back ; 执行完事务回滚之后 自动结束, 只要没执行commit操作,其数据就没有真正的刷新到硬盘.
事务确认 >>> commit ; 执行完确认提交后无法回滚, 事务自动结束
保留点>>> savepoint , 为了支持回退部分事务处理,必须在事务处理中合适的位置放置占位符, 这样如果需要回退可以回退到某个占位符(保留点)
创建占位符使用save point
savepoint sp01; 创建占位符
rollback to sp01; 回退到占位符
SQL定义了四种隔离级别,每一种级别都规定了应该事务中所做的修改.
innodb支持所有隔离级别
事务隔离机制的故名思与就是事务彼此之间隔离, 多个事务在同时处理一个数据彼此之间互不影响, 如果隔离的不好就可能会产生脏读,幻读, 不可重复读等现象.
隔离性分为四个级别
由低到高依次为Read uncommitted 、Read committed 、Repeatable read 、Serializable ,这四个级别可以逐个解决脏读 、不可重复读 、幻读 这几类问题。
√: 可能出现 ×: 不会出现

ps: 我们可以采用提高事务的隔离级别的方式来解决脏读, 幻读, 不可重复读等问题, 但事物的隔离级别越高,并发能力就越低.
事务的隔离级别: 未提交读、提交读、可重复读、可序列化'锁'
Read uncommitted(未提交读):在这种事务隔离级别下,一个事务可以读到另外一个事务未提交的数据。可能会脏读
Read committed(提交读):在一个事务修改数据过程中,如果事务还没提交,其他事务不能读该数据。 可能不可重复读
Repeatable read(可重复读):由于提交读隔离级别会产生不可重复读的读现象。所以,比提交读更高一个级别的隔离级 别就可以解决不可重复读的问题。这种隔离级别就叫可重复读
Serializable(可序列化):是最高的隔离级别,前面提到的所有的隔离级别都无法解决的幻读,在可序列化的隔离级别 中可以解决.
innoDB 存储引擎默认隔离级别为可重复读(Repeatable Read),该隔离级别下,避免了脏读、不可重复读现象的产 生,对于索引的查询采用 next-key locks。 这样做就避免了幻读现象(未提交读),(提交读)
事务日志
事务日志可以帮助提高事务的效率, 存储引擎在修改表的数据时只需要修改其内存拷贝, 在把该修改记录到持久在硬盘上的事务日志中, 而不用每次都将修改的数据本身持久到磁盘
事务日志采用的是追加方式, 因此写日志操作是磁盘上一小块区域内的顺序io人不象是随机io需要操作多个地方移动磁头,所以采用事务日志的方式相对来说要快得多,
事务日志持久之后内存中被修改的数据在后台可以慢慢刷回磁盘,此前大多数存储引擎都是这样实现的, 通常称之为'预写式日志'
修改数据需要写两次磁盘.
日志分类
| 日志种类 | 作用 |
|---|---|
| 错误日志 | 记录 MySQL 服务器启动、关闭及运行错误等信息 |
| 事务日志 | 1、redo log重做日志 2、undo log回滚日志 |
| 查询日志 | 记录所有的sql |
| 慢查询日志 | 记录执行时间超过指定时间的操作,如果是全表查询,即便没有超时也会被记录下来 |
| 二进制日志 | 又称binlog日志,以二进制文件的方式记录数据库中除 SELECT 以外的操作。即只记录写操作不记录读操作 |
| 中继日志 | 备库将主库的二进制日志复制到自己的中继日志中,从而在本地进行重放 |
| 通用日志 | 审计哪个账号、在哪个时段、做了哪些事件 |
错误日志
错误日志使用log_error以及log_warnings等参数进行定义
首次启动会提示错误日志位置,后期查询错误日志存放路径的命令如下
[root@db01 ~]# mysqladmin -uroot -pEgon@123 variables | grep -w log_error 或者[root@db01t ~]# mysql -uroot -pEgon@123mysql> show variables like '%log_error%';
详情参见:MySQL日志管理 - JasonJi - 博客园
mvcc多版本并发控制
mvcc只能在read commited, repeatable read 两种隔离级别下工作, 其他两个不兼容. << read uncommitted 总是读取最新, serializable 所有的行都加锁>>
InnoDB的MVCC通过在每行记录后面保存两个隐藏的列来实现MVCC
一个列保存了行的创建时间
一个列保存了行的过期时间(或删除时间) # 本质是系统版本号
每开始一个新的事务版本号都会自动递增,事务开始时刻的系统版本号会作为事务的版本号用来和查询到的每行记录版本号进行比较
例如
刚插入第一条数据的时候,我们默认事务id为1,实际是这样存储的
username create_version delete_version
jason 1
可以看到,我们在content列插入了kobe这条数据,在create_version这列存储了1,1是这次插入操作的事务id。
然后我们将jason修改为jason01,实际存储是这样的
username create_version delete_version
jason 1 2
jason01 2
可以看到,update的时候,会先将之前的数据delete_version标记为当前新的事务id,也就是2,然后将新数据写入,将新数据的create_version标记为新的事务id
当我们删除数据的时候,实际存储是这样的
username create_version delete_version
jason01 2 3
当我们查询记录的时候只有满足两个条件记录才会被显示出来
1.当前事务id大于或者等于当球按行的creative_version值, 这表示事务开始之前这行数据已经存在了
2. 当前事务id要小于delete_version值, 这表示在十五开始之后这行记录才被删除
本文探讨了MySQL中的事务隔离级别,包括读现象、错误日志和MVCC(多版本并发控制)机制。MVCC提高了数据库在高并发情况下的性能,通过快照读和当前读处理读写冲突。事务隔离级别包括读未提交、读已提交、可重复读和可串行化,每个级别解决了特定的并发问题,如脏读、不可重复读和幻读。MVCC主要在可重复读和读已提交级别下工作,利用行的创建和过期时间版本号来实现并发控制。

1539

被折叠的 条评论
为什么被折叠?



