标签:attr engine mode lock abc 异步 失败 抛出异常 poi
Python的ORM框架SQLAlchemy基本操作和常用技巧,包含大量实例,非常好的一个学习SQLAlchemy的教程,需要的朋友可以参考下
python编程语言下的一款开源软件。提供了SQL工具包及对象关系映射(ORM)工具,使用MIT许可证发行。
MySQL InnoDB 使用,所以使用其他数据库的也不能完全照搬本文。
mysql
操作系统,遇到问题就 Google 一下吧。我是在 Mac OS X 上开发的,途中也遇到些问题,不过当时没记下来……
值得一提的是我用了 MySQL-Python 来连 MySQL,因为不支持异步调用,所以和 Tornado 不是很搭。不过性能其实很好,因此以后再去研究下其他方案吧……
import create_engine
拿到 session 后,就可以执行 SQL 了:
于是来定义一个表:
接着就开始使用这个表吧:
下面开始介绍一些进阶的知识。
import INTEGER
import randint
1451, ‘Cannot delete or update a parent row: a foreign key constraint fails (`ooxx`.`friendship`, CONSTRAINT `friendship_ibfk_1` FOREIGN KEY (`user_id1`) REFERENCES `user` (`id`))‘) ‘DELETE FROM user WHERE user.age < %s‘ (50,) 原因是删除 user 表的数据,可能会导致 friendship 的外键不指向一个真实存在的记录。在默认情况下,MySQL 会拒绝这种操作,也就是 RESTRICT。InnoDB 还允许指定
ON DELETE 为 CASCADE 和 SET NULL,前者会删除 friendship 中无效的记录,后者会将这些记录的外键设为 NULL。
除了删除,还有可能更改主键,这也会导致 friendship 的外键失效。于是相应的就有 ON UPDATE 了。其中 CASCADE 变成了更新相应的外键,而不是删除。
而在 SQLAlchemy 中是这样处理的:
为什么无法删除 in 操作查询出来的记录?
not evaluate current criteria in Python. Specify ‘fetch‘ or False for the synchronize_session parameter. 但这样是没问题的:
1, User.id == 2, User.id == 3)).delete() 搜了下找到《Sqlalchemy delete subquery》这个问题,提到了 delete 的一个注意点:删除记录时,默认会尝试删除 session 中符合条件的对象,而 in 操作估计还不支持,于是就出错了。解决办法就是删除时不进行同步,然后再让
session 里的所有实体都过期:
如何正确使用事务?
假设有一个简单的银行系统,一共两名用户:
> user1.money
两次转账都成功了,但是只转走了一笔钱,这明显不科学。
可见 MySQL InnoDB 虽然支持事务,但并不是那么简单的,还需要手动加锁。
首先来试试读锁:
现在在执行 session1.commit() 的时候,因为 user1 和 user2 都被 session2 加了读锁,所以会等待锁被释放。超时以后,session1.commit() 会抛出个超时的异常,如果捕捉了的话,或者 session2 在另一个进程,那么 session2.commit() 还是能正常提交的。这种情况下,有一个事务是肯定会提交失败的,所以那些更改等于白做了。
接下来看看写锁,把上段代码中的 ‘read‘ 改成 ‘update‘ 即可。这次在执行 select 的时候就会被阻塞了:
user1 = session2.query(User).with_lockmode(‘update‘).get(1)
这样只要在超时期间内,session1 完成了提交或回滚,那么 session2 就能正常判断 user1.money >= 100 是否成立了。
由此可见,如果需要更改数据,最好加写锁。
那么什么时候用读锁呢?如果要保证事务运行期间内,被读取的数据不被修改,自己也不去修改,加读锁即可。
举例来说,假设我查询一个用户的开支记录(同时包含余额和转账记录),可以直接把 user 和 tansefer_log 做个内连接。
但如果用户的转账记录特别多,我在查询前想先验证用户的密码(假设在 user 表中),确认相符后才查询转账记录。而这两次查询的期间内,用户可能收到了一笔转账,导致他的 money 字段被修改了,但我在展示给用户时,用户的余额仍然没变,这就不正常了。
而如果我在读取 user 时加了读锁,用户是无法收到转账的(因为无法被另一个事务加写锁来修改 money 字段),这就保证了不会查出额外的
tansefer_log 记录。等我查询完两张表,释放了读锁后,转账就可以继续进行了,不过我显示的数据在当时的确是正确和一致的。
另外要注意的是,如果被查询的字段没有加索引的话,就会变成锁整张表了:
要避免的话,可以这样:
10, 2), index=True) 另一个注意点是子事务。
InnoDB 支持子事务(savepoint 语句),可以简化一些逻辑。
例如有的方法是用于改写数据库的,它执行时可能提交了事务,但在后续的流程中却执行失败了,却没法回滚那个方法中已经提交的事务。这时就可以把那个方法当成子事务来运行了:
此外,rollback 一个子事务,可以释放这个子事务中获得的锁,提高并发性和降低死锁概率。
如何对一个字段进行自增操作?
最简单的办法就是获取时加上写锁:
如果不想多一次读的话,这样写也是可以的:
标签:attr engine mode lock abc 异步 失败 抛出异常 poi
原文地址:http://www.cnblogs.com/wt11/p/7164066.html