Welcome 微信登录

首页 / 数据库 / MySQL / 在Twisted下用MySQL adbapi获取自增id

D jango的ORM有一个很便捷的功能,其实也应该说是一个很基本的功能吧。就是在对一个model调用 save() 插入到数据库后,会将创建的自增id同步到当前model上。SQL中调用 INSERT 默认的返回值是插入的行数,就目前的应用来说,其实是一个没啥意义的返回值,所以Django的ORM能够处理好自增id的同步是一件很让人愉悦的事。不过没有使用Django,最近用的是Twisted提供的adbapi,如何获取自增id呢?如果是我力挺的PostgreSQL的话,很简单,给 INSERT 加上 RETURNING 语句就可以了:INSERT INTO distributors (did, dname)
VALUES (DEFAULT, "XYZ Widgets") RETURNING did;
不过MySQL呢?最近用了一阵子MySQL,只是从命令行自动补全这方面来说,就已经明显地感觉到和PostgreSQL的差距了。老实说真不知道为啥那么多人如此热爱深爱着MySQL……在StackOverflow上搜了一下,找到两种方法,要么是使用SELECT LAST_INSERT_ID();
或者是使用connector的 mysql_insert_id() 函数,这个对于Python中的 MySQLdb 来说就是connection的 insert_id() 函数,比如:conn = MySQLdb.connect(host="heaven", user="god",
                       passwd="jesus", db="elysium")
cursor = conn.cursor()
cursor.execute("INSERT INTO account VALUES (%s, %s)",
               ("satan", "male or female, who knows"))
new_id = conn.insert_id() # <= 就是这玩意儿
过程也还算简单,但是对于Twisted的adbapi来说,我们的活并没有结束。为啥呢?因为adbapi用的是线程池来管理MySQL的连接的,每次Query调用,都会从线程池中获取一个线程,然后将相应的事务defer到该线程来处理。其默认的事务是以单个SQL语句为划分的,所以说,对于MySQL这样在执行完后还需要做其他操作的需求来说,默认的接口是无法满足的。这儿我再吐一下槽,还是pg好啊……默认接口不够用,那我们就只能扩展它了。稍稍看一下adbapi的源代码我们可以发现,对于通常事务,adbapi其实是使用了 runInteraction 这个接口函数的。具体不同的事务,adbapi是将相应的callback作为其第一个参数,然后在 deferToThreadPool 时指定线程运行该callback来实现。所以,我们只需要为MySQL定义一种新的事务就可以了。下面就是我们需要定义的新事务:def runMySQLInsert(self, *args, **kw):
    assert self.dbapiName == "MySQLdb"
    return self.runInteraction(self._runMySQLInsert, *args, **kw)def _runMySQLInsert(self, trans, *args, **kw):
    trans.execute(*args, **kw)
    return trans.connection.insert_id()
Ok,接下来,把这两个函数Monkey Patch到adbapi上就完事了:)Ubuntu Oracle ORA-01031: insufficient privilegesMySQL随机查询rand()优化相关资讯      mysql 
  • 数据库服务器 MySQL  (08/15/2013 06:50:23)
  • MySQL 5.6 GA 及逃亡潮  (02/08/2013 14:36:35)
  • MySQL 5.5.22、5.1.62、5.0.96全线  (03/22/2012 19:03:49)
  • MySQL Administrator连接VMWare下  (05/24/2013 09:20:58)
  • MySQL 5.1.68 发布  (02/05/2013 08:37:47)
  • CentOS 5.2+MySQL+Heartbeat双机互  (01/29/2012 11:16:55)
本文评论 查看全部评论 (0)
表情: 姓名: 字数