关于MySQL事务的简单讲解

事务:

mysql要开始一个事务需要begin

扁平事务 不能提交或者回滚一部分,最常见的一种事务

三种结果 主动提交 (遇到错误)主动回滚  被动回滚 

带有保存点的扁平事务可以回滚一部分,保存点仅仅是一个标签,事务没提交前,一旦数据库崩溃,事务全部回滚,不会因为保存点而部分回滚

链事务(基本不用):应用于 一个大事务分多次提交, (提交释放锁资源),但是一个大事务多次提交缺不能回回滚

嵌套事务(MYSQL不支持嵌套事务 oracle支持):由若干个事务组成, 中间的部分事务提交 只要总的回滚,那么里面的事务也都会回滚

分布式事务:

核心是 一个事务跨两个数据库  

当一个事务跨两个数据库并且需要独自提交,这时候需要使用分布式事务 可以保证两事务同时提交或者回滚

但是MySQL支持的分布式事务并不好                                                                                                    

对于innodb支持 扁平 带有保存点的扁平 链事务 分布式事务

对于MySQL数据库来讲无论是事务还是sql都要尽可能的简单 。为了减少MySQL中的分布式事务等复杂事务我们可以在程序层面控制,将不同的商品放在不同的数据库中,避免一个事务同时访问两台数据库

对事务的实现必须要有redo 和undo

redo log 作用:

保证事务的持久性,

支持缓冲写

崩溃恢复(前滚恢复速度快,速度稳定,(速度主要取决于io))

redo 分为 两部分: 内存: redo log buffer

                   磁盘: redo log file

redo记录方式:

物理日志的记录方式(对某文件某个页所做的操作),不需要解析,

        

因为物理日志写的单元是512字节,所以不需要double write

redo保证了事务的持久性:

  原因:

日志先行

1、当事务提交的时候,会将redo log buffer中的日志写入到磁盘

2、当log buffer大小占用1/2的时候,会往磁盘里刷新

3、 数据写入磁盘的时候会触发检查点  log chechkpoint

所谓的检查点我们可以认为:

系统恢复的最早的那个点即写入到磁盘的最新脏块的redo log的位置(被记录到ibdata中即最早脏的那个数据块 系统崩溃恢复的时候,检查点作为崩溃恢复检查的起点)

redo 由两部分组成: redo log buffer 、 redo log file(区别与bin log)

通过 innodb_flush_log_at_trx_commit参数来控制写入重做日志的级别;默认值是1 

0:日志缓冲每秒一次地被写到日志文件,并且对日志文件做到磁盘操作的刷新,但是在一个事务提交不做任何操作。

1:在每个事务提交时,日志缓冲被写到日志文件,对日志文件做到磁盘操作的刷新。

2:在每个提交,日志缓冲被写到文件,但不对日志文件做到磁盘操作的刷新。对日志文件每秒刷新一次。网易技术部 67

默认值是 1,也是最安全的设置,即每个事务提交的时候都会从 log buffer 写到日志文件,而且会实际刷新磁盘,但是这样性能有一定的损失。

如果可以容忍在数据库崩溃的时候损失一部分数据,那么设置成 0 或者 2 都会有所改善。设置成 0,则在数据库崩溃的时候会丢失那些没有被写入日志文件的事务,最多丢失 1 秒钟的事务,

种方式是最不安全的,也是效率最高的。设置成 2 的时候,因为只是没有刷新到磁盘,但是已经写入日志文件,所以只要操作系统没有崩溃,那么并没有丢失数据 ,比设置成 0 更安全一些。

当我们批量导数据的时候可以将该参数改为0  (50W个insert 事务,设为1需要50秒,设为0仅需要13秒就可以完成)

redo  特点: 顺序写,在数据库正常运行情况下我们不去读脏块:

事务已经提交,redo log一定已经写入了磁盘

事务没有提交,脏块已经写入到了磁盘,redo log 一定写入到了磁盘

这个事务没有提交,因此回滚的数据一直存在,这个回滚的数据被redo log保护,,保证崩溃恢复的时候undo的正确回滚

事务没有提交,redo log也没有写入磁盘

innodb_log_group_home_dir,最好将redo放在写性能很高的磁盘 如ssd

innodb_log_file_in_group  设置redo file的每组多少个 建议设置5个,设置过低,当切换redo的时候,数据库会出出现短暂的停顿,。

