Electronic Joint Business

Solution for E-Business

sql

基于 MYSQL 存储引擎实现虚拟数据表查询 (二)

在上一篇文章中,我阐述了如何基于 MYSQL 存储引擎从 API 中检索数据,并回馈给 MYSQL。特别是我需要从 MySQL 控制台上获得最新的系统进程列表。本文是对上一篇文章的改进,你将看到我们无须对 MySQL 解析器做任何修改就可以解决同样的问题。1

ProcessInfoEngine
这里的存储引擎不同于常见的 MyISAM 或者 InnoDB 等存储引擎,它从 Windows 进程 API 中检索数据并回馈给 MySQL。为此我们创建数据表 runningprocesslist ,其存储引擎是 ProcessInfoEngine。

`PROCESSNAME` varchar(2048) DEFAULT NULL,
  `ProcessID` int(11) DEFAULT NULL,
  `Threadcount` int(11) DEFAULT NULL,
  `ParentprocessID` int(11) DEFAULT NULL,
  `Priorityclass` int(11) DEFAULT NULL
) ENGINE= ProcessInfoEngine

当用户在 runningprocesslist 数据表上执行 select 查询时,控制权被交给 ProcessInfoEngine 的 rnd_init 方法。该方法会检查数据表名称是否真的为 “RunningProcessList”,然后再检查 where 子句解析树是否存在。如果存在,where 子句解析树将被遍历以便转换成 OpenProcess 调用。如果不存在 where 子句,那么我们将创建进程快照,并将所有进程的信息回馈给 MySQL。

int ha_example::rnd_init(bool scan)
{
        DBUG_ENTER("ha_example::rnd_init");
       
        if(_stricmp(table_share->table_name.str,"RunningProcessList")==0)
        {
                THD *thd=this->ha_thd();
                SELECT_LEX *select_lex=&thd->lex->select_lex;
                m_processListIndex=0;

                if(select_lex->where==0)
                {
                        GetAllProcessList(m_processList);
                }
                else
                {
                        stack<parsestackelement> parseStack;
                        select_lex->where->traverse_cond(My_Cond_traverser,(void*)&parseStack,Item::traverse_order::POSTFIX);
                        if(!parseStack.empty()&&parseStack.size()==1)
                        {
                                GetProcessListSpecifiedInWhereClause(m_processList,parseStack.top().setOfProcessIds);
                        }
                        else
                        {
                                GetAllProcessList(m_processList);
                        }
                }
        }
        DBUG_RETURN(0);
}

在后序遍历 Where 子句解析树时, 我们创建并维护了名为 ParseStackElement 这样一个栈结构。

>>> 阅读全文

 

,

基于 MYSQL 存储引擎实现虚拟数据表查询 (一)

文章评价:
MySQL 支持多种可用于存储管理与检索的存储引擎,最常见的是 MyISAM 和 InnoDB 。创建数据表时可以指定存储引擎。最简单的存储引擎只能读取数据表。大多数引擎支持从文件读取数据并回馈给 MySQL。所以,我设想调用 API 来检索数据并将数据直接回馈给 MySQL。在此之上,我们可以利用 SQL 语句对检索到的数据进行复杂分析。为此我需要在相关 API 之上编写一个引擎,不过我并不打算从头开始编写新引擎,而是打算构建一个通用的组件让所有存储引擎调用,这将大大简化编写引擎的工作。1

背景
我希望透过 MySQL 对系统中的进程进行分析,通过 MySQL 控制台上获得运行中的进程的列表,进而执行复杂分析,比如说查询某个进程所包含的模块。为了提供简单的视图,我希望将这些以数据表的形式呈现,由存储引擎来调用相关 API 检索数据。API 是操作系统中现成的。对于其他部分,传统办法是创建数据表,每当有新进程启动就插入新的数据行,有进程终止时就删除数据行。

显然这种方法有很多缺点:

  • 插入删除数据行都是系统开销。
  • 在查询数据表前,你需要触发负责插入或删除数据行的日志程序。
  • 即便只需查看单一进程,数据表中还是需要维护所有进程的信息。
  • 一旦进程终止它的进程 ID 又为新进程所用,这时如旧数据行未删除就插入新数据行会产生 ID 冲突。
  • 插入或删除需要表锁定,可能会是整个检索单元的性能瓶颈。

