CI 묻고 답하기

제목 메모리부족으로 인한 에러 발생 문제 ini_set() 함수 위치가?
카테고리 CI 2, 3
글쓴이 정수리 작성시각 2016/10/04 09:25:55
댓글 : 11 추천 : 0 스크랩 : 0 조회수 : 19848   RSS

몇일 특정 페이지에서 데이터 등록 시 오랜 로딩 후에 

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 80 bytes) in /home2/users/intra/public_html/jds/application/controllers/program_c.php on line 261 

이런 에러가 출력되어 글을 올렸습니다.

한대승님께서 올려주신 답변을 통해 구글에 메모리부족으로 인한 해결 방법이 

주르륵 나오더라구요

1,php.ini파일수정

2,ini_set함수 사용

위의 두 해결 방법 중 php.ini의 경우 제가 php.ini을 수정할 권한이 없기에 사용할수 없는

방법이기에 2번째 ini_set 함수를 사용하였습니다.

이 함수를 코드에 입력한 후 등록을 하니 그전보다 로딩이 훨씬 길어지네요;;

너무 길다보니 어떤 에러가 출력되는지도 모르겠으며 언제 이 로딩이 끝날지도 모르겠네요;;

 

제가 일단 ini_set 함수 적용한 위치는 

 

컨트롤러의 생성자 부분에 위치를 시킨후 실행하였을 때 너무 로딩이 길어 일단 정지 후 주석으로 제외시킨후 

if(!defined('BASEPATH')) exit('No direct script access allowed');

class Program_c extends CI_Controller{

	public function __construct(){
		
		parent::__construct();
		ini_set("memory_limit", -1);
		$this->load->model('Program_m');

		
		
	}

 

폼을 통해 post 데이터를 받는 컨트롤러 함수 부분에 적용시켜보았습니다.

function pg_dm_modify(){
			$this->output->enable_profiler(TRUE);
			ini_set("memory_limit", -1);
			$data = array();
			foreach($this->input->post(null, true) as $key => $val) $data["{$key}"]= $val;
			
			$result = $this->pg_dm_modify($data);

				if($result){
					
					echo "
					<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
					<script>alert('수정되었습니다');
					window.opener.parent.location.reload();
						window.close();
					</script>";
		
				}
			
	}

 

그리고 다시 실행을 하여도 로딩이 엄청 길어지네요;;

 

제가 ini_set 위치를 잘못 잡은 것일까요?

