django文档:https://yiyibooks.cn/xx/django_182/topics/db/transactions.html

mysql事务

1) 事务概念

一组mysql语句,要么执行,要么全不不执行。

2) 事务的特点

1、原子性:一组事务,要么成功;要么撤回。

2、稳定性 有非法数据(外键约束之类),事务撤回。

3、隔离性事务独立运行。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。事务的100%隔离,需要牺牲速度。

4、可靠性:软、硬件崩溃后,InnoDB数据表驱动会利用日志文件重构修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit 选项 决定什么时候吧事务保存到日志里。

3) 事务控制语句

BEGIN或START TRANSACTION;显式地开启一个事务;

COMMIT;也可以使用COMMIT WORK,不过二者是等价的。COMMIT会提交事务,并使已对数据库进行的所有修改称为永久性的;

ROLLBACK;有可以使用ROLLBACK WORK,不过二者是等价的。回滚会结束用户的务,并撤销正在进行的所有未提交的修改;

SAVEPOINT identifier;SAVEPOINT允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT;

RELEASE SAVEPOINT identifier;删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;

ROLLBACK TO identifier;把事务回滚到标记点;

4) mysql事务隔离级别

SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
Read Uncommitted(读取未提交内容)

在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)

这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
Repeatable Read(可重读)

这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

Serializable(可串行化) 
       这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:

脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。

不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。

幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几行(Row)数据,而另一个事务却在此时插入了新的几行数据,先前的事务在接下来的查询中,就会发现有几行数据是它先前所没有的。

5) 设置mysql事务的隔离级别

打开mysql配置文件: sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf, 添加如下行。

保存配置文件,重启mysql服务。

  1. sudo service mysql restart

视图函数view.py中

  1. from django.db import transaction # 事务处理
  2. class OrderCommitView(View):
  3. '''订单创建'''
  4. @transaction.atomic() # 事务处理装饰器
  5. def post(self, request):
  6. '''订单创建'''
  7. # 判断用户是否登录
  8. user = request.user
  9. if not user.is_authenticated():
  10. # 用户未登录
  11. return JsonResponse({'res':0, 'errmsg':'用户未登录'})
  12.  
  13. # 接收参数
  14. addr_id = request.POST.get('addr_id')
  15. pay_method = request.POST.get('pay_method')
  16. sku_ids = request.POST.get('sku_ids') # 1,3
  17.  
  18. # 校验参数
  19. if not all([addr_id, pay_method, sku_ids]):
  20. return JsonResponse({'res':1, 'errmsg':'参数不完整'})
  21.  
  22. # 校验支付方式
  23. if pay_method not in OrderInfo.PAY_METHODS.keys(): # 需要在orders/model.py中添加PAY_METHODS字典
  24. return JsonResponse({'res':2, 'errmsg':'非法的支付方式'})
  25.  
  26. # 校验地址
  27. try:
  28. addr = Address.objects.get(id=addr_id)
  29. except Address.DoesNotExist:
  30. # 地址不存在
  31. return JsonResponse({'res':3, 'errmsg':'地址非法'})
  32.  
  33. # todo: 创建订单核心业务
  34.  
  35. # 组织参数
  36. # 订单id: 20171122181630+用户id
  37. order_id = datetime.now().strftime('%Y%m%d%H%M%S')+str(user.id)
  38.  
  39. # 运费
  40. transit_price = 10
  41.  
  42. # 总数目和总金额
  43. total_count = 0
  44. total_price = 0
  45.  
  46. # 设置保存点
  47. save_id = transaction.savepoint()
  48. try:
  49. # todo: 向df_order_info表中添加一条记录
  50. order = OrderInfo.objects.create(order_id=order_id,
  51. user=user,
  52. addr=addr,
  53. pay_method=pay_method,
  54. total_count=total_count,
  55. total_price=total_price,
  56. transit_price=transit_price)
  57.  
  58. # todo: 用户的订单中有几个商品,需要向df_order_goods表中加入几条记录
  59. conn = get_redis_connection('default')
  60. cart_key = 'cart_%d'%user.id
  61.  
  62. sku_ids = sku_ids.split(',')
  63. for sku_id in sku_ids:
  64. # 获取商品的信息
  65. try:
  66. sku = GoodsSKU.objects.get(id=sku_id)
  67. except:
  68. # 商品不存在
  69. transaction.savepoint_rollback(save_id) # 回滚到保存点
  70. return JsonResponse({'res':4, 'errmsg':'商品不存在'})
  71.  
  72. # 从redis中获取用户所要购买的商品的数量
  73. count = conn.hget(cart_key, sku_id)
  74.  
  75. # todo: 判断商品的库存
  76. if int(count) > sku.stock:
  77. transaction.savepoint_rollback(save_id) # 回滚到保存点
  78. return JsonResponse({'res': 6, 'errmsg': '商品库存不足'})
  79.  
  80. # todo: 向df_order_goods表中添加一条记录
  81. OrderGoods.objects.create(order=order,
  82. sku=sku,
  83. count=count,
  84. price=sku.price)
  85.  
  86. # todo: 更新商品的库存和销量
  87. sku.stock -= int(count)
  88. sku.sales += int(count)
  89. sku.save()
  90.  
  91. # todo: 累加计算订单商品的总数量和总价格
  92. amount = sku.price*int(count)
  93. total_count += int(count)
  94. total_price += amount
  95.  
  96. # todo: 更新订单信息表中的商品的总数量和总价格
  97. order.total_count = total_count
  98. order.total_price = total_price
  99. order.save()
  100. except Exception as e:
  101. transaction.savepoint_rollback(save_id) # 回滚到保存点
  102. return JsonResponse({'res': 7, 'errmsg': '下单失败'})
  103.  
  104. # 如果没失败则提交事务
  105. transaction.savepoint_commit(save_id)
  106. # todo: 清除用户购物车中对应的记录
  107. conn.hdel(cart_key, *sku_ids)
  108.  
  109. # 返回应答
  110. return JsonResponse({'res':5, 'message':'创建成功'})