因此新的构思应当解决这些问题:

  • 无需插入或删除数据行
  • 查询数据表之前无需触发日志应用
  • 如只查询单一进程则不用读取所有进程的消息
  • 无进程 ID 的不一致性,因为该数据表只是系统的状态快照
  • 无性能瓶颈,因为没有插入或删除操作

好处
新构想比传统方法更好地解决了一个具体问题:即表中的数据可以有时间轴。当表的大小达到一定限度时,可以创建新表。这也是使用 Tableau 商业智能工具进行分析时的要求。Tableau 可以生成 SQL 查询。为方便起见,要求使用单个表而在背后维护多表间的关系。我们可以生成编程式查询来检索某时间段内的数据并显示在 web 页面上,但 Tableau 无法使用这些程序。一种传统技术是将数据复制到单个表中,但同时我们所维护多表的关联就会失效。另一种传统技术是使用视图,但是在视图背后使用编程式查询会导致视图失效。我所构想的是只公开单个数据表,利用 API 从多个表中检索数据。编写存储引擎可以提供解决方法。最简单的引擎会回馈所有的数据让 MySQL 筛选,但这非常低效。而我所构想的存储引擎将利用 MySQL 查询分析器的强大能力。在 MySQL 查询期间 where 子句会被转换为对函数和 API 的调用,这样某种程度上我们只要检索所需的数据。这个构想广义上可以推广到任何 API,无需重写生成 API 调用等核心逻辑。

>>> 阅读全文

 

, , ,

MVCC (一)概述

本文的作者是 Trek Palmer,他是 NuoDB 的工程师,负责实现及调试 NuoDB 的 Atom 层。在过去的一年中, Palmer 一直致力于分布式事务一致性方面的研究。在与客户的沟通中, Palmer 发现最常被问起的问题之一就是:如何在接受众多节点的更新的同时保持一致性。答案就是:分布式上下文中多版本并发控制(MVCC) 的实现。想要理解这一点,你必须对 MVCC 有相当的了解。Palmer 是并发方面的专家,也当过教师,所以他在博客上对 MVCC 做了一系列的详细的技术解释。1 2

MVCC 剑指何方?
数据库的设计思想很纯粹:攫取数据、保存数据、并按所需的格式返回数据。出于实用性考虑,任何数据库都应能同时处理尽可能多的请求。 SQL 是一种声明性语言。也就是说,像 average 这样的 SQL 语句并未规定它该如何执行,只是罗列了数据库执行语句时要操作的参数。当程序员与数据库交互时,细节部分被转交给了数据库本身。这是好事,意味着应用逻辑和数据存储的细节的分离。这样做的后果之一是,数据库本身要能管理多个并发客户端。特别是,数据库需要处理在不同事务(来自多个客户端)同时读取和写入同一数据片的情况。

如果你看过传统的并行代码,可能会问“为什么不使用读/写锁?”。这种想法是合理的,而且多年来也一直为一些数据库所使用。然而,它有个严重的问题。简单地说,读阻塞写,写阻塞读。读/写锁的语义本身就是如此,没什么特别惊讶的。然而,这些语义对任何事务型数据库的性能都会产生严重的不良影响。

思考一下,假如系统中有两种事务:一种是只读的长事务,用于创建报告或者数据分析。一般只有一两个并发用户。而另一些是与用户进行交互的短事务,比如说在线下单,这类交互通常包括两读和一写(或两写)。并发用户可能有成千上万。读/写锁的问题是,如果短事务的写操作与长事务的读操作之间有任何数据重叠,短事务会被阻塞,直到长事务完成。对习惯互联网消费的人来说,哪怕长事务只是造成订单延迟几秒钟,也是不能接受的。问题在于如何同时保证合理延迟和最高并发性。理想情况下,阻塞只应在事务真的影响另一事务更新数据行时才发生(实际上,阻塞只是可用的数据库并发控制机制之一) 。拿上面的例子来评估,情况应该是:长事务永远不应造成短事务阻塞;短事务之间除非更新到同一行,否则不应互相影响或阻塞。当读/写锁力不从心时,这一壮举该如何完成?对 NuoDB 和许多现代数据库来说, 答案是:多版本并发控制。

