CI 묻고 답하기

제목 db reconnect 사용 위치와 에러에 대한 문의 드립니다.
카테고리 CI 2, 3
글쓴이 잔디 작성시각 2016/12/08 14:47:05
댓글 : 6 추천 : 0 스크랩 : 0 조회수 : 21442   RSS

안녕하세요.

평소 CI에 대한 궁금증이 있을때마다 먼저 찾게 되어, 그동안 다른분들의 질문과 답변을 통해 해결을 하고는 했었는데 이번에는 찾기가 어려워 문의 드립니다. ^^;

CI로 사이트를 만들어서 잘 사용을 하고 있고, 개발(?)을 하고 있는데, 타 서버와 curl로 xml통신을 하게 되면서 문제가 발생했습니다.

타 서버와 통신을 하면서 소요시간이 짧을 경우 문제가 없었는데, 1분 30총 ~ 2분정도의 시간이 걸리는 경우가 있을 경우 DB 연결이 끊어져 이후 에러가 발생을 하고 있습니다.

// config/database 셋팅
$db['default'] = array(
	'dsn' => '',
	'hostname' => 'hostname',
	'username' => 'username',
	'password' => 'password',
	'database' => 'database',
	'dbdriver' => 'mysqli',
	'dbprefix' => '',
	'pconnect' => false,
	'db_debug' => (ENVIRONMENT !== 'production'),
	'cache_on' => false,
	'cachedir' => '',
	'char_set' => 'utf8',
	'dbcollat' => 'utf8_general_ci',
	'swap_pre' => '',
	'encrypt' => false,
	'compress' => false,
	'stricton' => false,
	'failover' => array(),
	'save_queries' => true 
);

DB는 위와 같이 세팅이 되어 있고, autoload에 추가하여 전반적으로 사용을 하고 있습니다.

 

// Controller 부분
class A extends CI_Controller {

	function __construct() {
		parent::__construct();
	}

	function aa() {
		// 전체 스크립트 처리에 2분정도 소요되기 때문에 timeout값 무제한으로 지정
		set_time_limit(0);
		
		$this->load->model('b_model');

		$result = $this->b_model->bb();

		// view 사용 부분
		print_r($result);
	}
}

// Model B 부분
class B_model extends CI_Model {

	function __construct() {
		parent::__construct();
	}

	function bb() {
		$this->load->model('c_model');
		$this->load->model('e_model');

		$result = $this->c_model->cc();

		// $result 데이터 파싱 후 결과 데이터를 DB에 저장
		$this->e_model->insert_ee();

		// 파싱 후 결과 데이터를 전달
		return $result;
	}
}

// Model C 부분
class C_model extends CI_Model {

	function __construct() {
		parent::__construct();
	}

	function cc() {
		$this->load->model('d_model');

		// 타 서버와 curl을 이용한 xml 통신 부분, 결과로 $result 생성
		// 타 서버와 통신시 약 2분정도 소요되어 sleep(120)으로 대체
		$result = array();
		sleep(120);

		// 타 서버와 통신시 시간이 많이 소요되어 DB 재연결
		$this->db->reconnect();

		// xml 통신에 대한 로그 기록 저장
		$this->d_model->insert_dd(); 

		// 통신 결과를 전달
		return $result;
	}
}

// Model D 부분
class D_model extends CI_Model {

	function __construct() {
		parent::__construct();
	}

	function insert_dd() {
		// DB에 curl 통신에 대한 로그 기록 저장
		$this->db->insert();
	}
}

// Model E 부분
class E_model extends CI_Model {

	function __construct() {
		parent::__construct();
	}

	function insert_ee() {
		// DB에 curl 통신 결과에 대한 데이터값 저장
		$this->db->insert();
	}
}

 

문제가 발생하는 부분에 대한 간략적인 구조입니다.

에러가 발생하는 부분은 타 서버와 통신을 하고 DB 재연결을 하는 reconnect부분입니다.

 

Severity: Warning

Message: mysqli::ping(): MySQL server has gone away

Filename: mysqli/mysqli_driver.php

Line Number: 206

 

Severity: Error

Message: Call to a member function real_escape_string() on a non-object

