현대 웹 개발에서 PHP의 세션 관리는 핵심 구성 요소로서 사용자의 상태를 유지하고 사용자 데이터가 다른 페이지 요청간에 저장되고 전달되도록 할 수 있습니다. 전통적인 세션 저장 방법은 파일 시스템을 기반으로하지만 일부 고 부하 및 고화질 애플리케이션 시나리오에서는 파일 스토리지가 성능 병목 현상을 가져올 수 있습니다. 따라서 데이터베이스를 사용하여 세션 정보를 저장하는 것은 점차 일반적인 관행이되었습니다.
PHP에서 SessionHandler 클래스는 개발자가 세션 스토리지 방법을 사용자 정의 할 수있는 메커니즘을 제공합니다. SessionHandler 인터페이스를 구현하면 세션이 데이터베이스에 저장되어 세션 관리를보다 효율적이고 안정적으로 만들 수 있습니다.
이 기사에서는 SessionHandler :: Database를 통해 세션 스토리지를 구현하는 방법에 대해 논의하고 효율적이고 안정적인 데이터베이스 세션 시스템을 구현하는 방법에 대해 논의합니다.
PHP의 내장 세션 처리 방법 (기본적으로 파일 스토리지)을 사용자 정의 세션 핸들러 로 대체 할 수 있습니다. PHP가 세션을 요청하면 SessionHandler는 다음과 같은 주요 방법을 수행합니다.
Open ($ savepath, $ sessionName) : 오픈 세션 스토리지.
닫기 () : 세션 스토리지를 닫습니다.
읽기 ($ sessionID) : 지정된 세션 ID의 세션 데이터를 읽습니다.
쓰기 ($ sessionid, $ data) : 세션 데이터를 쓰십시오.
파괴 ($ sessionID) : 세션을 파괴하십시오.
GC ($ maxlifetime) : 쓰레기 수집을 수행합니다.
이러한 방법을 다시 작성함으로써 개발자는 파일 시스템에만 의존하는 대신 세션 데이터를 데이터베이스에 저장할 수 있습니다.
다음은 PHP를 통해 데이터베이스에 세션 데이터를 저장하는 기본 단계입니다.
먼저 세션 정보를 저장하려면 데이터베이스에 테이블을 작성해야합니다. 테이블 구조의 기본 예는 다음과 같습니다.
<span><span><span class="hljs-keyword">CREATE</span></span><span> </span><span><span class="hljs-keyword">TABLE</span></span><span> `sessions` (
`session_id` </span><span><span class="hljs-type">varchar</span></span><span>(</span><span><span class="hljs-number">255</span></span><span>) </span><span><span class="hljs-keyword">NOT</span></span><span> </span><span><span class="hljs-keyword">NULL</span></span><span>,
`session_data` text </span><span><span class="hljs-keyword">NOT</span></span><span> </span><span><span class="hljs-keyword">NULL</span></span><span>,
`last_access` </span><span><span class="hljs-type">int</span></span><span>(</span><span><span class="hljs-number">11</span></span><span>) </span><span><span class="hljs-keyword">NOT</span></span><span> </span><span><span class="hljs-keyword">NULL</span></span><span>,
</span><span><span class="hljs-keyword">PRIMARY</span></span><span> KEY (`session_id`)
);
</span></span>
이 테이블에서는 세션 _id를 세션의 고유 식별자 인 Session_Data Spore Session 데이터로 사용하며 Last_Access는 세션의 마지막 액세스 시간을 기록하는 데 사용됩니다.
다음으로 세션 핸들러를 물려받는 클래스는 세션 스토리지의 기능을 구현하기 위해 개발되었습니다.
<span><span><span class="hljs-class"><span class="hljs-keyword">class</span></span></span><span> </span><span><span class="hljs-title">DbSessionHandler</span></span><span> </span><span><span class="hljs-keyword">extends</span></span><span> </span><span><span class="hljs-title">SessionHandler</span></span><span>
{
</span><span><span class="hljs-keyword">protected</span></span><span> </span><span><span class="hljs-variable">$db</span></span><span>;
</span><span><span class="hljs-keyword">public</span></span><span> </span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">__construct</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-variable">$db</span></span></span><span>)
{
</span><span><span class="hljs-variable language_">$this</span></span><span>->db = </span><span><span class="hljs-variable">$db</span></span><span>;
}
</span><span><span class="hljs-keyword">public</span></span><span> </span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">open</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-variable">$savePath</span></span></span><span>, </span><span><span class="hljs-variable">$sessionName</span></span><span>)
{
</span><span><span class="hljs-comment">// 여기에서 데이터베이스 연결의 초기화 작업을 수행하도록 선택할 수 있습니다.</span></span><span>
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-literal">true</span></span><span>;
}
</span><span><span class="hljs-keyword">public</span></span><span> </span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">close</span></span><span>(</span><span><span class="hljs-params"></span></span><span>)
{
</span><span><span class="hljs-comment">// 여기에서 데이터베이스 연결을 닫을 수 있습니다</span></span><span>
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-literal">true</span></span><span>;
}
</span><span><span class="hljs-keyword">public</span></span><span> </span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">read</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-variable">$sessionId</span></span></span><span>)
{
</span><span><span class="hljs-comment">// 데이터베이스에서 세션 데이터를 읽습니다</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span> = </span><span><span class="hljs-variable language_">$this</span></span><span>->db-></span><span><span class="hljs-title function_ invoke__">prepare</span></span><span>(</span><span><span class="hljs-string">"SELECT session_data FROM sessions WHERE session_id = :session_id"</span></span><span>);
</span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">execute</span></span><span>([</span><span><span class="hljs-string">'session_id'</span></span><span> => </span><span><span class="hljs-variable">$sessionId</span></span><span>]);
</span><span><span class="hljs-variable">$row</span></span><span> = </span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">fetch</span></span><span>(PDO::</span><span><span class="hljs-variable constant_">FETCH_ASSOC</span></span><span>);
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-variable">$row</span></span><span> ? </span><span><span class="hljs-variable">$row</span></span><span>[</span><span><span class="hljs-string">'session_data'</span></span><span>] : </span><span><span class="hljs-string">''</span></span><span>;
}
</span><span><span class="hljs-keyword">public</span></span><span> </span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">write</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-variable">$sessionId</span></span></span><span>, </span><span><span class="hljs-variable">$data</span></span><span>)
{
</span><span><span class="hljs-comment">// 세션 데이터 업데이트</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span> = </span><span><span class="hljs-variable language_">$this</span></span><span>->db-></span><span><span class="hljs-title function_ invoke__">prepare</span></span><span>(</span><span><span class="hljs-string">"REPLACE INTO sessions (session_id, session_data, last_access) VALUES (:session_id, :session_data, :last_access)"</span></span><span>);
</span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">execute</span></span><span>([
</span><span><span class="hljs-string">'session_id'</span></span><span> => </span><span><span class="hljs-variable">$sessionId</span></span><span>,
</span><span><span class="hljs-string">'session_data'</span></span><span> => </span><span><span class="hljs-variable">$data</span></span><span>,
</span><span><span class="hljs-string">'last_access'</span></span><span> => </span><span><span class="hljs-title function_ invoke__">time</span></span><span>()
]);
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-literal">true</span></span><span>;
}
</span><span><span class="hljs-keyword">public</span></span><span> </span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">destroy</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-variable">$sessionId</span></span></span><span>)
{
</span><span><span class="hljs-comment">// 세션 데이터를 삭제합니다</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span> = </span><span><span class="hljs-variable language_">$this</span></span><span>->db-></span><span><span class="hljs-title function_ invoke__">prepare</span></span><span>(</span><span><span class="hljs-string">"DELETE FROM sessions WHERE session_id = :session_id"</span></span><span>);
</span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">execute</span></span><span>([</span><span><span class="hljs-string">'session_id'</span></span><span> => </span><span><span class="hljs-variable">$sessionId</span></span><span>]);
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-literal">true</span></span><span>;
}
</span><span><span class="hljs-keyword">public</span></span><span> </span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">gc</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-variable">$maxlifetime</span></span></span><span>)
{
</span><span><span class="hljs-comment">// 만료 된 세션을 정리하십시오</span></span><span>
</span><span><span class="hljs-variable">$stmt</span></span><span> = </span><span><span class="hljs-variable language_">$this</span></span><span>->db-></span><span><span class="hljs-title function_ invoke__">prepare</span></span><span>(</span><span><span class="hljs-string">"DELETE FROM sessions WHERE last_access < :expire_time"</span></span><span>);
</span><span><span class="hljs-variable">$stmt</span></span><span>-></span><span><span class="hljs-title function_ invoke__">execute</span></span><span>([</span><span><span class="hljs-string">'expire_time'</span></span><span> => </span><span><span class="hljs-title function_ invoke__">time</span></span><span>() - </span><span><span class="hljs-variable">$maxlifetime</span></span><span>]);
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-literal">true</span></span><span>;
}
}
</span></span>
이 구현에서는 PDO를 통해 데이터베이스와 상호 작용하며 특정 작업은 다음과 같습니다.
열기 메소드 : 데이터베이스 연결 초기화. 일반적으로 데이터베이스 연결 이이 메소드에서 설정됩니다.
방법 읽기 : 세션 ID를 통해 데이터베이스에서 해당 세션 데이터를 쿼리하십시오.
쓰기 방법 : 세션 데이터를 데이터베이스에 쓰십시오. 세션 ID가 존재하지 않으면 새 레코드를 삽입하고 기존 레코드를 업데이트하십시오.
방법 파괴 방법 : 지정된 세션 ID로 데이터를 삭제합니다.
GC 방법 : 쓰레기 수집 작업을 수행하고 만료 된 세션 레코드를 삭제하십시오.
SessionHandler 의 구현을 완료 한 후에는 PHP에 사용자 정의 세션 스토리지 프로세서를 등록해야합니다. Session_SET_SAVE_HANDLER 함수를 통해 사용자 정의 세션 처리 방법을 설정하십시오.
<span><span><span class="hljs-comment">// 데이터베이스 연결을 만듭니다</span></span><span>
</span><span><span class="hljs-variable">$db</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title function_ invoke__">PDO</span></span><span>(</span><span><span class="hljs-string">'mysql:host=localhost;dbname=test'</span></span><span>, </span><span><span class="hljs-string">'username'</span></span><span>, </span><span><span class="hljs-string">'password'</span></span><span>);
</span><span><span class="hljs-comment">// 사용자 정의 세션 프로세서를 인스턴스화하십시오</span></span><span>
</span><span><span class="hljs-variable">$sessionHandler</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">DbSessionHandler</span></span><span>(</span><span><span class="hljs-variable">$db</span></span><span>);
</span><span><span class="hljs-comment">// 사용자 정의 세션 프로세서를 등록하십시오</span></span><span>
</span><span><span class="hljs-title function_ invoke__">session_set_save_handler</span></span><span>(
[</span><span><span class="hljs-variable">$sessionHandler</span></span><span>, </span><span><span class="hljs-string">'open'</span></span><span>],
[</span><span><span class="hljs-variable">$sessionHandler</span></span><span>, </span><span><span class="hljs-string">'close'</span></span><span>],
[</span><span><span class="hljs-variable">$sessionHandler</span></span><span>, </span><span><span class="hljs-string">'read'</span></span><span>],
[</span><span><span class="hljs-variable">$sessionHandler</span></span><span>, </span><span><span class="hljs-string">'write'</span></span><span>],
[</span><span><span class="hljs-variable">$sessionHandler</span></span><span>, </span><span><span class="hljs-string">'destroy'</span></span><span>],
[</span><span><span class="hljs-variable">$sessionHandler</span></span><span>, </span><span><span class="hljs-string">'gc'</span></span><span>]
);
</span><span><span class="hljs-comment">// 세션을 시작하십시오</span></span><span>
</span><span><span class="hljs-title function_ invoke__">session_start</span></span><span>();
</span></span>
Session_SET_SAVE_HANDLER는 PHP의 세션 처리 방법을 사용자 정의 DBSESSIONHANDLER 클래스로 대체하여 세션 데이터가 데이터베이스에 저장되도록합니다.
효율적이고 안정적인 데이터베이스 세션 스토리지를 달성하려면 다음 측면에 특별한주의를 기울여야합니다.
세션 테이블에서 Session_ID 필드는 일반적으로 기본 키로 사용되므로 독창성과 효율적인 쿼리 성능을 보장합니다. 또한, 마지막 _access 필드를 색인화하여 쓰레기 수집 중에 만료 된 세션을 효율적으로 검색 할 수 있습니다.
세션 만료 전략은 효율적인 데이터베이스 세션을 보장하는 핵심입니다. 세션의 최대 수명 시간을 합리적으로 설정하고 GC 방법에서 만료 된 세션을 삭제하면 데이터베이스에서 너무 많은 정크 데이터를 방지 할 수 있습니다.
세션 데이터가 공유되므로 여러 요청이 동시에 동일한 세션에 액세스하고 수정할 수 있습니다. 데이터 충돌 및 불일치를 피하기 위해 세션 데이터 수정 중에 다른 요청이 동시에 수정되지 않도록 세션 잠금 전략을 채택 할 수 있습니다.
동시성 응용 프로그램이 높은 경우 매번 데이터베이스 연결을 생성하면 성능에 영향을 줄 수 있습니다. 데이터베이스 연결 풀링 기술을 사용하거나 데이터베이스 연결을 지속시켜 성능 향상을 고려하십시오.
데이터베이스의 압력을 줄이려면 세션 데이터를 메모리로 캐싱하여 Redis, Memcached 등과 같은 캐싱 기술을 결합하여 데이터베이스의 부담을 줄이고 세션 스토리지의 응답 속도 및 안정성을 향상시킬 수 있습니다.
세션 핸들러 인터페이스를 구현하고 데이터베이스에 세션 데이터를 저장하면 세션 관리의 유연성과 안정성을 효과적으로 개선 할 수 있습니다. 세션 스토리지의 구현 방법을 합리적으로 설계하고 적절한 최적화 측정을 수행함으로써 효율적이고 안정적이며 확장 가능한 데이터베이스 세션 스토리지 시스템을 달성 할 수 있습니다.