线上只执行一次的脚本编写注意事项

时间:2021-07-07 09:25:55

线上只执行一次的脚本编写注意事项(此文章会不定时更新)

业务需要:不管是为了修复历史数据,还是在新加需求时,当你无法直接用sql完成数据修改时,可能你就需要编写临时的执行脚本来处理数据了。


以下是我编写的其中一个简单的临时方法文件,实现的是将指定条件下的数据查询出来,并处理成理想的格式,添加到新的表中。为防止出错,使用了事务(多表操作的话就一定要使用事务,原因的话事务的特性和作用就能解释,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消)。

<?php
namespace Home\Controller;
use Think\Controller;
class ImportController extends Controller {

// 手动入库
public function handleAddStoreStockIn () {
$model = M();
$m_stockCount = D('TestCount');
$cond['TP_RealNum'] = ['gt', 0]; // 实际数量
$cond['TP_StoreId'] = ['not in', ['2067','2074']]; // 门店ID
$spDatas = D('TestProduct')->getProductList($cond, 'TP_RealNum,TP_StoreId,TP_Id'); // 商品库存记录表 -- 数据
$productCountDic = [];
foreach ($spDatas as $value) {
$productCountDic[$value['TP_StoreId']][$value['TP_Id']] += $value['TP_RealNum']; // 计算门店对应的商品总数
}

$model->startTrans();

foreach ($productCountDic as $_storeId => $_product) {
foreach ($_product as $_productId => $_count) {

$countData['TC_Store'] = $_storeId;
$countData['TC_Product'] = $_productId;
$countData['TC_Count'] = $_count;
// 添加至库存
$addCountRes = $m_stockCount->add($countData);
if (!$addCountRes) {
$model->rollback();
echo '添加数量失败';
exit();
}
}
}
$model->commit();

echo '入库成功';
exit();
}
}

可能有人就发现,我这里是在循环中的做添加,而不是将数据整理起来,直接用addAll()一次添加,这就是我要说的第一个注意事项了

  foreach ($productCountDic as $_storeId => $_product) {
foreach ($_product as $_productId => $_count) {

$countData['TC_Store'] = $_storeId;
$countData['TC_Product'] = $_productId;
$countData['TC_Count'] = $_count;
// 添加至库存
$addCountRes = $m_stockCount->add($countData);
if (!$addCountRes) {
$model->rollback();
echo '添加数量失败';
exit();
}
}
}

1.循环获取数据做添加处理时,如若数据量过大,建议不要用addAll()一次性处理添加,首先数据过大时,一次性直接处理添加时,数据库在此承受的压力会很大,可能会出错,搞不好也会崩掉了,分批次添加就分担掉了这个压力。
在这个文件中没有加‘?>’ 终止符,这是第二个注意,实际上在一般php代码编写中,都最好不要加。

2.如果是PHP和HTML混编时,一定要有结束符号‘?>’,否则有可能导致语法错误。如果是一个纯粹的PHP页面,最后的结束符‘?>’最好一定不要添加。这样做的好处是:如果这个是一个被别人包含的程序,没有这个结束符,可以减少很多很多问题。

比如说:header,
setcookie, session_start这些动作之前不能有输出,如果不小心在‘?>’
后边加了不可见字符(多余的空格、换行符)等破坏页面显示,就会报‘Header already
sent’错误,不写的话不会有此问题。