什么是 MVCC?
你可能会说,“很好,我了解 MVCC 要解决什么问题了,不过是如何解决的呢?” 答案就在它的名字中。对非 MVCC 数据库来说,每条既定记录都有其固定存储点,并在该存储点上进行着各种花销的锁,而 MVCC 数据库允许既定记录同时拥有多个版本。每次对数据行进行更新都会产生一个新版本。因此,写操作竞争的是往数据行最高版本之上添加新版本的权利,而读操作则可以读取任何可见版本。对上面的例子来说,这意味着只读的长事务永远不会锁定数据行。因此不会导致短事务被阻塞。而且,只有两个(或更多)短事务争相获得某个数据行版本的更新权利时,才会彼此干扰。如果在维护事务中的可见性信息的同时找出可见的数据行版本,MVCC 就可以实现数据库快照。实际上,当事务开始时,它会“冻结”一揽子数据记录版本作为其可见数据集。对这些版本进行更新逻辑上发生在事务读取该数据集之后(哪怕执行事务的线程没有实际读取该数据行版本) 。要支持 MVCC 语义你需要的是:记录存储系统,可以为同一记录保存不同版本;某种锁定系统,可以让其它事务知道记录被同步更新了;以及将记录版本号翻译为事务ID 的机制,以进行可见性计算。

>>> 阅读全文

 

,

NuoDB 数据库的架构

一直以来,关系型数据库被设计成向上扩容(scale-up) 的架构。换句话说,要处理更多的负载,就需要更强大的计算机。这意味着,如果在几年前想要支持水平扩容(scale-out)的架构,你要嘛得放弃 SQL,要嘛得用上分区(sharding)、Active-Passive 复制等技巧。想在一个弹性的逻辑数据库上实现真正的 ACID 编程模型是不太可能的。这个矛盾正是 NewSQL 运动的矛头所向,也是 NuoDB 的灵魂所在。1

NuoDB 是为云扩展而设计的关系型数据库。这句话该怎么理解呢?NuoDB 是真正的 SQL 服务:它拥有 ACID 事务的所有属性、标准的SQL 语言、以及真正的关系型逻辑,这一切都深受用户喜欢。最重要的是,从最初的设计开始,NuoDB 就能按云服务的方式进行伸缩。

关于“云扩展”的定义有点老生常谈。如果感兴趣,你可以到我们的技术博客上了解什么是云扩展。简单来说,除了支持水平扩容的模型外,我觉得它还应包括敏捷、易用、可自动化、安全以及高可用性。本文就是从这个观点出发的.。2

请注意,NuoDB “只是”个软件。它能够运行在 Linux、Mac 或者 Windows 上,无论这些系统被安装在笔记本、私有云或公有云上。NuoDB 可以部署在 Amazon Web Services 或 Google Compute Engine 上,或者可以集成 OpenStack 一起使用,或者就在笔记本上作为本地 Windows 服务运行。NuoDB 十分灵活,你可以随心所欲地进行测试、开发,之后再部署到你想要的地方。

本文将重点要介绍什么是 NuoDB,它采用了什么架构来应对现今世界的挑战,以及你可用 NuoDB 来解决什么问题。阅读完本文,你应该可以对 NuoDB 的关键概念和架构的不同之处有所了解。你也可以了解到一些实际部署和管理的特性,并对自己的 NuoDB 数据库进行伸缩。

>>> 阅读全文

 

, , , , ,

HadoopDB 入门 (二) 配置MySQL

文章评价:
在上一篇文章中,我们介绍了如何对 HadoopDB 和 PostgreSQL 进行配置,以便它们能在一起工作。在本文中,我们将介绍如何在 HadoopDB 中配置另一种普遍使用的数据库来。在文章的前一部分,我还会涉及如何在 Ubuntu 中安装并运行起 HadoopDB,已经熟悉的朋友可以直接跳过这一部分。这里我使用的是 64 位的 Ubuntu Server 10.04,并且广泛地使用 Ubuntu 的包管理器,本文介绍的安装方式,对于其他的 Linux 系统比如 CentOS 也应该是适用的。

