当前位置: 首页 > news >正文

事务操作的统计,TPS的计算,隔离级别的读提交

对于事务操作的统计

因为InnoDB存储引擎是支持事务的,因此对于InnoDB存储引擎的应用,在考虑每秒请求数(Question Per Second,QPS)的同时,也许更应该关注每秒事务处理的能力(Transaction Per Second,TPS)。

计算TPS的方法是(com_commit+com_rollback)/time。但是用这种方法计算的前提是:所有的事务必须都是显式提交的,如果存在隐式的提交和回滚(默认autocommit=1),不会计算到com_commit和com_rollback变量中。如:

show global status like 'com_commit'\G  5

insert into t select 3;

select * from t\G

show global status like'com_commit'\G  5

MySQL另外还有2个参数handler_commit和handler_rollback。但是我注意到,这两个参数在MySQL 5.1中可以很好地用来统计InnoDB存储引擎显式和隐式的事务提交操作,而在InnoDB Plugin中该参数的表现有些“怪异”,并不能很好地统计事务的次数。所以,如果你的程序都是显式控制事务的提交和回滚,那么可以通过com_commit和com_rollback进行统计。如果不是,那么情况就显得复杂了。

事务的隔离级别

令人惊讶的是,大部分数据库系统都没有提供真正的隔离性,最初或许是因为系统实现者并没有真正理解这些问题。如今这些问题已经弄清楚了,但是数据库实现者在正确性和性能之间做了妥协。ISO和ANIS SQL标准制定了四种事务隔离级别的标准,但是很少有数据库开发厂商遵循这些标准,比如Oracle数据库就不支持read uncommitted和repeatable read的事务隔离级别。

SQL标准定义的四个隔离级别为:

  1. READ UNCOMMITTED
  2. READ COMMITTED
  3. REPEATABLE READ
  4. SERIALIZABLE

READ UNCOMMITTED称为浏览访问(browse access),仅仅只对事务而言的。

READ COMMITTED称为游标稳定(cursor stability)。

REPEATABLE READ是2.9999˚的隔离,没有幻读的保护。

SERIALIZABLE称为隔离,或3˚。SQL和SQL 2标准的默认事务隔离级别是SERIALIZABLE。

InnoDB存储引擎默认的支持隔离级别是REPEATABLE READ,但是与标准SQL不同的是,InnoDB存储引擎在REPEATABLE READ事务隔离级别下,使用Next-Key Lock锁的算法,因此避免幻读的产生。这与其他数据库系统(如Microsoft SQL Server数据库)是不同的。所以说,InnoDB存储引擎在默认REPEATABLE READ的事务隔离级别下已经能完全保证事务的隔离性要求,即达到SQL标准的SERIALIZABLE隔离级别。

隔离级别越低,事务请求的锁越少,或者保持锁的时间就越短。这也是为什么大多数数据库系统默认的事务隔离级别是READ COMMITTED。

在InnoDB存储引擎中,可以使用以下命令来设置当前会话或者全局的事务隔离级别:

SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL

{

  READ UNCOMMITTED

  |READ COMMITTED

  |REPEATABLE READ

  |SERIALIZABLE

}

如果想在MySQL库启动时就设置事务的默认隔离级别,那就需要修改MySQL的配置文件,在[mysqld]中添加如下行:

[mysqld]

transaction-isolation=READ-COMMITTED

查看当前会话的事务隔离级别,可以使用:

select @@tx_isolation\G

查看全局的事务隔离级别,可以使用:

select @@global.tx_isolation\G

在SERIALIABLE的事务隔离级别,InnoDB存储引擎会对每个SELECT语句后自动加上LOCK IN SHARE MODE,即给每个读取操作加一个共享锁。因此在这个事务隔离级别下,读占用锁了,一致性的非锁定读不再予以支持。因为InnoDB存储引擎在REPEATABLE READ隔离级别下就可以达到3˚的隔离,所以一般不在本地事务中使用SERIALIABLE的隔离级别,SERIALIABLE的事务隔离级别主要用于InnoDB存储引擎的分布式事务。

在READ COMMITTED的事务隔离级别下,除了唯一性的约束检查以及外键约束的检查需要Gap Lock,InnoDB存储引擎不会使用Gap Lock的锁算法。但是使用这个事务隔离级别需要注意一些问题。首先,在MySQL 5.1中,READ COMMITTED事务隔离级别默认只能工作在Replication(复制)的二进制日志为ROW的格式下。如果二进制日志工作在默认的STATEMENT下,则会指出如下的错误:

create table a(b int,primary key(b))engine=innodb;

set @@tx_isolation='read-committed';

select @@tx_isolation\G

begin;

insert into a select 1;

ERROR 1598(HY000):Binary logging not possible.Message:Transaction level

'READ-COMMITTED'in InnoDB is not safe for binlog mode'STATEMENT'

