应用代码处理事务时,要注意哪些点
- 避免并发。
- 优先使用现成的处理并发的工具。比如数据库唯一约束 ,数据库提供的现成 CAS 原子操作,Django 等 ORM 工具中提供的 F(‘x’) + 1 等现成操作等等。
- 加锁。
- 加乐观锁。乐观锁太复杂容易把开发着绕晕。尽量少用。
- 有时候有少量异常数据是不用关心的。
在过去的开发经验中,数据库提供的谓词锁让我大吃一惊。我一直以为数据库的锁只能锁住已经存在于数据库的记录。没想到谓词锁还可以锁住没有存在的记录。比如:
with transaction():
Order.objects.select_for_update.filter(order__user__name='zhangsan')
上面这个谓词锁会锁住张三的订单,不仅包括张三已经有的订单,就算是要在数据库中新加张三的订单也会被 block 住。
数据库是如何事务的
- 持久性:将数据保存在非易失性存储介质中。基本就是保存到硬盘。最多加上异地备份。
- 隔离性:隔离性是表述数据系统如何处理并发的。基本是通过加锁来实现隔离性的。有不同的隔离级别,对应地也有不同的实现方式(加锁方式)。
- 原子性:通过记录操作,实现操作回滚实现的方式。
- 一致性:没有什么明确的含义。