本文介绍的是如何配置一个单节点系统,如果您需要一个多节点系统,可以参考上一篇文章中的介绍,你将会发现对 HadoopDB 进行扩展是多么的简单。

安装 Hadoop
安装 Hadoop 之前,首先需要安装 Java。你可以从 Oracle 的站点下载 Sun JDK,或者使用 OpenJDK 也没有任何问题,在 Ubuntu 上,运行下面命令就可以安装 OpenJDK:

sudo apt-get install openjdk-6-jdk

Michael Noll 写过一篇文章深入讨论了如何在 Ubuntu 上安装 Hadoop,我强烈建议您在开始之前读一下这篇文章,本文很多内容都是借鉴该文章的。

首先我们先创建需要运行 Hadoop 帐号和组:

>>> 阅读全文

 

, , , , , ,

HadoopDB 快速上手指南

HadoopDB 是由美国耶鲁大学计算机科学教授 Daniel J. Abadi 及其团队推出开源并行数据库。该数据库集合关系型数据库的数据处理能力与 Hadoop、MapReduce 等技术于一身,采用了许多不同的开源组件,包括开源数据库、PostgreSQL、Apache Hadoop 技术和 Hive 等等。

HadoopDB 的查询是利用 MapReduce 或常规的 SQL 语言完成的。MapReduce 适用于大规模数据集(大于1TB)的并行计算。另一方面,HadoopDB 的数据处理部分是利用Hadoop 完成的。Abadi表示,其中部分是利用了分布在无分享计算机群集中的许多节点上的不同 PostgreSQL 实例完成的。实质上,HadoopDB是MapReduce和并行数据库管理系统技术的混血儿。不过和 Aster Data、Greenplum或Hive等已经开发出的项目和厂商不同,HadoopDB不是简单地在语言/接口层面上的混合,它是更深的系统实现层面上的集成。

因为集两种技术的精华于一身,HadoopDB 可以取得 MapReduce 等大规模并行数据基础设施的容错性。在这些基础设施中,服务器故障对整个网络的影响非常小。HadoopDB可以执行复杂的分析,速度几乎与已有的商用并行数据库一样快。

本文的目的是为运行HadoopDB给出一些指导。整个 HadoopDB 的设计概述可以在VLDB 论文的第五节找到。在该论文中,你还可以找到我们测试 Hadoop (带 HDFS)、HadoopDB 和商用并行数据库的测试结果比较。

HadoopDB 的基本原理是利用 Hadoop 来存取部署在集群上多个单一节点上的 DBMS 服务器(比如:PostgreSQL 或 MySQL)。通过发起 SQL 查询,HadoopDB 将尽可能多的数据处理推给数据库引擎来进行(通常情况下,大部分的映射/组合 – Map/Combine 阶段的逻辑可以用 SQL 来表达)。这样就创建了一个类似于无共享并行数据库的系统。应用从数据库世界得到的技术大大提升了性能,特别是在更复杂的数据分析上。同时,HadoopDB 依赖于 MapReduce 框架的事情确保了系统在高可扩展性和容错、异构性(heterogeneity)方面的效果与 Hadoop 类似。详细内容请再次参考 VLDB 论文。

>>> 阅读全文

 

, , , , , , ,

Oracle 启动过程

通常所说的 Oracle 服务器主要由两个部分组成: 数据库实例 Instance 和数据库 Database。数据库实例是指一组后台进程(在 Windows 上是一组线程)和一块共享内存区域;数据库是指存储在磁盘上的一组物理文件。通过 Instance 与 Database 协同,Oracle 数据库服务器才能形成一个动态的可访问关系型数据库系统。

数据库管理员最常见的工作之一就是启动或者停止 Oracle 数据库。通常来说,我们并不希望经常让数据库停机,因为:

  • * 会给用户群造成不便
  • * 每次重启数据库,就得冒它无法启动的风险
  • * 关闭数据库会清空 Oracle 内存区域,比如数据库缓冲 cache

