2011-03-12 6 views
3

変数NUMBER_OF_ITERATIONSを1に設定すると、すべて正常に動作しますが、1より大きい値に変更すると問題が発生します。MySQLの奇妙な動作SELECT

まず、この場合、resの値を印刷すると、巨大な数値(18446744073709551615など)が表示されます。

第二に、最も重要な、価値のな長さは常に0であるため、この場合にはスクリプトがデータを処理することはできません...

if __name__ == '__main__': 

    NUMBER_OF_ITERATIONS = 2 

    conn = DBconnection() # return a database connection 

    for i in range(NUMBER_OF_ITERATIONS): 
     cursor = conn.cursor() 
     res = cursor.execute('SELECT field 
           FROM table 
           WHERE other_field = 0 
           LIMIT 10 LOCK IN SHARE MODE') 
     print '# of selected rows: ' + str(res) 

     values = [] 
     for elem in cursor.fetchall(): 
      if elem != None: 
       values.append(list(elem).pop()) 

     if len(values) != 0: 
      # do something... 

     else: 
      print 'NO VALUES AVAILABLE' 
      cursor.close() 
      break 

    conn.close() 
    print 'DONE' 

私はInnoDBストレージエンジンを使用して、同時に、この時ですスクリプトには、(LOAD DATA INFILEの構文を使用して)同じテーブルにデータをアップロードする別のスクリプトpythonがあります。

私はそれが負荷データによって引き起こされるテーブルロックに起因する可能性があると考えましたが、1から2(またはそれ以上)の反復との違いは何ですか? 1回の反復ではすべて正常に動作し、2回でも最初の反復は悪くなります。私はポイントを得ることができません。

答えて

2

次のコードを使用して問題を再現できませんでした。エラーを示すためにそれを変更できますか? 私はInnoDBストレージエンジンを使用していますし、同時に、このスクリプトでは上のデータをアップロードしている別のスクリプトのpythonがある:

import config 
import MySQLdb 
import multiprocessing as mp 
import random 
import string 
import time 

def random_string(n): 
    return ''.join(random.choice(string.letters) for _ in range(n)) 

def generate_data(): 
    conn=MySQLdb.connect(
     host=config.HOST,user=config.USER, 
     passwd=config.PASS,db='test')  
    cursor=conn.cursor() 
    while True: 
     with open('/tmp/test.dat','w') as f: 
      for _ in range(20): 
       f.write('{b}\n'.format(b=random_string(10))) 
     # sql='LOCK TABLES foo WRITE' 
     # cursor.execute(sql) 
     sql="LOAD DATA INFILE '/tmp/test.dat' INTO TABLE test.foo" 
     cursor.execute(sql) 
     conn.commit() 
     # sql='UNLOCK TABLES' 
     # cursor.execute(sql)   
     time.sleep(0.05) 

def setup_innodb(connection): 
    cursor=connection.cursor() 
    sql='DROP TABLE IF EXISTS foo' 
    cursor.execute(sql) 
    sql='''\ 
     CREATE TABLE `foo` (
      `bar` varchar(10) NOT NULL 
     ) ENGINE=InnoDB 
     ''' 
    cursor.execute(sql) 
    connection.commit() 

if __name__ == '__main__': 
    NUMBER_OF_ITERATIONS = 20 
    conn=MySQLdb.connect(
     host=config.HOST,user=config.USER, 
     passwd=config.PASS,db='test') 
    setup_innodb(conn) 

    # Start a process which is "simultaneously" calling LOAD DATA INFILE 
    proc=mp.Process(target=generate_data) 
    proc.daemon=True 
    proc.start() 

    for i in range(NUMBER_OF_ITERATIONS): 
     cursor = conn.cursor() 
     # sql='''SELECT field 
     #  FROM table 
     #  WHERE other_field = 0 
     #  LIMIT 10 LOCK IN SHARE MODE''' 
     # sql='LOCK TABLES foo READ' 
     # cursor.execute(sql) 
     sql='''SELECT * 
       FROM foo 
       LOCK IN SHARE MODE 
       ''' 
     res = cursor.execute(sql) 
     print '# of selected rows: ' + str(res) 
     values = cursor.fetchall() 
     # http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html 
     # Locks set by LOCK IN SHARE MODE and FOR UPDATE reads are released when 
     # the transaction is committed or rolled back. 
     conn.commit() 
     time.sleep(0.1) 

    conn.close() 
    print 'DONE' 

は、私は一つのことを忘れていたので、私は私の元の質問を編集し

# of selected rows: 0 
# of selected rows: 40 
# of selected rows: 80 
# of selected rows: 120 
# of selected rows: 160 
# of selected rows: 180 
# of selected rows: 220 
# of selected rows: 260 
# of selected rows: 300 
# of selected rows: 340 
# of selected rows: 360 
# of selected rows: 400 
# of selected rows: 440 
# of selected rows: 460 
# of selected rows: 500 
# of selected rows: 540 
# of selected rows: 580 
# of selected rows: 600 
# of selected rows: 640 
# of selected rows: 680 
DONE 
+0

を生成します同じテーブル(LOAD DATA INFILEの構文を使用)。 –

+0

サブプロセスで 'LOAD DATA INFILE'を実行するコードを追加しましたが、それでもエラーを再現できませんでした。問題を示す実行可能なスクリプトを投稿できますか? – unutbu

+0

ok、それは私が選択後にコミットするために行方不明だったようだ!しかし、数回の反復の後、私はこのエラーを受け取ります:Lock wait timeout exceeded;トランザクションを再開してみてください –