欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~

本文由horstxu发表于云+社区专栏

1. 问题背景

PHP Laravel框架中的db migration是比较常用的一个功能了。在每个版本迭代中,除了代码会变动之外,一般数据库的字段或者数据库表也会有些变动。因此在新版本上线时,除了发布新版代码,不可避免地要把数据库的变动也执行了。在没有db migration功能之前,我们的做法是把要变动库表的SQL语句写好(CREATE TABLEALTER TABLE等)存在一个sql文件中,然后在上线时连接数据库,将sql语句执行一遍。

这么做比较大的一个缺点是没有数据库的版本管理,万一上线失败,要回滚版本,还要把sql文件里的内容再写个反向的SQL(DROP TABLEDROP COLUMN等)。这种方式也比较原始,在web开发中,我们总是希望尽量避免开发直接用原始的sql来操作数据库,出错风险很高,并且很有可能出现不可逆的错误,每次操作都要提心吊胆。

于是乎,PHP Laravel框架提供了db migration的功能,用代码来管理数据库。参考链接

2. 问题描述

在一个新的版本中,我将自己的数据库变更用如下方式记录

php artisan make:migration db_migration_for_new_version

这会在项目的database/migrations目录下创建一个新的PHP文件,自己填入要变更的数据库内容

public function up {Schema::create('a_new_table', function(Blueprint $table) {$table->bigIncrements('id');});Schema::create('another_new_table', function(Blueprint $table) {$table->bigIncrements('id');$table->string('user', 64)->default(0)->comment('用户名');// 这里模拟出现错误的情形throw new \Exception("出现错误");});
}

在上面这个例子中,我的本意是想要创建两个表格。然而在第一个表格创建完了以后,第二个表格出现错误导致创建失败了。按照正常流程,我在上线时应该执行如下指令创建表格

php artisan migrate

由于第二个表格创建失败,这时候上面的指令必然会报错。然而报错之后你应该怎么做呢?首先当然是把代码里出现错误的地方修正,然后应该怎么搞?此时数据库里面第一个表已经建好了,第二个表还没建。这时候你如果再执行php artisan migrate会报错:你第一张表格已经创建,不可重复创建表格。你可能会感觉,我需要回滚一次,于是你可能会执行回滚操作php artisan migrate:rollback --step=1。这里需要强调,此时千万别回滚!!!

因为刚才第一次执行migration出错,导致数据库并没有生成一个新的版本号。这时候如果回滚,那你回滚的是上个版本发布的时候做执行的数据库操作,而不是你刚刚执行的这个版本的数据库操作,这很可能是灾难性的,会导致你数据丢失。目前数据库最新版本是什么,可以参考数据库中migrations表的batch字段(这个表是laravel migration功能自动生成和管理的,并非业务表)。

总结一下这一无解深坑: db migration进行到一半时出错,此时只能手动操作数据库把已经执行的操作回滚掉,无法再通过artisan指令进行回滚

3. 为什么无解?

其实GitHub和StackOverflow上有很多人已经碰到了这个问题,但是答案都很悲观。

所有人的第一反应都是:可以开启事务操作么?将一次migration的所有操作视为一个整体,要么都成功,要么都失败可以么?很遗憾,不支持事务操作。在mysql里面,只有进行update、insert、delete这些常规操作时才可以有事务,而我们migration中执行的都是DDL(Data Definition Language)操作。这种建表(CREATE TABLE)、修改表结构(ALTER TABLE)的操作是无法回滚的,即使开启了事务也无法回滚(参考链接)。把DDL操作放在一个事务(Transaction)中,会导致事务自动的提交(参考链接),这往往不是我们代码逻辑所期望的结果。

4. 那该怎么办?

如果你已经碰到了这种问题,那没办法只得手动去一条一条看数据库发生了什么变化,然后自己执行反向操作。

目前只能想到一些预防此问题出现的办法。根据GitHub上的开发者建议,最好每一个CREATE TABLEALTER TABLE操作都是一个单独的migration。即每次migration只建一张表,或只改一个表结构,只做一个操作( 参考链接)……

还有一种办法是,把自己的建表、改表操作都放在一个try catch结构中,一旦出现错误,直接调用migration文件中的down函数,把所做的操作回滚掉。不过这个需要注意up和down的兼容性。例如up中有ADD COLUMN操作,而down中有DROP COLUMN操作。在ADD COLLUMN操作执行之前就出错,直接取执行down函数中的DROP COLUMN,也会有可能报COLUMN不存在的错误。

总之,这个问题并没有十分完美的解决方案,堪称无解深坑,尤其要注意rollback操作不要乱做 ,不要为了弥补一个坑,给自己挖了更大的一个坑。

问答
PHP功能滥用?
相关阅读
一图弄懂ASCII、GB2312、GBK、GB18030编码
其实你不一定懂csv文件格式
【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识

此文已由作者授权腾讯云+社区发布,更多原文请点击

搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!

海量技术实践经验,尽在云加社区!

这个PHP无解深坑,你能解出来吗?(听说能解出来的都很秀)相关推荐

  1. 不要妄图一夜实现「智能」,这里有AI工业落地几乎必遇的「深坑」

    2020-03-30 17:08:50 作者:寓扬 疫情前,丰融出差去了趟重庆,跟一个客户谈工业大脑的方案.但项目还没来得及落地,疫情已经到来. 丰融是阿里云工业大脑首席解决方案架构师.春节期间,客户 ...

  2. android MultiDex multidex原理原理下遇见的N个深坑(二)

    android MultiDex 原理下遇见的N个深坑(二) 这是在一个论坛看到的问题,其实你不知道MultiDex到底有多坑. 不了解的可以先看上篇文章:android MultiDex multi ...

  3. 深坑之Webview,解决H5调用android相机拍照和录像

    最近在开发过程中遇到一个问题,主要是调用第三方的实名认证,需要拍照和录像; 办过支付宝大宝卡和腾讯的大王卡的都知道这玩意,办卡的时候就需要进行实名认证,人脸识别; 本来第三方平台(xxx流量公司)说的 ...

  4. 终于!有本书把我从“拖延+不专注”的低效深坑里救出来了!

    作者:李小墨 来源:深夜书桌(ID:shenyeshuzhuo) 任务进展没有达到自己和其他人期待的速度,是我每天都在面对的一种失败. 但是终于!鬼知道有多久了,终于有本书把我从拖延.不专注的低效深坑 ...

  5. 【案例解析】 e家洁创始人:O2O创业的痛点与深坑

    家政会成为O2O下一个颠覆对象吗? 2014年是家政O2O的兴起之年, 2015年将是家政O2O的破局之年.随着创业者争相涌入和资本市场不断加码,家政O2O正成为继打车.外卖之后的又一风口.e家洁创始 ...

  6. 【深坑】记一次MacBook pro 恢复出厂设置抹盘重装系统

    电脑卖给朋友,有很多环境配置不好删除,于是决定想抹盘重装系统. 找到了这个官方教程,使用"磁盘工具"抹掉基于 Intel 的 Mac https://support.apple.c ...

  7. 知晓云深坑:数据修改返回401解决办法

    入门小程序时候用的知晓云,然后那时候只用到了数据表权限的查和增,改没写,然后最近开发的时候又用到了知晓云,还用到了改!这里是一个深坑! 返回了401错误,没有权限,然后查文档,查文档,知晓云的文档有点 ...

  8. 知晓云深坑:获取不到数据

    今天用了几个小时来解决一个bug,记录一下: 因为有一段时间没有搞小程序了,突然做熟悉了一会儿才回过神来,因为是一个测试项目用的是知晓云的云数据库. 遇到的问题是:各种配置都已经正常了,访问200成了 ...

  9. 谈谈 跨境劳工的噩梦深坑。

    去年11月,我从上海浦东机场返回新加坡,过海关的时候,队伍前面是一些去坡打工的人,那么海关核对的非常严格,甚至琐碎,不仅仅是查签证,还追问这些人的学历,工作背景,英文技能,工作合同,以及查阅他们和雇主 ...

  10. 去做海外,无数深坑-第一次使用java调用javascript,第一次调用curl

    工作很多年了,发现互联网有着很多以前从来没听过的名词,真是尴尬啊. 前端时间,产品经理提出 [埋点],当时我就有点懵圈,这是啥玩意.后来请求了android的姑娘,大致意思就是我们的操作上报第三方,由 ...

最新文章

  1. java 数组 反射_java数组的反射
  2. Hierarchical Attention Networks for Document Classification(HAN)
  3. 成功解决Exception “unhandled AttributeError“ module ‘cv2.cv2‘ has no attribute ‘estimateRigidTransform‘
  4. ubuntu:无法将“ubuntu1804.exe”项识别为cmdlet、函数、脚本文件或可运行程序的名称。【已解决】
  5. 关乎每个人!2021年5月1日起实施
  6. mysql删除不安全的账户_【20200407】MySQL账号不规则删除导致权限错误
  7. 多线程基础:两种常见的创建线程的方式
  8. Python练习:星号三角形 I
  9. pktgen:DPDK流量生成器
  10. zabbix在ubuntu16.04上的安装
  11. 尚硅谷JDBC笔记(带源码)——了解数据库,看这一篇就够了
  12. 数据库原理与应用教程(何玉洁 第四版)第七章课后题
  13. linux安全工具(RKHunter)
  14. 前端人眼中的大数据生态链
  15. 【FNN回归预测】基于matlab粒子群优化前馈神经网络婚姻和离婚数据回归预测【含Matlab源码 2069期】
  16. Linux驱动编程 step-by-step (二)
  17. 计算机考研数学和英语考什么,考研英语几与数学几的区别?
  18. python中demo函数是什么意思_Python函数(中)
  19. Android项目开发实战常用知识点
  20. android 头部折叠,Android 头像折叠效果

热门文章

  1. UML/ROSE学习笔记系列一:建模原理、概念
  2. (源码)群体智能优化算法之社会蜘蛛算法(Social Spider Algorithm ,SSA)
  3. 【GIS导论】实验一 桌面GIS的功能与菜单操作
  4. python 地理处理包:geopandas介绍
  5. 【ArcGIS|空间分析】在范围内平均生成点 | 面要素内均匀且规定个数来均匀生成点
  6. 实习踩坑之路:实习以来获得的踩坑经验、一些提升开发效率的方法或者常用技巧
  7. kubernetes集群搭建(二进制方式)
  8. Android CertificateSource系统根证书的检索和获取
  9. Android Studio Library生成jar包问题总结
  10. linux删除文件密码不奏效,Linux运维知识之linux_无秘登录问题(不生效)