重启之后的数据库的性能总会慢一点,这种状况会持续到数据库内存区域被“预热”了。不过有时候我们不得不关闭数据库,例如:

  • * 需要打补丁或者升级
  • * 进行某些应用维护
  • * 进行离线数据库备份-冷备份 (通常推荐热备份这样可以避免关闭数据库)
  • * Oracle 软件存在的某个 bug 要求在某些情况下重启数据库

当需要再次启动数据库的时候(使用 shutdown 和 startup 命令),我们用 SQL*Plus 来发出这些指令。下面详细了解一下这些命令。

Oracle Startup 命令
用 startup 命令可以启动 Oracle 数据库。首先要用有 sysdba 或 sysoper 权限的帐号登录,比如 SYS 用户。下面的例子演示了 DBA 是如何连接到数据据库,并启动 instance :

>>> 阅读全文

 

, , ,

数据库与事务处理

介绍
数据库是与某一企业相关的数据项的集合,通常存储描述企业当前状态的信息,例如,一家银行的数据库存储每个储户当前的账户余额。当现实世界中的某一事件改变了企业的状态,存储在数据库中的信息必须做相应的改变,这些改变通常由称为事务(transaction)的程序实时地实现。事务管理是对企业应用最紧要的要求之一。在贸易、金融和电子商业领域中,多数大的企业应用依赖于递送它们的商务的事务处理功能。 鉴于当今商务对灵活性的要求,在构造、部署和维护企业级别的分布式应用中,事务处理占据的是其中最复杂的部分之一。

本文把以下内容介绍给读者:

  • 什么是事务? 什么是 ACID?
  • 建造一个事务应用的要点是什么? 事务管理中间件为什么很重要?
  • 事务处理应用的典型的体系是怎样的? 体系中的各种构件的职责是什么?
  • 事务处理系统涉及哪些概念?
  • 事务管理领域中有哪些标准和技术?

本文不特定于任何产品,力图在描述各种要点和概念时保持普遍性。本文不打算比较各种事务处理的技术/标准,只是提供对此的一个讨论。

什么是事务?
为了完成对数据的操作,企业应用经常要求并发访问在多个构件之间共享的数据。这些应用在下列条件下应该维护数据的完整性(由应用的商务规则来定义):分布式访问一个单独的数据资源,以及从一个单独的应用构件访问分布式资源。

在这种情况,可能要求在(分布式)资源上的一组操作被当作一个工作单元(unit)。在一个工作单元中, 操作的所有部分一起成功或失败并恢复。在下面的情况下这个问题更加复杂:通过一组分布式的、访问多个资源的数据的构件实现一个工作单元,和/或部分操作是被顺序执行的或在要求协调和/或同步的并行线程中。

>>> 阅读全文

 

, ,

在Azure中运行MySQL

由于不同的原因,我手头的许多Azure应用都必须依赖于MySQL。例如,我手头的Joomla开发就完全依赖于MySQL。大部分情况下,这是因为在应用中使用了MySQL的原生驱动,而未不是设计一个数据库独立层,类似.NET中的ADO.NET或者PHP中的PDO,或者裁剪掉那些MySQL特有特性。基于上述的理由,要在Windows Azure中运行这些应用,不得不想方设法让MySQL在Azure中运行。

这其实没有想象的困难,在此过程中,我可以重用许多二进制可执行文件。

想法与建议
在深入让MySQL运行起来的技术细节之前,我想先分享一下个人对于在Azure中运行MySQL的观点,在我告诉你别这么做之前,你可以节约阅读这篇文章的时间,

现实是即使你能在Windows Azure中运行MySQL,这么做也不太实际。我的建议是把它保留做你最后的法宝或者权宜之计直到Sql Server能够支持你的应用。我这么说是有许多原因的,有些是技术方面的,有些是财务方面的。因此,本文更多是关注在Azure运行和管理MySQL的过程,而不是非要这么做。

