Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103118230
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: Mysql/postgreSQL

2008-03-24 22:30:10

来源:赛迪网    作者:limeinan

MySQL服务器(3.23至该系列的最高版本,所有4.0版本,以及更高版本)支持采用InnoDB和BDB事务存储引擎的事务。InnoDB提供了全面的ACID兼容性。

MySQL服务器中的其他非事务性存储引擎(如MyISAM)遵从不同的数据完整性范例,称之为“原子操作”。按照事务术语,MyISAM表总能高效地工作在AUTOCOMMIT=1模式下。原子操作通常能提供可比较的完整性以及更好的性能。

由于MySQL服务器支持两种范例,因而你能决定是否利用原子操作的速度更好地服务于你的应用程序,或使用事务特性。该选择可按表进行。

正如所阐述的那样,事务性和非事务性表类型之间的权衡主要取决于性能。事务性表对内存和磁盘空间的要求更高,CPU开销也更大。另一方面,多种事务性表类型,如InnoDB,也能提供很多显著特性。MySQL服务器的模块化设计允许同时使用不同的存储引擎,以满足不同的要求,并在所有情形下,提供最佳性能。

但是,即便使用非事务性MyISAM表,你将如何使用MySQL服务器的特性来保持严格的完整性呢?这些特性与事务性表类型相比又如何呢?

1. 如果应用程序采用了特定的编写方式,依赖于在关键情况下能够调用ROLLBACK而不是COMMIT,那么事务性类型更方便。使用事务,还能确保未完成的更新或崩溃的活动不被提交到数据库,能为服务器提供自动回滚的机会,并保存你的数据库。

如果使用非事务性表,MySQL服务器几乎在所有情况下均允许你解决潜在的问题,方式是在更新前进行简单检查,并运行检查数据库一致性的简单脚本,如果出现不一致性,该脚本能自动修复它或给出告警。注意,仅使用MySQL日志或增加额外日志,通常能完美地更正表,同时不会造成数据完整性损失。

2. 在很多情况下,能够对关键的事务更新进行重写,使之成为“原子”类型。一般而言,所有由事务解决的完整性问题均能用LOCK TABLES或原子更新解决,从而确保了服务器不会自动中断,后者是事务性数据库系统的常见问题。

3. 为了安全使用MySQL服务器,无论是否使用事务性表,仅需启用备份和二进制日志功能。这样,你就能解决使用其他事务性数据库系统时遇到的任何问题。无论使用的数据库系统是什么,启用备份总是个好主意。

事务范型有自己的优点和不足之处。很多用户和应用程序开发人员喜欢这类简单性,在出现问题时或必要时,通过代码解决问题。但是,即使你是原子操作范型的新手,或更熟悉事务,也请考虑非事务性表的速度益处,与经过优化调整的最快的事务性表相比,它的速度快3~5倍。

在完整性具有最高重要性的情况下,即使是对非事务性表,MySQL也能提供事务级别的可靠性和安全性。如果使用LOCK TABLES锁定了表,所有更新均将被暂时中止直至完整性检查完成。如果你获得了对某一表的READ LOCAL锁定(与写锁定相对),该表允许在表尾执行并行插入,当其他客户端执行插入操作时,允许执行读操作。新插入的记录不会被有读锁定属性的客户端看到,直至解除了该锁定为止。使用INSERT DELAYED,能够将插入项置于本地队列中,直至锁定解除,不会让客户端等待插入完成。

从我们赋与其名称的意义上,“原子”绝非不可思议的。它仅意味着,你能确信在每个特性更新运行的同时,其他用户不能干涉它,而且不会出现自动回滚(如果你不小心,对于事务性表,这种情况可能发生)。MySQL服务器还能保证不存在脏读。

 

下面列出了使用非事务性表的一些技术:

· 对于需要事务的循环,通常能使用LOCK TABLES进行编码,不需要光标来更新正在处理的记录。

· 要想避免使用ROLLBACK,可采取下述策略:

1. 使用LOCK TABLES锁定所有希望访问的表。

2. 执行更新前,测试必须为真的条件。

3. 如果一切正常,执行更新。

4. 使用UNLOCK TABLES解除锁定。

与使用具有回滚可能性的事务性表相比,它通常具有更快的速度,虽然并非始终如此。该解决方案唯一不能处理的情形是,在更新中途杀死了线程。在这种情况下,将释放所有锁定,但某些更新可能尚未执行。

◆也可以使用函数在单一操作中更新记录。采用下述技术,能获得效率很高的应用程序。

◆根据其当前值更改列。

◆仅更新出现实际变化的列。

例如,当我们更新某些客户信息时,仅更新已更改的客户数据,与原始行相比,仅测试已更改的数据或依赖于已更改数据的数据是否未出现变化。对于已更改数据的测试,它是通过UPDATE语句的WHERE子句完成的。如果记录未更新,将向客户端发出消息: “一些你改变的数据已被其他用户更改”。接下来,我们在窗口中给出了旧行和新行,以便用户决定使用哪个版本。

这给出了与列锁定类似的结果,但效果更好,使用相对于其当前值的值,仅更新了某些列。这意味着,典型的UPDATE语句与下面给出的类似:

UPDATE tablename SET pay_back=pay_back+125; 
UPDATE customer
  SET    
customer_date='current_date',    
address='new address',    
phone='new phone',    
money_owed_to_us=money_owed_to_us-125  
WHERE    
customer_id=id AND address='old address' AND phone='old phone';

它很有效,即使其他客户端更改了pay_back或money_owed_to_us列中的值,也能使用。

·在很多情况下,用户希望将LOCK TABLES和/或ROLLBACK用于管理唯一ID。可以在不使用锁定功能或回滚的情况下,使用AUTO_INCREMENT列以及LAST_INSERT_ID() SQL函数或mysql_insert_id() C API函数。

我们通常能使用代码来处理行级锁定方面的需求。在某些情况下,实际上不需要它,InnoDB表支持行级锁定。通过MyISAM表,能够在表中使用标志列,并完成类似下面的操作:

UPDATE tbl_name SET row_flag=1 WHERE id=ID;

如果找到行,而且原始行中的row_flag不是1,对于受影响的行数,MySQL返回1。

你可以认为MySQL将前述查询更改为:

UPDATE tbl_name SET row_flag=1 WHERE id=ID AND row_flag <> 1;
阅读(359) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~