엑셀 10만건 디비 등록중 페이지가 ERR_TIMED_OUT 되요
본문
excel_file.php
excel_upload.php
그누보드/lib/PHPExcel/IOFactory.php 활용
엑셀파일 10만건
10만건 등록을 진행하면 통상 10~60분 이상도 걸립니다
즉, 브라우저가 중간에 TIME_OUT 이 발생하게 됩니다
물론 상품은 서버에서 계속 등록중입니다
phpMyAdmin 에서 SHOW PROCESSLIST; 로 확인해보면 열일중이죠
상품이 등록되는 동안 서버와 소통하면서 상황이 업데이트 되면서 이용자와 소통해야하나 고민중입니다
아래는 테스트에 필요한 요소만 최대한 정리해서 올렸습니다
아래내용을 다른 엑셀 등록에 응용하시면 나름 좋은 학습자료가 될 수 있습니다
iframe 을 넣어서 거기에 서버와 소통하는 ajax 를 만들까 하는 생각도 해보고
일단 파일이 업로드 되고, 디비에 등록 시작되면 등록중, 페이지를 닫으세요 라는 내용을 띄울까도 생각해보고
여러가지 방법을 찾아보는 중입니다
이와 관련하여 참고할 정보나 아이디어가 있다면 조언 부탁드립니다
1. 디비 테이블
item 테이블 칼럼
item_idx int(11) auto_increment
item_barcode varcha(255)
item_barcode varcha(255)
item_title varcha(255)
item_quanitiy varcha(255)
item_price varcha(255)
item_history 테이블 칼럼
item_barcode varcha(255)
item_title varcha(255)
item_quanitiy varcha(255)
item_price varcha(255)
2. 엑셀파일 셀 정보 ( 엑셀 파일은 B1 에는 다른 행에 동일한 것이 n개 존재합니다 )
A1 = it_id 순서
B1 = BARCODE 제품번호
C1 = DESCRIPTION 상품명
D1 = QUANTITY 수량
E1 = price 금액
3. excel_file.php
<?php
include_once("_common.php");
$g5['title'] = '엑셀파일로 상품 대량 등록';
include_once(G5_PATH.'/head.php');
add_stylesheet('<link rel="stylesheet" href="./excel.css">', 0);
?>
<form name="fitemexcel" method="post" action="./excel_upload.php" enctype="MULTIPART/FORM-DATA" autocomplete="off">
<div id="excelfile_upload">
<label for="excelfile">파일선택</label>
<input type="file" name="excelfile" id="excelfile">
</div>
<div class="win_btn btn_confirm">
<input type="submit" value="상품 엑셀파일 등록" class="btn_submit btn">
</div>
</form>
</div>
<?php
include_once(G5_PATH.'/tail.php');
4. excel_upload.php
<?php
//ini_set('memory_limit','512M'); // 메모리 512MB 사용
ini_set('memory_limit','-1'); // 메모리 무제한 사용
include_once("_common.php");
$g5['title'] = '엑셀파일로 상품 대량 등록 결과';
include_once(G5_PATH.'/head.php');
$upload_max_filesize = ini_get('upload_max_filesize');
// 업로드 허용용량
$upload_size_MB = "20"; // MB
$upload_size_BY = "1048576"; // Byte
$upload_size = $upload_size_MB * $upload_size_BY;
//$upload_size = "20971520"; // 20MB x 1 MB x 1,048,576 bytes
$tmp_file = $_FILES['excelfile']['tmp_name'];
$filesize = $_FILES['excelfile']['size'];
$filename = $_FILES['excelfile']['name'];
$filename = get_safe_filename($filename);
//echo "filename = {$filename}<br>";
//echo "upload_max_filesize = {$upload_max_filesize}<br>";
//echo "error = {$_FILES['excelfile']['error']}<br>";
// 서버에 설정된 값보다 큰파일을 업로드 한다면
if ($filename) {
if ($_FILES['excelfile']['error'] == 1) {
$file_upload_msg .= '\"'.$filename.'\" 파일의 용량이 서버에 설정('.$upload_max_filesize.')된 값보다 크므로 업로드 할 수 없습니다.\\n';
alert($file_upload_msg);
// continue;
}
else if ($_FILES['excelfile']['error'] != 0) {
$file_upload_msg .= '\"'.$filename.'\" 파일이 정상적으로 업로드 되지 않았습니다.\\n';
alert($file_upload_msg);
// continue;
}
}
if (is_uploaded_file($tmp_file)) {
// 설정한 업로드 사이즈보다 크다면 건너뜀
if ($filesize > $upload_size) {
$file_upload_msg .= '\"'.$filename.'\" 파일의 용량('.number_format($filesize).' 바이트)이 '.number_format($upload_size).' 바이트 보다 크므로 업로드 하지 않습니다.\\n';
alert($file_upload_msg);
// continue;
}
}
add_stylesheet('<link rel="stylesheet" href="./excel.css">', 0);
include_once(G5_LIB_PATH.'/PHPExcel/IOFactory.php');
$objPHPExcel = PHPExcel_IOFactory::load($tmp_file);
$sheet = $objPHPExcel->getSheet(0); // 첫번째 시트 데이타 추출
$num_rows = $sheet->getHighestRow();
$highestColumn = $sheet->getHighestColumn();
$dup_it_id = array();
$fail_it_id = array();
$dup_count = 0;
$total_count = 0;
$fail_count = 0;
$succ_count = 0;
// 실 데이타가 2번행부터 시작되므로 $i = 2
for ($i = 2; $i <= $num_rows; $i++) {
$total_count++;
$j = 0;
$rowData = $sheet->rangeToArray('A' . $i . ':' . $highestColumn . $i,
NULL,
TRUE,
FALSE);
$it_id = addslashes($rowData[0][$j++]); // A
$BARCODE = addslashes($rowData[0][$j++]); // B
$DESCRIPTION = addslashes($rowData[0][$j++]); // C
$QUANTITY = addslashes($rowData[0][$j++]); // D
$price = addslashes($rowData[0][$j++]); // E
// 필드에 값이 있는지 확인해서 있을때만 작업시작
if ($BARCODE) {
// $BARCODE 중복체크
$sql_cnt1 = " select count(*) as cnt from `item` where item_barcode = '{$BARCODE}' ";
$sql_cnt1 .=" limit 1 ";
//echo "sql_cnt1 = {$sql_cnt1}<br>";
$row_cnt1 = sql_fetch($sql_cnt1);
// 신규 등록일때
if($row_cnt1['cnt'] == 0) {
//echo "신규 {$BARCODE} {$DESCRIPTION} <br>";
sql_query( "
insert into `item` set
item_barcode = '{$BARCODE}' ,
item_title = '{$DESCRIPTION}' ,
item_quanitiy = '{$QUANTITY}' ,
item_price = '{$price}'
");
//sql_query($sql);
//echo "sql_insert = {$sql}<br>";
sql_query( "
insert into `item_history` set
item_barcode = '{$BARCODE}' ,
item_title = '{$DESCRIPTION}' ,
item_quanitiy = '{$QUANTITY}' ,
item_price = '{$price}'
");
//sql_query($sql);
//echo "sql_history = {$sql}<br>";
$succ_count++;
} else { // 중복일때
//echo "중복 {$BARCODE} {$DESCRIPTION} <br>";
//$fail_it_id[] = $it_id;
//$dup_it_id[] = $BARCODE;
$dup_count++;
//$fail_count++;
//continue;
}
}
}
?>
<div class="new_win">
<div class="local_desc01 local_desc">
<p><?php echo $filename; ?> 상품등록을 완료했습니다.</p>
</div>
<dl id="excelfile_result">
<dt>총상품수</dt>
<dd><?php echo number_format($total_count); ?></dd>
<dt>완료건수</dt>
<dd><?php echo number_format($succ_count); ?></dd>
<?php /* ?>
<dt>실패건수</dt>
<dd><?php echo number_format($fail_count); ?></dd>
<?php if($fail_count > 0) { ?>
<dt>실패상품코드</dt>
<dd><?php //echo implode(', ', $fail_it_id); ?></dd>
<?php } ?
<?php */ ?>
<?php //if($dup_count > 0) { ?>
<dt>중복건수</dt>
<dd><?php echo number_format($dup_count); ?></dd>
<?php /* ?>
<dt>중복상품코드</dt>
<dd><?php echo implode(', ', $dup_it_id); ?></dd>
<?php */ ?>
<?php //} ?>
</dl>
</div>
<?php
include_once(G5_PATH.'/tail.php');
답변 3
10만건을 insert하는걸 대기하는게 문제겠네요
처리방식을 좀 변경해보세요
1. 업로드
2. 브라우저에는 상태는 처리중으로 회신종료
3. 업로드된 엑셀 insert로직 작동 (서버의 배치작동으로) - 작동시작시점은 서버에서 판단하도록 설정 (시간별체크라던지...)
4. 엑셀자료 insert종료시 처리중상태를 업로드완료로 상태변경
5. 업로드된 데이타 조회가능처리
로 하면되지 않을까싶네요
insert작업중에 브라우저와의 통신을 최대한 배제 하시는게 좋습니다.
가능하다면
cvs로 바꾸어서
서버에서 mysql로 작업하시는 것을 추천합니다.
웹브라우저 기본 타임아웃이 있기 때문에
시간이 오래걸리는 작업은 서버에서 별도 프로세스로 동작시키는게 낫습니다.
이런 경우 웹브라우저 기반으로 동작시키려면
시간이 오래걸리지 않도록 잘게 쪼개어 실행시키는 방식으로 변경하거나
별도 프로세스에서 동작시키고
진행률을 표시하거나 확인할수 있는 방법을 제공해주는 방법정도가 좋을것 같습니다.