乐淘资源 干货福利 transaction (1)—mysql进阶(五十七)

transaction (1)—mysql进阶(五十七)

广告位

前面说了当设置的buffer_pool_size在1个G内,则不管如何设置,buffer_pool_instances都是一个,当在1个G以上,mysql才支持多个instances设置,每个都有自己独立的链表,多线程的情况下互不干扰运行。

Show engine innodb status\G

磁盘太慢,内存很有必要,buffer_pool在mysql启动的时候会向系统申请连续的内存空间,buffer_pool_instances 和buffer_pool_chunk_size这几个参数是倍数关系,设置的时候,mysql为了防止浪费内存出现碎片,自动会平衡他们的参数。

为了方便管理,里面有free链表,flush链表,lru链表,

Free链表就是申请空闲的缓存页,flush链表就是修改之后的数据,需要更新到磁盘上的,lru链表又分为young区域和old区域,这里面的数据代表最后 使用数据。Select查询过程是先从磁盘吧数据放入buffer pool缓存页,有自己的控制块,吧控制块放入old区域,如果在buffer_old _block_time,初次和最后一次访问超过这个时间,则会吧数据放入young,这样可以解决全表查询数据太大导致热数据被内存释放,也可以防止预读。

链表里面数据那么多怎么查询呢,通过hash表来查询,key是表空间id+页号,value就是缓存页。

​​多个buffer Pool实例 (3)—Buffer Pool(五十六)​​

为什么要事务?

我们先创建一个表

mysql> create table account(
-> id int not null auto_increment comment '自增id',
-> name varchar(100) comment '客户名称',
-> balance int comment '余额',
-> primary key (id
-> )engine=Innodb charset=utf8;
Query OK, 0 rows affected (0.04 sec)


+----+--------+---------
| id | name | balance |
+----+--------+---------
| 1 | 狗 | 11
| 2 | 猫 | 2
+----+--------+---------+

从上我们可以看到狗有11元,猫有2元,现实生活中,如果猫向狗借10元钱,那么够会变成1元,猫变成12元。那这两个操作在代码里运行其实执行两个sql语句。

UPDATE account SET balance = balance – 10 WHERE id = 1;

UPDATE account SET balance = balance + 10 WHERE id = 2;

但如果执行到一半的时候,断电了或者系统宕机,或者各种原因导致接下来一半不执行,狗的11元减少成功,猫但是还是显示2元,那么整个数据就会乱套。怎么能保证这些和现实中保持一致呢,于是要把现实中的规则带入到代码。

原子性(Atomicity)

现实中,两个人的转账操作是不可分割的,要不压根没转过,要不转账成功,不能一个人转账成功,另一个人没有收到钱。Mysql吧这种要么做就做完整的规则叫做原子性(Atomicity)。但现实中不可分割的操作,在数据库里可能要执行多次,比如两个sql,比如 缓存页的脏数据还没有刷新到磁盘上,最要命的是,任何一个步骤错了,都会导致操作执行不下去,就会导致猫收不到钱。为了保证mysql数据库的原子性,mysql费尽心机吧已经操作的数据如果异常,就恢复到之前的数据,这是我们后面需要仔细唠嗑的回滚。

隔离性(isolation)

现实中两个人转账是互不干扰的,比如狗向猫转账两次5元,那么猫肯定会多10元,狗肯定少10元,那么代码中的过程是什么呢?

  1. 读取狗的金额,read(A)
  2. 狗的金额-5,A = A-5
  3. 吧狗的金额刷新到磁盘,write(A)
  4. 读取猫的金额,read(B)
  5. 猫的金额+5, B =B+5
  6. 吧猫的金额刷新到磁盘,write(B)

现在要操作两次,如果按顺序操作,比如1~6执行完之后,在执行1次1~6的步骤,这样是没有问题的,猫会+10,狗会减少10。

但很不幸的是,数据库真实的操作是这样的,

事务1:read(A)

事务2:read(A)

事务1:A = A-5

事务1:write(A),这时候A是6

事务1:read(B)

事务1:B=B+5.

事务1:write(B),这时候b是7.

事务2:A = A-5,

事务2:write(A),这时候A还是6

事务2:read(B)

事务2:B=B+5

事务2:write(B) 这时候b是12

对于上面那种情况,如果猫加了10元,而狗减了5元,那么银行不是亏本了吗,所以mysql在每个事物之间让他们隔离开,互不干扰。

一致性(Consistency)

我们的生活有形形色色的约束,比如身份证号码不能重复,高考分数目前只能在0~750之间,红绿灯只能有三种颜色,买东西时候单价不能为负数等等,只有符合这些约束才有效,比如有人跟你说今天开车看到个蓝色的红绿灯,你一听就知道是假的。所以mysql数据库也是有约束性的。

其实可以从两方面努力,数据库本身能给我们保证约束性,比如触发器检测金额不能小于0。但这种一般都是不可取的,实际的业务场景里,我们都是通过程序员,因为更改数据库的时候检测是不是金额大于0是非常耗时的,但如果在代码里判断就非常简单,只要在编写业务的时候加个>0的判断就好。

前面的原子性和隔离性,对一致性也有很大的影响,如果原子性 和 隔离性不能保证,那么数据都是错的,根本就不可能保证一致性。

但原子性和隔离性一定满足,就能保证一致性吗,这又不一定,因为如果金额成为了负数,这也是不能满足一致性约束的。

持久性(Durability)

当我们现实生活中,发生借钱事件后,结果将会永久的保存下来,所以在mysql中也是如此,比如狗向猫转账,成功后,猫的账单又回到2,恢复到转账前的样子,那样实不可取。

所以持久性意味着数据必须在磁盘上永久保存。

事务的概念

综上所述,Atomicity,Isolution,Consistency,Durability,合在一起就是ACID,mysql为了方便,直接把这四个统一称为transaction。

事务大致划分四个状态:

  1. 活动的(active):事务对应的数据库操作正在执行中,表示该事务活动的状态。
  2. 部分提交的(partially committed):事务的最后一个操作完成,但因为事务都在内存里进行,还没有刷新到磁盘上,这种称为部分提交。
  3. 失败的(filed):当事务在活动的,部分提交的时候遇到错误,如数据库错误,或者断电等,这时候事务就在失败状态。
  4. 终止的(aborted):当在活动和部分提交之后,出错怎么办呢,失败之后就终止,并且mysql会吧当前的数据恢复到操作前的状态,我们叫这个为回滚。
  5. 提交的(commited):如果成功呢,则就持久化到磁盘上。
本文来自网络,不代表乐淘资源立场,转载请注明出处,如有侵权问题需要处理,请联系站长删除。联系QQ 917118162

作者: admin

上一篇
下一篇
广告位
联系我们

联系我们

在线咨询: QQ交谈

邮箱: 917118162@qq.com

工作时间:周一至周五,9:00-17:30
关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部