 다음글 CI 4 모델 로드하기 (2)
 이전글 안녕하세요 csrf에관하여 몇 가지 질문드립니다.. (1)

댓글

kaido / 2016/10/04 09:46:49 / 추천 0

둘중 하나입니다.

database 내용이 너무 많다던가, 혹은 그걸 불러오는 쿼리가 무겁게 짜여져 있다던가.

 

db 자체가 무거우면 방법은 db 업그레이드 하던가, 그냥 느린채로 쓰던가 입니다. 그리고 많은 데이터를 받을 수 있게 메모리 업그레이드도 필요 할테구요. 하드웨어적인 문제가 맞다면 어필 하세요. 

 

서버의 가용 가능한 메모리도 확인해 보세요.

이전에 듣기에는 테스트용 서버를 분활해서 사용한다고 본것 같습니다만, 리미트를 오버하면 느려질 수밖에 없습니다.

아무리 설정을 높게 잡아도 물리 메모리 영역이 부족하면 어디서 공짜로 메모리가 생겨나진 않거든요.

정수리 / 2016/10/04 10:04:59 / 추천 0

@kiado

처음에 설계할때는 서버를 분할할려고 하였는데 그냥 기존 인트라넷과 동일한 서버에서 작업하기로 하였습니다.

기존인트라넷의 경우 새프로젝트보다 더 많은 내용을 가지고 있는데도 문제가 없어 보이는데 제것만 그러네요 ㅜㅜ

제가 위에서 말한 특정페이지의 경우 데이터를 수정하는 부분입니다.

데이터를 수정할 때 기존의데이터를 가지고 올때는 잘가져옵니다. 그리고 데이터를 수정한 후 수정버튼을 누르면

그때로딩이 걸립니다. 

그렇다면 일단 db와 query 문제는 아니지 않나요??

수정버튼을 눌렀을 때 데이터를 가지고 온후에 db에 연결하고 데이터를 등록하는 query문을 실행하는 순서 아닌가요??;

제가 잘못 이해하고 있는 것일까요;;

kaido / 2016/10/04 10:15:04 / 추천 0

비슷한 질문으로 제가 답을 해드렸던 기억이 납니다.

 

어떤 문제가 발생하면 모든 부분을 테스트해서 어떤 부분이 느린지 판단 해야 한다.

 

지금 당장 나오는 에러 문구만 보면 db 작업에서 메모리 오버가 나오고 있습니다.

그렇기에 db 관련을 집어보라는 추측을 해드릴 수밖에 없고요.

 

불러오기만이 db 작업이 아니죠. 수정 이라고 하였으니 수정 부분도 db 작업니다.

리스트 단위로 받아와서 리스트 단위로 반복해서 수정을 한다면 메모리가 오버될수 있습니다.

php는 하나의 페이지가 종료될 때까지 모든 작업에 메모리가 소모가 됩니다.

 

CI가 기본 사용하는 메모리 사용량이 네이티브 보단 높은 편인건 맞습니다만, CI 때문에 메모리 사용이 엉망이라는 것은 핑계 입니다.

이런 로직적인 문제가 아닌 부분을 넘었다면, 그 다음 부터는 개발자 본인이 판단해서 어떻게 해결 할지 고민 해야합니다.

 

이문제 대해서 사실상 포럼에서 도움을 드릴 수 있는 부분은 이미 다 해드린것 같아요.

 

참고로 그 실제 사용서버 스펙을 좀 알려달라고 해서 비교 해보세요.

보아하니 많은 데이터를 사용하는 사이트인것 같은데... 실용 서버 스펙이 월등 할 거라 추측됩니다.

가령 128M 이 한계인 테스트서버에 100M씩 데이터 받아오는거랑 16G 씩 사용하는 실섭에 300M씩 데이터 주는 거랑 같을까요?

정수리 / 2016/10/04 11:05:40 / 추천 0

@kaido

그렇군요,, 답변감사합니다.

일단 어디 부분이 느린지 확인할려면 

applicatio의 log부분과 프로파일을 사용하여 느린 부분을 체크해야 될까요?

어디부분부터 확인하여 느린부분을 찾아내야 할지 조언좀 해주실수 있을까요?

이범준 / 2016/10/04 11:08:13 / 추천 0

제 예상으로는 대량의 데이터를 처리하시고 있으시고 insert/update에 부하가 있으신 것 같습니다.

먼저 application/config/database.php 에서 save_queries를 FALSE로 바꾸시기 바랍니다.

 

하나의 클라이언트가 128M를 다 사용할 정도의 작업이 있다는 거 자체가, 그게 유지 된다는 것 자체가 조금 무리수입니다.

로직에서 메모리에 담아둔 대량의 데이터들은 사용 후 즉시 unset을 시키시기 바랍니다.

 

분명 128M의 자원을 사용하는 로직이 있기에 에러가 발생하는 겁니다.

코드를 하나씩 디버깅 하시면서 찾아보시기 바랍니다.

당연히 해당 로직은 메모리 누수를 유발하는 잘못된 코드이지요.

 

위의 로직에서 반복문의 맨 마지막에 clearstatcache(); 메소드를 넣으시기 바랍니다.

로직과 쿼리들을 다시 한 번 살펴보시고, 쓸데없이 자원 잡아먹는 코드는 최대한 최적화를 시키시기 바랍니다.

 

지금 수정하신 int_set limit_memory는 보통 .htaccess에 넣습니다만 서버에서 제한 걸어 놓으면 아무 의미 없습니다.

그렇기에 이 부분에 대해서 수정하신 건 모두 원상복구 하시기 바랍니다.

정수리 / 2016/10/04 11:23:54 / 추천 0

@이범준

답변 감사합니다.

아직 실력이 부족해서 이해가 되지 않는 부분이 있는데

메모리에 담아둔 대량의 데이터들은 사용 후 즉시 unset을 시키시지 바랍니다.

라느 부분에서 unset을 시키기 위해서는 따로 변수를 초기화해야 하거나 다른 방법이 있는 것인가요?

php를 공부하면서 따로 데이터를 사용한 후 unset을 시키는 작업을 해본적이 없고 듣어본적이없어서;;

이범준 / 2016/10/04 11:25:20 / 추천 0

@정수리

 

unset(); 메소드의 첫 번째 파라미터에 변수를($test) 넣으시면 해당 변수는 메모리에서 사라집니다.

정수리 / 2016/10/04 12:32:06 / 추천 0

@이범준

unset메서드가 따로있었군요.

그렇다면의 반복문에 들어가있는 데이터모두 unset해줘야 되겠군요?

그리고 이상한점을 발견했는데

function pg_dm_modify(){
			$this->output->enable_profiler(TRUE);
			$data = array();
			echo '1: '.memory_get_usage();
			echo '2:'.memory_get_peak_usage();
			foreach($this->input->post(null, true) as $key => $val) $data["{$key}"]= $val;
			
			
			$result = $this->pg_dm_modify($data);
/*
				if($result){
					
					echo "
					<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
					<script>alert('수정되었습니다');
					window.opener.parent.location.reload();
						window.close();
					</script>";
		
				}
	*/			
				clearstatcache();
			
	}

if문만 주석처리후 수정버튼을 누르니 echo문으로 메모리사용량이 화면에 출력이 되는데

이게  계속해서 늘어나네요;;

그렇다보니 model쪽으로 데이터를 보낼때 문제가 되는것 같기도 하네요;

도라에몽 / 2016/10/04 13:12:36 / 추천 0

아파치 사용하시면 아파치 자체 버그 일수도 있습니다. 

http://cikorea.net/bbs/view/tip?idx=14234 이거 참고하셔서 일단 응급 조치라도 취해보심이 좋을듯 합니다. ^^

정수리 / 2016/10/04 13:27:52 / 추천 0

@도라에몽

답변감사합니다

제가 아파치와 서버 자체를 수정할수 있는 권한도 없고;;

기존의 운영중인 사이트들은 정상적으로 운영되고 있어서요 ㅜㅜ

정수리 / 2016/10/04 15:03:57 / 추천 0

해결 하였습니다 ㅜㅜ

컨트롤러에서 중간의 모델명을 실수로 빼버렸더니 컨트롤러함수가 자기 자신을 계속 부르고 있었네요;;

죄송합니다,