django-mysql事务的更多相关文章

  1. Mysql事务探索及其在Django中的实践(二)

    继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...

  2. Django中MySQL事务的使用

    Django中事物的使用 from django.db import transaction @transaction.atomic通过transaction的@transaction.atomic装 ...

  3. day056-58 django多表增加和查询基于对象和基于双下划线的多表查询聚合 分组查询 自定义标签过滤器 外部调用django环境 事务和锁

    一.多表的创建 from django.db import models # Create your models here. class Author(models.Model): id = mod ...

  4. DJango中事务的使用

    Django 中事务的使用 Django默认的事务行为 默认情况下,在Django中事务是自动提交的.当我们运行Django内置的模板修改函数时,例如调用model.save()或model.dele ...

  5. Django MySQL 数据库连接

    Django 1.11 官方文档 常规说明 数据库连接 CONN_MAX_AGE 定义数据库连接时限(ALL) default:0 保存在每个请求结束时关闭数据库连接的历史行为. None:保持长连接 ...

  6. MYSQL事务的开启与提交

    MYSQL 事务处理主要有两种方法: 1.用 BEGIN, ROLLBACK, COMMIT来实现 BEGIN 开始一个事务 ROLLBACK 事务回滚 COMMIT 事务确认 2.直接用 SET 来 ...

  7. Django 中事务的使用

    目录 Django 中事务的使用 Django默认的事务行为 在HTTP请求上加事务 在View中实现事务控制 使用装饰器 使用context manager autocommit() commit_ ...

  8. 07 模型层 orm相关查询 F查询Q查询 django开启事务

    一.Django终端打印SQL语句 如果你想知道你对数据库进行操作时,Django内部到底是怎么执行它的sql语句时可以加下面的配置来查看 在Django项目的settings.py文件中,在最后复制 ...

  9. Ubuntu14.04 Django Mysql安装部署全过程

    Ubuntu14.04 Django Mysql安装部署全过程   一.简要步骤.(阿里云Ubuntu14.04) Python安装 Django Mysql的安装与配置 记录一下我的部署过程,也方便 ...

  10. MySQL 事务

    MySQL 事务主要用于处理操作量大,复杂度高的数据.比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成 ...

随机推荐

  1. SpringBoot应用部署到Docker上(docker-ce版本)

    配置TCP远程连接(docker-maven-plugin插件连接的地址) # 加上红色标识的部分[root@localhost admin]# vim /lib/systemd/system/doc ...

  2. 【rt-thread】1、快速建立rt-thread nano最小裁剪工程

    快速建立rt-thread nano最小裁剪工程 使用keil5建立 1.下载rt-thread 3.03版本,3.03程序占用最小 2.使用 CubeMX 配置工程 3.选择添加rt-thread ...

  3. Django开发之登陆和登出

    使用django自带的验证模块 1.首先使用python manage.py startapp models为当前项目添加一个应用. 2.在setting.py中INSTALLED_APPS后面添加' ...

  4. H5页面跳转与传值

    页面之间的跳转经常使用a标签,使用mvc框架的都是通过访问controller的请求方法,返回请求页面.但本次开发,前端与后台完全分离,前端APP使用HBuider来开发,后台数据就无法使用mvc框架 ...

  5. 使用poi统计工作职责

    1 创建一个新的sheet工作页 Sheet job = workbook.createSheet("工作职责统计"); 2 查询工作职责问题选项列表,并设置第一行倒出时间 Lis ...

  6. MVC Filter的使用方法

    相信对权限过滤大家伙都不陌生 用户要访问一个页面时 先对其权限进行判断并进行相应的处理动作 在webform中 最直接也是最原始的办法就是 在page_load事件中所有代码之前 先执行一个权限判断的 ...

  7. 【转载】C#中List集合使用Contains方法判断是否包含某个对象

    在C#的List集合中,如果要查找List集合是否包含某一个值或者对象,如果不使用List集合类的扩展方法的话一般会使用for循环或者foreach遍历来查找,其实List集合类中的扩展方法Conta ...

  8. 如何传递大文件(GB级别)

    一.拆分:压缩工具,压缩并拆分为多个小文件. 二.QQ离线传输 QQ离线文件有限制条件: 1.离线传送的文件,为用户保存7天,逾期接收方不接收文件,系统将自动删除该文件: 2. 离线传送的文件,单个文 ...

  9. Flink Runtime核心机制剖析(转)

    本文主要介绍 Flink Runtime 的作业执行的核心机制.本文将首先介绍 Flink Runtime 的整体架构以及 Job 的基本执行流程,然后介绍在这个过程,Flink 是怎么进行资源管理. ...

  10. PHP 将json的int类型转换为string类型 解决php bigint转科学计数法的问题

    /** * 将json的int类型转换为string类型 * @param $str * @param int $minLength 最小的转换位数,即只有大于等于这个长度的数字才会被转换为字符串 * ...