• Tidak ada hasil yang ditemukan

The run command is special as it is mandatory and that it always has support for parallel execution. Unlike other commands that are implemented in a single function (optionally invoking other functions), Sysbench uses three functions for the run command. The three functions that must always exist are

thread_init(): This is called when Sysbench initializes the script.

thread_done(): This is called when Sysbench is done executing the script.

event(): This is where the actual test is implemented and is called once per iteration.

For this example, the thread_init() function can be kept very simple:

-- Initialize the script

-- Initialize the global variables used in the rest of the script function thread_init()

-- Initialize the database driver and connections db = sysbench.sql.driver()

cnx = db:connect() end

For this simple test, all the initialization that is required is to create the connection to MySQL which consists of initializing the database driver and to use that to create the connection. The driver is available from the sysbench object. By creating the

connections in the thread_init() function, Sysbench can reuse the connections instead of creating a new connection for each iteration. If you want to simulate creating a new connection for each group of queries, you can also choose to do that by adding the code in the event() function and make the connection object local in the same way as it will be done later for the prepare and cleanup commands.

Similarly, the thread_done() function cleans up after the execution:

-- Clean up after the test function thread_done()

-- Close the connection to the database cnx:disconnect()

end

CHapter 3 BenCHmarking witH SySBenCH

All that is required in this case is to close the connection which is done using the disconnect() method of the connection.

The most interesting of the three required functions is the event() function which defines what is done when executing the test. The code for the example script can be seen in Listing 3-10.

Listing 3-10. The event() function -- Called for each iteration function event()

-- Check the --skip_trx option which determines -- whether explicit transactions are required.

if not sysbench.opt.skip_trx then cnx:query("BEGIN")

end

-- Execute the customer test do_increment()

-- If necessary, commit the transaction if not sysbench.opt.skip_trx then cnx:query("COMMIT")

end end

This code uses one option, the --skip_trx option. If --skip_trx is disabled, then the test relies on the auto-commit feature; otherwise, explicit BEGIN and COMMIT are executed.

Note in the Sysbench Lua scripts, you cannot use START TRANSACTION to begin a transaction.

In this case, the event() function does not actually perform any work itself. That is deferred to the do_increment() function to show how you can add extra functions to separate out the work like in other programs. The do_increment() function together with a couple of helper functions is shown in Listing 3-11.

47 Listing 3-11. The do_increment() and helper functions

-- Generate the table name from the table number function gen_table_name(table_num)

return string.format("sbtest%d", table_num) end

-- Generate the key from an id function gen_key(id)

return string.format("sbkey%d", id) end

-- Increment the counter and fetch the new value function do_increment()

-- Choose a random table and id

-- among the tables and rows available table_num = math.random(sysbench.opt.tables) table_name = gen_table_name(table_num) id = math.random(sysbench.opt.table_size) key = gen_key(id)

query = string.format([[

UPDATE %s

SET val = LAST_INSERT_ID(val+1) WHERE id = '%s']], table_name, key) cnx:query(query)

cnx:query("SELECT LAST_INSERT_ID()") end

The gen_table_name() function generates the table name based on an integer, and the gen_key() function similarly generates a key value based on an integer id. The table name and key value are used in a few other places in the script, so by splitting the logic into helper functions, you can ensure they are generated in the same way throughout the script.

The do_increment() function itself starts out generating the table name and key based on random values based on the number of tables and the number of rows in each table in the test. In a real application, you may not have such a uniform access to the sequences, in which case you can modify the logic in the script. Finally, the UPDATE and

CHapter 3 BenCHmarking witH SySBenCH

SELECT statements are executed. A possible extension of the script is to use the generated sequence number in some other query, but be careful that you do not end up doing work that is not relevant to what you are trying to benchmark.

That is all that is required for the run command. Notice that nothing was done to implement parallel execution; that is handled automatically by Sysbench unless you do not want to treat all threads the same. An example where the threads should not perform identical work is the prepare command where each thread will be responsible for its own tables.