保护了redo log就是保护了事务(redo log的保护比数据文件的保护还要重要)

binlog : 备份恢复, 主从复制   redo log 只对innodb引擎有效,bin log 对innodb 和 myism引擎都有效

redo log是基于页的物理记录方式即记录着该数据对应的页 行的地址,恢复的时候指定在哪恢复

bin log 逻辑层面 是基于语句级的记录方式

LSN号; 每条日志,每个数据页

每一个数据页,每一条日志都有lsn号 检查点也有lsn号  lsn号记录的就是数据的位置

 

double write技术

            

                        

redo lock

 

log group

mysql中,组之间是镜像关系

redo 的日志格式:

redo_log_type 重做日志的类型

space 表空间的ID     

page_no 页的偏移量

redo_log_body具体的操作格式

undo主要的三个作用:

1、事务回滚    

2、MVCC    

3、崩溃恢复

ibdata 共享表空间里第五个页是属于 undo的默认128个段

128个段各自又有多个块,

每个段的第一个块成为段头块

uodo的第一个块被称为系统事务表,分别指向不同段的段头块

段头块:

一个段头块最多可以有1024的slot(可以认为每个段最多可以有1024个事务,即一个数据库最多可以并发128*1024个事务)

一个事务的起始、

事务开始是会生成一个事务id:xid(依次递增),在系统事务表里找到一个相对空闲(活跃事务较少的段)的undo段,将自己的xid写进段头块的一个空闲槽位slot,事务修改数据前,将数据存放到空闲的块中,需要多个块的时候,地址依次相连(undo块使用了链条进行链接),最后一个用到的块会指向段头块的那个槽位

commit: 修改slow 已提交

rollback:

事务没有被提交,slot不会被覆盖,undo块不会被覆盖

找到最后一个块,依次往前回滚

所以如果是一个大事务,回滚时间会很长

崩溃恢复,回滚完,开始前滚,记录了事务的最大id,那说明所有未提交的事务都小于该id

但是并不会马上回滚,当新的事务修改数据块时,发现该数据块的事务未提交,就会前去回滚

事务提交但是没被写入磁盘需要redo 前滚,有些事务没提交但是被写入磁盘则需要undo回滚

undo 段 默认128个 

undo页需要回收。 通过purge线程 

同时支持的活动事务的数量 =undo段数*1024

可以用py_innodb_page_info.py工具来查看当前共享表空间的undo的数量

history list: 

按照事务提交的顺序将已提交的事务连起来,(这些事务也都分别对应着自己的undo块),当我们在purge清空回收undo块的时候,会根据history list 的顺序从尾端依次清空,即先清空事务最早的提交的undo块

show engine innodb status 在transactions中可以监控到history list的长度,当这个长度增长较快的时候

说明数据库undo的刷新可能出现了问题这时可以考虑是否有大量的未提交的事务

表示该数据库的undo已经刷新到了1793,这个事务id, 也就是比这个事务id还小的事务都已经执行

通过以下参数来控制undo

innodb_undo_directory :可以设置undo段文件所在的路径(默认在默认表空间里可以通过修改路径将其放在单独的文件中)

innodb_undo_logs : 设置回滚段的个数(最大值就是128)

innodb_undo_tablespaces  :用来设置构成undo段的文件的数量,即将undo段分配到多个文件里因为下面已经设置了多个raid所以该参数没哟多大意义

关于内存中undo 页的回收即purge 是一个磁盘离散读取的过程消耗Io为了节约undo采用了重用模式,即一个undo页如果备用空间小于3/4那么其他的事务也可以将undo数据存放到该页上节约undo的占用空间

关于事务控制: auto_commit自动提交的原因是 mysql在解决锁的问题上压力很大 

时间: 2024-09-23 13:52:40

关于MySQL事务的简单讲解的相关文章

简单讲解MySQL的数据库复制方法_Mysql

MySQL复制其实就是把数据从一个节点(master) 拷贝到另一个节点(slaves), 当然根据应用架构的不同,采用的方式也不同,MySQL服务器之间的复制使用的是二进制日志机制.对master的更新与变动都会作为事件(event)记录在日志中,日志中的信息会随变化的不同被记录成不同的格式.slaves被配置成从master读取日志,并且执行二进制日志中的事件到slave本地数据库.一旦master启动二进制日志功能,那么所有语句操作都会被记录下来,每一个slave会收到一份整个日志内容的拷

