forked from TimelordUK/node-sqlserver-v8
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtxn2.js
110 lines (92 loc) · 3.35 KB
/
txn2.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
const { TestEnv } = require('../../test/env/test-env')
const env = new TestEnv()
const connectionString = env.connectionString
console.log(`connectionString = ${connectionString}`)
const saString = env.getConnection('sa')
console.log(`saString = ${saString}`)
const table = '_customer2'
async function create () {
const theConnection = await env.sql.promises.open(connectionString)
const mgr = theConnection.tableMgr()
const res = await theConnection.promises.query('SELECT db_NAME() as [db]')
const db = res.first[0].db || 'node'
console.log(`db = ${db}`)
const builder = mgr.makeBuilder(table, db)
builder.addColumn('id').asInt().isIdentity(true, 1, 1).isPrimaryKey(1)
builder.addColumn('name').asVarChar(256)
builder.toTable()
console.log(builder.createTableSql)
console.log(builder.clusteredSql)
console.log(builder.nonClusteredSql)
await builder.drop()
await builder.create()
// await builder.index()
await theConnection.promises.close()
}
async function dbLocks (id, connection) {
const sql = `SELECT resource_type,
resource_database_id,
request_mode, request_status FROM sys.dm_tran_locks
WHERE resource_database_id = DB_ID()
AND resource_associated_entity_id = OBJECT_ID(N'${table}')`
const res = await connection.promises.query(sql)
const modes = res.first ? res.first.map(x => `${x.request_mode}.${x.resource_type}`) : []
console.log(`[${id}] modes = ${modes.join(', ')}`)
return res.first ? res.first?.length || 0 : 0
}
async function locks (id, saConnection) {
const lockCount = await dbLocks(id, saConnection)
console.log(`[${id}] lock count ${lockCount}`)
return lockCount
}
// with read uncomitted clause will run but dangerous dirty reads
// const isolation = 'SNAPSHOT'
// default this induces Bookmark lookup deadlock
const isolation = 'SNAPSHOT '
async function run (id, saConnection) {
const conn = await env.sql.promises.open(connectionString)
await conn.promises.query(`SET TRANSACTION ISOLATION LEVEL ${isolation}`)
iterate(id, conn, saConnection)
}
let counter = 0
async function iterate (id, conn, saConnection) {
console.log(`start [${id}] counter = ${counter}`)
try {
console.log(`[${id}] step 1`)
const modes = await locks(id, saConnection)
console.log(`[${id}] step 2 mode count ${modes}`)
const promises = conn.promises
console.log(`[${id}] step 3`)
await promises.query('BEGIN TRANSACTION')
console.log(`[${id}] step 4`)
await promises.query(`INSERT INTO ${table} (name) VALUES (?)`, ['foo'])
console.log(`[${id}] step 5`)
await locks(id, saConnection)
console.log(`[${id}] step 6`)
await promises.query(`select top 10 id, name from ${table} order by id DESC`)
console.log(`[${id}] step 7`)
await promises.query('COMMIT')
console.log(`[${id}] step 8`)
// get a row count
const total = await promises.query(`select count(*) as rc from ${table}`)
console.log(`[${id}] row count = ${total.first[0].rc}`)
await locks(id, saConnection)
} catch (e) {
console.log(`[${id}] error = ${e}`)
}
console.log(`done [${id}] counter = ${counter}`)
setTimeout(() => {
++counter
iterate(id, conn, saConnection)
}, 100)
}
async function runner () {
await create()
const saConnection = await env.sql.promises.open(saString)
for (let i = 0; i < 3; i++) {
run(i, saConnection)
}
}
runner().then(() => {
console.log('done')
})