2012-03-26 39 views
5

Tôi đang viết một ứng dụng Android giao tiếp với chương trình phụ trợ PHP. Các db phụ trợ là SQLite 3. Vấn đề là, tôi nhận được lỗi này liên tục PHP Warning: SQLite3::prepare(): Unable to prepare statement: 5, database is locked. Tôi đang mở một kết nối đến cơ sở dữ liệu trong mỗi tập tin PHP và đóng nó khi kịch bản kết thúc. Tôi nghĩ rằng vấn đề là một kịch bản đã khóa tập tin cơ sở dữ liệu trong khi viết cho nó và kịch bản thứ hai đã cố gắng truy cập nó, mà không thành công. Một cách để tránh điều này là chia sẻ kết nối giữa tất cả các tập lệnh php. Tôi đã tự hỏi nếu có cách nào khác để tránh điều này?Cơ sở dữ liệu bị khóa khi cố gắng truy cập từ tập lệnh PHP

Edit: Đây là tập đầu tiên:

<?php 
$first = SQLite3::escapeString($_GET['first']); 
$last = SQLite3::escapeString($_GET['last']); 
$user = SQLite3::escapeString($_GET['user']); 
$db = new SQLite3("database.db"); 
$insert = $db->prepare('INSERT INTO users VALUES(NULL,:user,:first,:last, 0 ,datetime())'); 
$insert->bindParam(':user', $user, SQLITE3_TEXT); 
$insert->bindParam(':first', $first, SQLITE3_TEXT); 
$insert->bindParam(':last', $last, SQLITE3_TEXT); 
$insert->execute(); 
?> 

Đây là tập tin thứ hai:

<?php 
$user = SQLite3::escapeString($_GET['user']); 
$db = new SQLite3("database.db"); 
$checkquery = $db->prepare('SELECT allowed FROM users WHERE username=:user'); 
$checkquery->bindParam(':user', $user, SQLITE3_TEXT); 
$results = $checkquery->execute(); 
$row = $results->fetchArray(SQLITE3_ASSOC); 
print(json_encode($row['allowed'])); 
?> 
+0

Lần đầu tiên chia sẻ Mã số –

+0

Đã thêm mã và mô tả khác –

Trả lời

13

Đầu tiên, khi bạn đang thực hiện với một tài nguyên mà bạn nên luôn luôn đóng nó lại. Về lý thuyết nó sẽ được đóng lại khi nó được thu gom rác, nhưng bạn không thể phụ thuộc vào PHP làm điều đó ngay lập tức. Tôi đã nhìn thấy một vài cơ sở dữ liệu (và các loại thư viện khác cho vấn đề đó) bị khóa vì tôi không tiết lộ tài nguyên một cách rõ ràng.

$db->close(); 
unset($db); 

Thứ hai, Sqlite3 cho bạn thời gian chờ bận. Tôi không chắc chắn về mặc định là gì, nhưng nếu bạn sẵn sàng đợi vài giây để khóa xóa khi bạn thực hiện truy vấn, bạn có thể nói như vậy. Thời gian chờ tính bằng mili giây.

$db->busyTimeout(5000); 
+0

Tôi thực sự quên đóng kết nối. Đã thêm và 'busyTimeout'. Nó hoạt động tốt ngay bây giờ. Cảm ơn! –

+3

Mặc dù vậy, bạn có thể gặp sự cố. Nếu bạn truy cập cùng một DB từ một tập lệnh trong khi vẫn mở từ một tập lệnh khác (Ví dụ: Ajax) thì bạn sẽ có cùng một vấn đề – Alex

+0

Giá trị mặc định là 60 giây == 60000 mili giây. Làm thế nào 5000 sẽ làm một điều hữu ích? – TechJS

1

tôi đã nhận được "cơ sở dữ liệu khóa" tất cả các thời gian cho đến khi tôi phát hiện ra một số tính năng của sqlite3 phải được thiết lập bằng cách sử dụng SQL hướng dẫn đặc biệt (ví dụ: sử dụng từ khóa PRAGMA). Ví dụ, những gì rõ ràng giải quyết vấn đề của tôi với "cơ sở dữ liệu bị khóa" đã được thiết lập journal_mode để 'wal' (nó là mặc định để 'xóa', như đã nêu ở đây: https://www.sqlite.org/wal.html (xem kích hoạt và cấu hình chế độ WAL)).

Vì vậy, về cơ bản những gì tôi phải làm là tạo kết nối tới cơ sở dữ liệu và thiết lập journal_mode bằng câu lệnh SQL. Ví dụ:

<?php 
    $db = new SQLite3('/my/sqlite/file.sqlite3'); 
    $db->busyTimeout(5000); 
    // WAL mode has better control over concurrency. 
    // Source: https://www.sqlite.org/wal.html 
    $db->exec('PRAGMA journal_mode = wal;'); 
?> 

Hy vọng điều đó sẽ hữu ích.

Các vấn đề liên quan