MySQL事务数据库(InnoDB类型)的安装方法

mysql|数据|数据库 MySQL数据库分二种类型,一种是传统的数据表格式,一种是支持事务处理的数据表格式(InnoDB,BDB,其中以InnoDB为主),下面我介绍一下关于MySQL事务处理数据库的安装及使用方法你先要去下载一下Mysql max版的安装程序,下载地址:www.mysql.com按常规的方法进行安装安装完成后,启动mysql\bin\WinMySQLadmin再退出运行mysql\bin\mydqld-nt --removemysql\bin\mysqld-max-nt --

安装MySQL事务数据库(InnoDB)

    MySQL数据库分二种类型,一种是传统的数据表格式,一种是支持事务处理的数据表格式(InnoDB,BDB,其中以InnoDB为主),下面我介绍一下关于MySQL事务处理数据库的安装及使用方法 你先要去下载一下Mysql max版的安装程序,下载地址:www.mysql.com 按常规的方法进行安装 安装完成后,启动mysqlbinWinMySQLadmin 再退出 运行 mysqlbinmydqld-nt --remove mysqlbinmysqld-max-nt --install

mysql事务特性实现并发安全的自增ID示例

 项目中经常会用到自增id,比如uid,下面为大家介绍下利用mysql事务特性实现并发安全的自增ID,感兴趣的朋友可以参考下 项目中经常会用到自增id,比如uid,最简单的方法就是用直接用数据库提供的AUTO_INCREMENT,但是如果用户量非常大,几千万,几亿然后需要分表存储的时候呢,这种方案就搞不定了,所以最好有一个全局的自增ID的生成器,不管是否分表,都能从生成器中获取到全局自增的ID.    实现方法应该有很多,不过所有的方案都需要解决一个问题,就是保证在高并发的情景下,数据获取依然正

MySQL事务内幕与ACID

       MySQL的事务实现严格遵循ACID特性,即原子性(atomicity),一致性(consistency),隔离性(isolation),持久性(durability).为了避免一上来就陷入对ACID的概念理解,我们直接先谈MySQL事务实现机制.             MySQL提供了两种事务型的存储引擎:InnoDB和NDB Cluster.另外还有一些第三方存储引擎也支持事务,比较知名的包括XtraDB和PBXT.下面以InnoDB来说明.             MySQ

PHP使用Mysql事务实例解析_php技巧

本文实例讲解了PHP使用MySQL事物的实例,并备有注释加以详细说明.分享给大家供大家参考之用. 具体实例如下所示: <?php //数据库连接 $conn = mysql_connect('localhost', 'root', ''); mysql_select_db('test', $conn); mysql_query("SET NAMES GBK"); /* 支持事务的表必须是InnoDB类型 一段事务中只能出现一次: mysql_query('START TRANSA

Oracle 和 mysql 的一些简单命令对比参照

mysql|oracle Oracle 和 mysql 的一些简单命令对比参照 Oraclemysql对比版本Personal Oracle7 Release 7.3.4.0.0mysql 3.22.34-shareware-debug启动画面(点击放大)默认安装目录C:\ORAWIN95C:\MYSQL各种实用程序所在目录C:\ORAWIN95\BINC:\MYSQL\BIN控制台工具SVRMGR.EXESVRMGR23.EXEmysqladmin.exe数据库启动程序0start73.exe

MySQL 4.1.0 中文参考手册 --- 6.7 MySQL 事务与锁定命令

mysql|参考|参考手册|中文 MySQL 4.1.0 中文参考手册 --- 犬犬(心帆)翻译 MySQL Reference Manual for version 4.1.0-alpha. 6.7 MySQL 事务与锁定命令6.7.1 BEGIN/COMMIT/ROLLBACK 句法 缺省的,MySQL 运行在 autocommit 模式.这就意味着,当你执行完一个更新时,MySQL 将立刻将更新存储到磁盘上. 如果你使用事务安全表 (例如 InnoDB.BDB),通过下面的命令,你可以设置

PHP和MYSQL联合打造简单留言本程序

数据库结构:(库名:lyb)表一: admin字段: id(int11)   name(varchvr)   password(varchvr) 表二: lo字段: id(int11)   username(varchvr)  sex(varchvr)  qq(varchvr)  email(varchvr)  info(text)  ip(varchvr)  submit_time(datetime) 1 conn.php(连接数据库文件) <?phpmysql_connect("loc