MySQL 5. 0版本之前不支持ROW格式的二进制日志时,也许有人知道,可以通过将参数innodb_locks_unsafe_for_binlog设置为1,来使得可以在二进制日志为STATEMENT下使用READ COMMITTED的事务隔离级别:

select @@version\G

system cat/etc/my.cnf | grep innodb_locks_unsafe_for_binlog

innodb_locks_unsafe_for_binlog=1

show variables like 'innodb_locks_unsafe_for_binlog'\G

***************************1.row***************************

Variable_name:innodb_locks_unsafe_for_binlog

Value:ON

set @@tx_isolation='read-committed';

begin;

insert into a select 1;

commit;

是的,的确可以通过上述办法使得在MySQL 5.0的版本之前使用READ COMMITED事务隔离级别。但是就像参数innodb_locks_unsafe_for_binlog的名称一样,它是unsafe的。在某些情况下,可能会导致master和slave之间数据的不一致。

接着来演示一种可能导致不同步的情况,首先来看下表a中的数据:

select * from a\G

***************************1.row***************************

b:1

***************************2.row***************************

b:2

***************************3.row***************************

b:4

***************************4.row***************************

b:5

4 rows in set(0.00 sec)

接着在master上开启一个会话A执行如下事务,并且不要提交:

#Session A on master

begin;

delete from a where b<=5;

在master上开启另一个会话B,执行如下事务,并且提交:

#Session B on master

begin;

insert into a select 3;

commit;

接着会话A提交,并查看表a中的数据:

#Session A on master

commit;

select * from a\G

***************************1.row***************************

b:3

但是在slave上看到的结果却是:

#Slave

select * from a;

可以看到,数据产生了不一致。导致这个问题发生的原因有两点:首先,在READ COMMITTED事务隔离级别下,事务是没有Gap Lock锁的,因此我们可以在小于等于5的范围内再插入一条记录;其次,statement记录的是master上产生的SQL语句,因此在master上是先删后插,但是在STATEMENT格式中记录的却是先插后删,逻辑上就产生了不一致。因此,使用READ REPEATABLE事务隔离级别就可以避免第一种情况的发生,因而也就避免了master和slave不一致问题的产生。

在MySQL 5.1的版本之后,因为支持了ROW格式的二进制日志记录格式,所以避免了第二种情况的发生,因此可以放心使用READ COMMITTED的事务隔离级别。即使不使用READ COMMITTED的事务隔离级别,也应该考虑将二进制日志的格式更换成ROW,因为这个格式记录的是行的变更,而不是简单的SQL语句,因此可以避免一些不同步现象的产生。

 

相关文章:

  • JavaScript的parseint()函数
  • 枚举 类和结构体
  • MongoDB 查询总结
  • 【成长之路】【python】python基础3
  • 一路风景,一路欣赏,一路有你
  • 唇读、生成式对抗网络、自动音乐生成都是些什么鬼?且看人工智能年度科技盘点(提供PDF干货下载)...
  • proguard 不混淆第三方jar包的问题
  • 使用mysqlbinlog提取二进制日志
  • centos7源码编译安装Subversion 1.9.5
  • 数据分析入门--https://cn.udacity.com/
  • 基于组件的设计工作流与界面抽象
  • HDU 3783 ZOJ
  • Java 9进入第一轮问题修复阶段
  • N的倍数
  • shell脚本,根据字符串获取行号的
  • [PHP内核探索]PHP中的哈希表
  • #Java异常处理
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • Git学习与使用心得(1)—— 初始化
  • JSDuck 与 AngularJS 融合技巧
  • Node + FFmpeg 实现Canvas动画导出视频
  • Redis字符串类型内部编码剖析
  • SwizzleMethod 黑魔法
  • Vue2.0 实现互斥
  • 今年的LC3大会没了?
  • 排序(1):冒泡排序
  • 判断客户端类型,Android,iOS,PC
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 我的面试准备过程--容器(更新中)
  • 我建了一个叫Hello World的项目
  • 赢得Docker挑战最佳实践
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • ​你们这样子,耽误我的工作进度怎么办?
  • ()、[]、{}、(())、[[]]等各种括号的使用
  • (3)nginx 配置(nginx.conf)
  • (day6) 319. 灯泡开关
  • (SpringBoot)第七章:SpringBoot日志文件
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (理论篇)httpmoudle和httphandler一览
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (转载)(官方)UE4--图像编程----着色器开发
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .net 受管制代码
  • .NET程序员迈向卓越的必由之路
  • .NET命名规范和开发约定
  • .NET委托:一个关于C#的睡前故事
  • .NET正则基础之——正则委托
  • @Transactional类内部访问失效原因详解
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [ vulhub漏洞复现篇 ] AppWeb认证绕过漏洞(CVE-2018-8715)
  • [ABP实战开源项目]---ABP实时服务-通知系统.发布模式
  • [AIGC] Kong:一个强大的 API 网关和服务平台
  • [Apio2012]dispatching 左偏树