2011-10-13 32 views
6

Tôi đã viết một daemon python liên tục thăm dò cơ sở dữ liệu mysql. Nó hoạt động tốt khi tôi liên tục kết nối và kết nối lại với cơ sở dữ liệu giữa các truy vấn như sau:Python MySQLdb truy vấn chọn trống mặc dù truy vấn thủ công thực thi cung cấp kết quả

def connect(self): 
    self.connection = MySQLdb.connect(...) 
    self.cursor = self.connection.cursor() 
    return self.cursor 

def disconnect(self): ... 
    self.cursor.close() 
    self.connection.close() 

def getData(); .... 
    sqlcmd = """SELECT ....""" 
    self.cursor.execute (sqlcmd % (params)) 
    result = self.cursor.fetchall() 
    return result 

if __name__ == "__main__": 
    db = prepaid_db.Database() 
    while 1: 
     dbConnection = db.connect() 
     data = db.getData() 
     ... do stuff 
     db.disconnect 

Nhưng khi tôi cố gắng giữ cho các kết nối cơ sở dữ liệu mở (như dưới đây) tôi nhận được một truy vấn rỗng, mặc dù, trong khi nó là chạy tôi có thể truy vấn db theo cách thủ công, cung cấp cho nó cùng một truy vấn và nhận được kết quả tôi mong đợi.

if __name__ == "__main__": 
    db = prepaid_db.Database() 
    dbConnection = db.connect() 
    while 1: 
     data = db.getData() 
     ... do stuff 
    db.disconnect 

Tôi đã thử tất cả mọi thứ để hiểu tại sao nó sẽ làm điều này:

  • bộ nhớ cache

    khuyết tật truy vấn và thêm ngẫu nhiên x = x với truy vấn trong bộ nhớ cache trường hợp mysql bị nhầm lẫn bởi các truy vấn tương tự
  • cho phép truy vấn đăng nhập mysql: truy vấn đi qua nhưng vẫn trả lại tập hợp trống
  • di chuyển cursor.connect đến database.connect và quay lại getData(), không có sự khác biệt

Tôi rất thích đầu mối về những gì tôi không hiểu.

+0

Dấu chấm phẩy trong 'def getData();' phải là dấu hai chấm. – unutbu

+0

Liệu 'self.cursor.fetchall()' trả về 'None' lần đầu tiên thông qua' while-loop', hay sau nhiều lần vượt qua? – unutbu

+0

- có trên dấu hai chấm, xin lỗi, typo đơn giản –

Trả lời

6

Có lẽ bạn đang truy vấn một bảng InnoDB trong đó một quy trình khác chèn dữ liệu mới trong thời gian chờ đợi. Nếu đúng như vậy, máy chủ MySQL sẽ tự động bắt đầu một giao dịch mới cho kết nối của bạn và vì bạn không gọi dbConnection.commit() hoặc .rollback() ở bất cứ đâu, bạn sẽ bị kẹt vĩnh viễn trong giao dịch đó. Cài đặt mặc định của InnoDB đảm bảo rằng bất cứ khi nào bạn truy vấn dữ liệu, bạn sẽ luôn thấy kết quả tương tự trong một giao dịch. Vì vậy, bất cứ điều gì một số quá trình khác được chèn vào bảng được ẩn từ kết nối daemon của bạn.

Giải pháp rất đơn giản: Thay vì gọi db.disconnect(), hãy gọi dbConnection.commit(), kết thúc hiện tại và bắt đầu giao dịch mới.

+3

thiên tài ra khỏi đó! –

+0

cảm ơn Simon, đó là bảng InnoDB duy nhất trong DB của tôi và tôi không nghĩ rằng nó sẽ có tác động trên một câu lệnh Select. Nhưng rõ ràng là vậy, tôi đã thêm commit() và bây giờ nó hoạt động hoàn hảo! cảm ơn bạn rât nhiêu! –

+0

maaaaaaaan! điều đó thật tuyệt vời, tôi nghĩ db.commit() chỉ dành cho việc cập nhật nội dung. Điều đó đã cứu cuộc đời tôi. – AliBZ

2

Đối tượng MySQLdb.cursor có thể không hỗ trợ cam kết như được đưa ra trong MySQLDB manual. Các đối tượng kết nối, mặt khác, làm.

Vì bạn xử lý mọi thứ thông qua lớp Cơ sở dữ liệu, tôi đoán mã cam kết có thể đến đó.

Chỉ cần để cung cấp cho một mã cho những gì Simon đã nói

def connect(self): 
     self.connection = MySQLdb.connect(...) 
     self.cursor = self.connection.cursor() 

    def disconnect(self): ... 
     self.cursor.close() 
     self.connection.commit() 
     self.connection.close() 

    def commit(self): 
     self.connection.commit() 

    def getData(self): .... 
     sqlcmd = """SELECT ....""" 
     self.cursor.execute (sqlcmd % (params)) 
     result = self.cursor.fetchall() 
     return result 

if __name__ == "__main__": 
    db = prepaid_db.Database() 
    db.connect() 
    while 1: 
     data = db.getData() 
     ... do stuff 
     db.commit() 
    db.disconnect() 

Tôi không chắc chắn nhưng có lẽ bạn cũng có thể làm điều gì đó như

db.connection.commit() 

trong khi vòng lặp thay vì gọi chức năng mới được xác định

+0

cảm ơn RebBaron, đó chính là cách tôi đã thực hiện nó. –

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