<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Leric&#039;s Blog &#187; MySQL</title>
	<atom:link href="http://www.leric.info/tag/mysql/feed" rel="self" type="application/rss+xml" />
	<link>http://www.leric.info</link>
	<description>Temec Nosce</description>
	<lastBuildDate>Sun, 18 Apr 2010 02:32:41 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PostgreSQL性能测试(转)</title>
		<link>http://www.leric.info/post/70.htm</link>
		<comments>http://www.leric.info/post/70.htm#comments</comments>
		<pubDate>Thu, 10 Dec 2009 03:13:39 +0000</pubDate>
		<dc:creator>Leric</dc:creator>
				<category><![CDATA[计算机技术]]></category>
		<category><![CDATA[Benchmark]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[性能测试]]></category>

		<guid isPermaLink="false">http://leric.net.cn/post/70.htm</guid>
		<description><![CDATA[http://www.randombugs.com/linux/mysql-postgresql-benchmarks.html
很迷惑为什么PostgreSQL这样优秀的一个项目总是不被接受，网上搜出的和MySQL的对比都在说PostgreSQL比MySQL慢得多，而证据都是三四年前的某个测试数据。昨晚找到了一个09年6月的帖子，测试方式还算比较严谨，数据在上面的链接里可以看到，作者得出了以下结论：

MySQL 5.0.51a-24+lenny1 – Debian stable version is the worst performer (also the MySQL version is a little bit old). 
MySQL 5.1.30/InnoDB 1.0.3 with Google SMP patch – Compiled by SUN and InnoDB compiled by ORACLE outperform PostgreSQL in some cases. 
PostgreSQL 8.3.7-0lenny1 – Debian Stable version – It’s a top performer from the Debian standard [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.randombugs.com/linux/mysql-postgresql-benchmarks.html">http://www.randombugs.com/linux/mysql-postgresql-benchmarks.html</a></p>
<p>很迷惑为什么PostgreSQL这样优秀的一个项目总是不被接受，网上搜出的和MySQL的对比都在说PostgreSQL比MySQL慢得多，而证据都是三四年前的某个测试数据。昨晚找到了一个09年6月的帖子，测试方式还算比较严谨，数据在上面的链接里可以看到，作者得出了以下结论：</p>
<ul>
<li>MySQL 5.0.51a-24+lenny1 – Debian stable version is the worst performer (also the MySQL version is a little bit old). </li>
<li>MySQL 5.1.30/InnoDB 1.0.3 with Google SMP patch – Compiled by SUN and InnoDB compiled by ORACLE outperform PostgreSQL in some cases. </li>
<li>PostgreSQL 8.3.7-0lenny1 – Debian Stable version – It’s a top performer from the Debian standard distro and is out performed only by the latest InnoDB 1.0.3. </li>
<li>Differences between PostgreSQL and MySQL 5.1.30/InnoDB 1.0.3 are very small </li>
<li>PostgreSQL is outperforming any MySQL version on Creating, Loading, Created Indexes operations (this can be very usefull on a DB recovery). </li>
<li>I don’t know why PostgreSQL is performing bad on bulk_delete() bulk_modify() querys … is possible to have a glitch in my configurations?</li>
</ul>
<p>除了一个批量删除和批量修改的操作PostgreSQL慢的有点离谱（和MySQL相差6000多倍），应该能算是个Bug了，其他的性能大多还是比MySQL要好的。当然这里都是和InnoDB比较的，若是和MyISAM相比的话，慢点儿也是正常，因为MyISAM的功能太少，少了很多必要的操作和约束，对于任何一个业务系统，没有事务支持都是肯定不行的，不过这在MySQL的主要应用领域——网站上并不是个大问题。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leric.info/post/70.htm/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>用于MySQL的WF WorkflowPersistenceService</title>
		<link>http://www.leric.info/post/48.htm</link>
		<comments>http://www.leric.info/post/48.htm#comments</comments>
		<pubDate>Fri, 20 Nov 2009 18:17:37 +0000</pubDate>
		<dc:creator>Leric</dc:creator>
				<category><![CDATA[计算机技术]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Windows Workflow Foundation]]></category>
		<category><![CDATA[WorkflowPersistenceService]]></category>

		<guid isPermaLink="false">http://leric.net.cn/?p=48</guid>
		<description><![CDATA[因为微软的Workflow Foundation里对WorkflowPersistenceService只提供了一个用于SqlServer的实现，对于想用别的方式保存工作流状态的应用就需要自己实现WorkflowPersistenceService了，今天自己写了个用于MySQL的实现，应该说是一个最简陋的实现了，只完成了最简单的保存和恢复的功能，高级点儿的加锁之类的功能还没弄明白。不过我想这些对学习WF的朋友应该也能帮上点儿忙。
数据库只有三个字段：
id     varchar(36)   Workflow Guid
state   blob              Workflow State Serialized
status    tinyint       Workflow  Status
代码如下：
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace Ganji.OA.Workflow
{
    public class MysqlWorkflowPersistenceService : WorkflowPersistenceService
    {
        public MysqlWorkflowPersistenceService()
            : base()
 [...]]]></description>
			<content:encoded><![CDATA[<p>因为微软的Workflow Foundation里对WorkflowPersistenceService只提供了一个用于SqlServer的实现，对于想用别的方式保存工作流状态的应用就需要自己实现WorkflowPersistenceService了，今天自己写了个用于MySQL的实现，应该说是一个最简陋的实现了，只完成了最简单的保存和恢复的功能，高级点儿的加锁之类的功能还没弄明白。不过我想这些对学习WF的朋友应该也能帮上点儿忙。<span id="more-48"></span></p>
<p>数据库只有三个字段：</p>
<blockquote><p>id     varchar(36)   Workflow Guid<br />
state   blob              Workflow State Serialized<br />
status    tinyint       Workflow  Status</p></blockquote>
<p>代码如下：</p>
<pre>using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace Ganji.OA.Workflow
{
    public class MysqlWorkflowPersistenceService : WorkflowPersistenceService
    {
        public MysqlWorkflowPersistenceService()
            : base()
        {}

        public List GetAllWorkflows()
        {
            List result = new List();
            Database db = DatabaseFactory.CreateDatabase("OAData");
            DbCommand command = db.GetSqlStringCommand("SELECT id FROM workflow_state");
            DbDataReader reader = command.ExecuteReader();
            while (reader.Read())
            {
                result.Add(new Guid((string)reader["id"]));
            }
            reader.Close();
            return result;
        }

        protected override Activity LoadCompletedContextActivity(Guid scopeId, Activity outerActivity)
        {
            Guid instanceId = WorkflowEnvironment.WorkflowInstanceId;
            Activity activity = Deserialize(instanceId, scopeId, outerActivity);
            return activity;
        }

        protected override Activity LoadWorkflowInstanceState(Guid instanceId)
        {
            Activity activity = Deserialize(instanceId, Guid.Empty, null);
            return activity;
        }

        protected override void SaveCompletedContextActivity(Activity activity)
        {
            Guid instanceId = WorkflowEnvironment.WorkflowInstanceId;
            Guid contextId = (Guid)activity.GetValue(Activity.ActivityContextGuidProperty);
            Serialize(instanceId, contextId, activity);
        }

        protected override void SaveWorkflowInstanceState(Activity rootActivity, bool unlock)
        {
            WorkflowStatus status = GetWorkflowStatus(rootActivity);
            Guid instanceId = WorkflowEnvironment.WorkflowInstanceId;

            if (status == WorkflowStatus.Terminated || status == WorkflowStatus.Completed)
            {
                DeleteWorkflow(instanceId);
            }
            else
            {
                Serialize(instanceId, Guid.Empty, rootActivity);
            }
        }

        protected override bool UnloadOnIdle(Activity activity)
        {
            return true;
        }

        protected override void UnlockWorkflowInstanceState(Activity rootActivity)
        {
        }

        private void Serialize(Guid instanceId, Guid contextId, Activity activity)
        {
            byte[] state = WorkflowPersistenceService.GetDefaultSerializedForm(activity);
            Database db = DatabaseFactory.CreateDatabase("OAData");
            String sql_del = "DELETE FROM workflow_state WHERE id=@id";
            DbCommand command_del = db.GetSqlStringCommand(sql_del);
            db.AddInParameter(command_del, "@id", DbType.String, instanceId.ToString());

            String sql = "INSERT INTO workflow_state (`id`, `state`, `status`) VALUES (@id, @state, @status)";
            DbCommand command = db.GetSqlStringCommand(sql);
            db.AddInParameter(command, "@id", DbType.String, instanceId.ToString());
            db.AddInParameter(command, "@state", DbType.Binary, state);
            db.AddInParameter(command, "@status", DbType.Byte, 0);

            using (DbConnection conn = db.CreateConnection())
            {
                conn.Open();
                db.ExecuteNonQuery(command_del);
                db.ExecuteNonQuery(command);
                conn.Close();
            }
        }

        private Activity Deserialize(Guid instanceId, Guid contextId, Activity outerActivity)
        {
            Database db = DatabaseFactory.CreateDatabase("OAData");
            string sql = "SELECT * FROM workflow_state WHERE id='" + instanceId.ToString() + "'";
            Activity activity = null;
            using (DbDataReader reader = db.ExecuteReader(CommandType.Text, sql) as DbDataReader)
            {
                if (reader.HasRows)
                {
                    reader.Read();
                    byte[] state = (byte[])reader["state"];
                    reader.Close();
                    activity = WorkflowPersistenceService.RestoreFromDefaultSerializedForm(state, outerActivity);
                }
            }
            return activity;
        }

        private void DeleteWorkflow(Guid instanceId)
        {
            Database db = DatabaseFactory.CreateDatabase("OAData");
            string sql = "DELETE FROM workflow_state WHERE id=@id";
            DbCommand command = db.GetSqlStringCommand(sql);
            db.AddInParameter(command, "@id", DbType.String, instanceId.ToString());
            using (DbConnection conn = db.CreateConnection())
            {
                conn.Open();
                command.ExecuteNonQuery();
                conn.Close();
            }
        }
    }
}</pre>
<p><strong><span style="color: #ff0000;">重要更正: </span></strong> 在Pro WF书里说保存和恢复Activity的状态是用的Activity对象的Save和Load方法，这样保存的对象信息有六十多KB，还只是对于一个只有5个状态的小工作流，这个尺寸放在MySQL的blob里都放不下，造成了运行时一开始可以正常的存入工作流状态，但状态变更后，工作流序列化后的对象增大，保存进数据库的时候被截断了，造成了下次从数据库取得状态时报一个“在分析完成之前就遇到流结尾。”的错误，浪费了近一天的时间去解决这个问题。最终在<a href="http://msdn.microsoft.com/zh-cn/library/system.workflow.runtime.hosting.workflowpersistenceservice.loadworkflowinstancestate.aspx">MSDN的一篇文章</a>的一小段例子里，看到它恢复Activity状态用的是WorkflowPersistenceService对象的这个方法</p>
<pre><span>protected</span> <span>static</span> Activity <span>RestoreFromDefaultSerializedForm</span>(
	byte[] <span>activityBytes</span>,
	Activity <span>outerActivity</span>
)</pre>
<pre>相应的保存Activity状态的方法是：
<pre><span>protected</span> <span>static</span> byte[] <span>GetDefaultSerializedForm</span>(
	Activity <span>activity</span>
)</pre>
<pre>这一对方法对序列化的状态用GZIP进行了压缩，上面六十多KB的数据现在只有13K左右了。</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.leric.info/post/48.htm/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