现在,让我们来深入技术问题。在Azure中运行MySQL的方法是创建一个Worker Role,它会作为二进制文件的实际宿主。你只要拷贝出可执行文件,然后编写简单的Windows Azure相关代码来实际执行应用,并传递请求给它。事实上,任何可执行文件只要可以通过xcopy发布而且无休止运行的都可以通过这个方法来实现。这对于进行分布式计算之类的事情是相当棒的。

>>> 阅读全文

 

, , , ,

在.NET中使用嵌入式Firebird (附驱动更新)

Firebird 脱胎于 Borland 公司的开源版数据库 Interbas e6.0,是一个完全非商业化的产品, 用 C 和 C++ 开发。由于与 interbase 的血缘关系,大部分 interbase 的开发工具可以直接应用 到 Firebird 开发中。

Firebird 2.0 项目已于 2005年2月份开发完成,2005年5月发布。下面列举一些 Firdbird 2.0 新增加的功能:

  • 对 SQL 标准支持增强:支持 SQL200X 标准定义的“派生表”(derived tables)、为了和 SQL-99 标准一致,引进了“SEQUENCE”,用来代替“GENERATOR”;
  • 经典结构模式(Classic architecture)支持全部API;
  • 支持 64 位操作系统平台;
  • 内置函数增加;
  • 存储过程语言(PSQL)增强:支持“显式游标”、存储过程支持默认参数、支持“LEAVE标号”语法、将用户自定义函数(UDF)作为存储过程调用等;
  • 索引得到增强:252字节限制取消、支持“表达式索引”等;
  • 改进的优化器;
  • 安全增强:安全数据库结构改变、口令加密更安全、远程不能访问安全数据库、阻止“暴力破解”行为;
  • 在线增量备份。

单从功能上,Firebird 比 SQLite 要强大许多,并且 FireBird 有多种版本,包括服务器版,单机版以及嵌入式,不管是服务器版还是嵌入式版它都完整支持视图、触发器、存储过程等SQL高级特性。

部署嵌入式FireBird十分简单,只需要把 fb Embedded Server 的 “fbembed.dll” 拷贝到应用程序目录下。在 .net 的工程项目中则可以包含 fbembed.dll 文件,并将其属性设置为 “copy always” 或者 “copy if newer” 即可。

在 C# 中使用嵌入式 Firebird 需要 .net provider 1.6以上版本,典型的 ConnectionString 如下:

>>> 阅读全文

 

, , , , , ,

详解MongoDB的DBRefs

比方说,有个内容丰富的站点,它囊括了诸如 blog ,图片之类的内容,也有日程安排, 文章引用的等等东西。这样许许多多截然不同的内容而且他们彼此之间又没有什么共性:blog 有标题和文本,图片有图片链接和缩略图, 文章引用有引文和作者的名字等等。它们的唯一共性就是站点上所有的东西被存储在不同的 MongoDB 集合中,而且都有一个属性 _Id。

现在有个需求,要求用户可以针对这个网站的所有内容都可以发表评论,也就是说,每个人都可以任选站点的任意内容评头论足一番。如果所有的东西都存储在 MySQL 或者其他关系数据库中,我们可能这样设计:我们可以给不同的数据表都添加上一栏comments:blogpost_comments,picture_comments等等。我们也可以选用另一个方法,创建一个新的数据表comments,并存储评论的内容的id和类型type。这样查询起评论就满简单的:

SELECT * FROM comments WHERE type = ‘picture’ AND object_id = 123

第二种方法和 DBRef 的工作方式类似,即利用类型 type 和 id。你可以参考这篇 文章。DBRef 的格式如下

{ $ref :<collname>, $id :<idvalue>; [, $db :<dbname>; ] }

正如你所见的,$ref有个参数 collection name,就是上面的 type。而 $id,当然就是 id 了。(这儿有个字段:$db,不过当我们只有一个 MongoDB 数据库时,它就没什么用处了)。用 MongoDB 我们这样来存储 comments表:

{
author: "John Doe",
text: "Oh, such a great picture",
object: { $ref: "pictures", $id: ObjectID("4b0552b0f0da7d1eb6f126a1") }
}

这就是全部。

>>> 阅读全文

 

, , ,