科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道5.6 怎样处理没有COMMIT/ROLLBACK

5.6 怎样处理没有COMMIT/ROLLBACK

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

MySQL不支持COMMIT-ROLLBACK。问题是有效地处理COMMIT-ROLLBACK将需要完全不同于MySQL今天使用的表布局。MySQL也将需要额外的线程在表上做自动清除工作,而且磁盘用量将更高

作者:天极软件 来源:天极软件 2008年1月23日

关键字: 策略 处理 MySQL

  • 评论
  • 分享微博
  • 分享邮件

MySQL不支持COMMIT-ROLLBACK。问题是有效地处理COMMIT-ROLLBACK将需要完全不同于MySQL今天使用的表布局。MySQL也将需要额外的线程在表上做自动清除工作,而且磁盘用量将更高。这将使MySQL比现今慢上大约2-4倍。MySQL比几乎所有其他SQL数据库都快(一般至少快2-3倍)。原因之一就是缺少COMMIT-ROLLBACK

目前,我们是更多地实现SQL服务器语言(象存储过程),有了它,你将确实很少需要COMMIT-ROLLBACK,这也将得到更好的性能。

通常需要事务的循环可以借助LOCK TABLES进行编码,并且当你能即时地更新记录时,你不需要光标(cursor)。

我们在TODO上有事务和光标,然而并非相当优先。如果我们实现这些,将作为CREATE TABLE的选项,那意味着COMMIT-ROLLBACK将仅工作在那些表上,以便速度损失仅仅强加在那些表上。

我们在TcX有一个更大的需求,一个比100%通用数据库的真正快速的数据库。无论何时我们发现一个方法来实现这些特征而没有任何速度损失,我们将可能做它。暂时,有许多更重要的事情要做。检查TODO,看我们此时如何将事情优先排列。(有的较高级别支持的客户可以改变它,因此事情是可以重新优先化的。)

当前的问题实际上是ROLLBACK,没有ROLLBACK,你能用LOCK TABLES做任何COMMIT动作。为了支持ROLLBACKMySQL将必须被改变以存储所有的旧记录,如果发出ROLLBACK,它们被更新的并且将任何东西恢复到起点。对于简单的情形,这不是难做的 (当前isamlog可以用于此目的),但是为ALTER/DROP/CREATE TABLE实现ROLLBACK将是更困难的。

避免使用ROLLBACK,你可以使用下列策略:

  1. 使用LOCK TABLES ...锁住所有你想要存取的数据库表。
  2. 测试条件。
  3. 如果一切无误,更新。
  4. 使用UNLOCK TABLES释放你的锁。

这通常比使用可能带ROLLBACK的交易是一个更快的方法,尽管不总是这样。这个解决方案不能处理的唯一状况是当某人在更新当中杀死线程时。在这种情况下,所有的锁将被释放,但是一些更改不能被执行。

你也可使函数以单个操作更新记录。你能通过使用下列技术得到一个很有效率的应用程序:

  • 相对他们的当前的值修改字段
  • 仅仅更新那些实际上更改的字段

例如,当我们正在更新一些客户信息时,我们仅仅更新那些改变了的客户数据并只测试没有任何数据的改变,或数据取决于改变的数据,与原来的行相比变化了。对于改变了的数据的测试用WHERE子句在UPDATE语句中完成。如果记录没被更新,我们给客户一条消息:“你改变了的一些数据已被其他用户改变了”,然后我们在一个窗口中显示新行对照旧行,因此用户能决定他该使用哪个版本的客户记录。

这给了我们类似于“列锁定”的东西,但是实际上甚至更好,因为我们仅仅更新某些列,使用相对于他们的当前值的值。这意味着典型的UPDATE语句看上去象这些一样东西:

UPDATE tablename SET pay_back=pay_back+'relative change';

UPDATE customer
  SET
    customer_date='current_date',
    address='new address',
    phone='new phone',
    money_he_owes_us=money_he_owes_us+'new_money'
  WHERE
    customer_id=id AND address='old address' AND phone='old phone';

正如你能看到的,这是很有效的并且就算其他客户已经改变了pay_backmoney_he_owes_us列的也能工作。

在许多情况下,为管理一些表格的唯一标识符目的,用户已经想要ROLLBACKLOCK TABLES。这可用一个AUTO_INCREMENT列和一个SQL函数LAST_INSERT_ID()或C API函数mysql_insert_id()更高效地处理。见20.4.29 mysql_insert_id()

在TcX,我们从来没有任何对行级锁定的需求,因为我们总是能通过编码解决它。一些情况下需要确实行锁定,但是他们是很少见的。如果你想要行级锁定,你可以在表中使用标志列并且这样做:

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;
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章