Filename: mysqli/mysqli_driver.php

Line Number: 355

 

이 두가지 에러가 같이 발생을 합니다.

reconnect의 위치가 잘못되어 있는건지, 아니면 다른 설정을 더 해줘야 하는건지 문의 드립니다.

통신시간이 짧을 경우에는 에러 메세지가 나타나지 않습니다.

 

바쁘시더라도 회원님들의 조언 부탁드립니다. ^^

태그 reconnect,db
 다음글 image_lib를 이용한 이미지 리사이징 질문드립니다... (2)
 이전글 서브도메인 라우터 질문드립니다. (1)

댓글

변종원(웅파) / 2016/12/09 13:24:38 / 추천 0

mysql 서버 타임아웃 관련 설정이 어떻게 되어 있나 확인해보세요.

http://kjk3071.tistory.com/entry/DB-MySQL-timeout-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0

변종원(웅파) / 2016/12/09 13:25:53 / 추천 0
그리고 curl 연결 이후에 db 연결해서 사용하시면 될것 같은데요?
잔디 / 2016/12/09 15:58:15 / 추천 0

답글 감사합니다. ^^

알려주신 url의 글을 토대로 mysql 서버의 타임아웃 설정을 보았는데, 관련된 설정값이라 생각되는 interactive_timeout와 wait_timeout 모두 28800으로 설정되어 있습니다. 그리고, 가비아 웹호스팅을 사용하고 있는 상황이라 설정파일의 값을 바꾸기에는 무리가 있을거 같습니다.

curl 연결 이후에 db연결을 하는건 curl 이전 부분에서도 db 연결해서 사용하는 부분이 있습니다.

자체적으로 이것저것 DB연결에 관련된 $this->load->database(), $this->db->initialize(), $this->db->reconnect, $this->db->close를 조합해서 테스트를 해보았는데, curl 이후 $this->db_close(); $this->db->initialize(); 를 사용해서 어느정도 해결이 된거 같습니다.

다만, 가끔씩 DB를 사용하는 세션이 끊겨서 로그인 페이지로 이동하게 되는 경우가 생깁니다. 가끔씩이라 딱히 관련이 있어보이진 않지만 의심쩍긴 합니다... ^^;;

추가적으로 테스트하다가 궁금한 사항이 있습니다.

// Controller 부분
public function dbtest() {
		set_time_limit(0);
		sleep(60);
		
		$this->db->close();
		$this->db->reconnect();
		
		/*
		$query = 'SELECT count(*) AS log_count' . PHP_EOL;
		$query .= 'FROM test_log' . PHP_EOL;
		$query = $this->db->query($query);
		$test_log = $query->row_array();
		echo ('log count, ' . $test_log['log_count'] . '<br>');
		*/
		
		$this->db->set('log_data', 'TEST LOG #1');
		$this->db->set('modify_date', date('Y/m/d H:i:s'));
		$this->db->insert('test_log');
		$test_log_idx = $this->db->insert_id();
		
		$query = 'SELECT *' . PHP_EOL;
		$query .= 'FROM test_log' . PHP_EOL;
		$query .= 'WHERE test_log.test_log_idx = ' . $this->db->escape($test_log_idx) . PHP_EOL;
		$query = $this->db->query($query);
		$test_log = $query->row_array();
		echo ($test_log['log_data'] . ', ' . $test_log['modify_date'] . '<br>');
	}

 

위 처럼 실행을 하면 Fatal error: Call to a member function real_escape_string() on a non-object 에러가 발생을 하고 주석 처리한 부분의 주석을 제거해 select 구문을 추가해주면 정상적으로 동작합니다.

kaido / 2016/12/09 16:31:22 / 추천 0

제 기억이 맞다면 real_escape_string()  이 문제는 php 버전이 낮아서 나오는 문제입니다.

변종원(웅파) / 2016/12/09 16:47:50 / 추천 0
아마도 php5.3이하이면 에러가 날겁니다.
잔디 / 2016/12/09 16:59:59 / 추천 0

아. php 버전의 문제이군요.

5.4.5버전을 사용중인데, 이것도 문제가 있나보네요.

답글 감사합니다~!! ^^